风险提示:本内容为量化技术及平台操作的纯知识分享,不构成任何投资建议,不推荐任何具体证券或交易时机。部分内容可能理解包含错误,请自行核实。市场有风险,投资需谨慎文章全部内容设计到的标的,只做策略思路的分析,不做投资参考,
昨天我们详细的介绍一下动量策略的思路1000个量化策略--1全球大类动量策略
发现动量核心在策略的低相关性和参数的周期选择

周期可以分位长,中短,我取了不同的周期执行了回测,发现了下面的规律

第一步远程执行全部参数的回测,5个时间为一个周期分析

from xg_quant_backtrader_data import xg_quant_backtrader_data
import pandas as pd
import numpy as np
import time
models=xg_quant_backtrader_data(
url= "124.220.32.224",
port= 8888,
user= "小果",
password="小果",
auth_code="小果")
data=pd.DataFrame()
for n in range(5, 121, 5):
#远程服务器执行策略回测
print(n,'************************')
result=models.xg_mom_backtrader(
start_date= '20250101',
end_date = '20500101',
stock_list= '',
index_stock= '000300.SH',
cash = 100000,
comm= 0.0001,
mom_type= '百分比',
mom_value= 1,
mom_daily=n,
min_mom= 0,
max_mom= 5,
buy_rank= 1,
sell_zdf= 0.03,
sell_amount= 1000)
result=result['绩效']
df=pd.DataFrame()
for keys,value in result.items():
df[keys]=[value]
print(df)
data=pd.concat([data,df],ignore_index=True)
'''
#同步发布到个人模拟盘
result=models.xg_mom_backtrader_moni(
st_name= '小果动量{}日动量'.format(n),
open_show= '是',
start_date= '20250101',
end_date= '20500101',
stock_list= '159915.SZ,513100.SH,518880.SH',
index_stock= '000300.SH',
cash= 100000,
comm = 0.0001,
mom_type = '百分比',
mom_value = 1,
mom_daily = n,
min_mom = 0,
max_mom = 5,
buy_rank= 1,
sell_zdf= 0.03,
sell_amount= 1000)
print(result)
#同步发布到个人社区仿真交易模拟盘
result=models.xg_mom_backtrader_moni_sq(
st_name= '小果动量{}日动量'.format(n),
open_show= '是',
start_date= '20250101',
end_date= '20500101',
stock_list= '159915.SZ,513100.SH,518880.SH',
index_stock= '000300.SH',
cash= 100000,
comm = 0.0001,
mom_type = '百分比',
mom_value = 1,
mom_daily = n,
min_mom = 0,
max_mom = 5,
buy_rank= 1,
sell_zdf= 0.03,
sell_amount= 1000)
print(result)
'''
data.to_excel(r'动量分析.xlsx')
得到的数据结果

对数据继续统计分析,先导入数据

先总体看看动量周期和收益的相关性,总体是负相关


动量周期和回测,先小后大,最好基本钝化,时间周期大于100,基本就不变

动量和夏普比率,先大后小,梯度下降

波动率分析

先详细的回归分析数据结果
#详细的相关性分析
import pandas as pd
import statsmodels.api as sm
# 1. 定义自变量 (X) 和因变量 (y)
X = df['mom_daily'] # 自变量
y = df['total_return'] # 因变量
# 2. 添加截距项(常数项),statsmodels 默认不包含截距
X_with_const = sm.add_constant(X)
# 3. 拟合 OLS (普通最小二乘) 回归模型
model = sm.OLS(y, X_with_const)
results = model.fit()
# 4. 打印完整的结果摘要
print(results.summary())

详细的相关性分析图,负相关性趋势
import statsmodels.api as sm
import matplotlib.pyplot as plt
# 使用 statsmodels 的 plot_regress_exog 生成 4 合 1 诊断图
fig = plt.figure(figsize=(12, 10))
fig = sm.graphics.plot_regress_exog(results, 'mom_daily', fig=fig)
plt.tight_layout()
plt.show()

残差分析图
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
def plot_regression_**ysis(results, x_name='X', y_name='Y'):
"""
一键生成一元线性回归的所有诊断图
"""
fig = plt.figure(figsize=(16, 12))
# 1. 散点图 + 回归线 + 置信区间
ax1 = plt.subplot(3, 3, 1)
ax1.scatter(results.model.exog[:, 1], results.model.endog, alpha=0.5)
ax1.plot(results.model.exog[:, 1], results.fittedvalues, 'r-', linewidth=2)
ax1.set_xlabel(x_name)
ax1.set_ylabel(y_name)
ax1.set_title(f'回归拟合图 (R²={results.rsquared:.3f})')
ax1.grid(True, alpha=0.3)
# 2. 残差 vs 拟合值
ax2 = plt.subplot(3, 3, 2)
ax2.scatter(results.fittedvalues, results.resid, alpha=0.5)
ax2.axhline(y=0, color='r', linestyle='--')
ax2.set_xlabel('拟合值')
ax2.set_ylabel('残差')
ax2.set_title('残差 vs 拟合值')
ax2.grid(True, alpha=0.3)
# 3. Q-Q 图
ax3 = plt.subplot(3, 3, 3)
sm.qqplot(results.resid, line='s', ax=ax3)
ax3.set_title('Q-Q 图')
ax3.grid(True, alpha=0.3)
# 4. 残差直方图
ax4 = plt.subplot(3, 3, 4)
ax4.hist(results.resid, bins=15, density=True, alpha=0.6, edgecolor='black')
from scipy.stats import norm
x = np.linspace(results.resid.min(), results.resid.max(), 100)
ax4.plot(x, norm.pdf(x, results.resid.mean(), results.resid.std()), 'r-', linewidth=2)
ax4.set_xlabel('残差')
ax4.set_ylabel('密度')
ax4.set_title('残差分布')
ax4.grid(True, alpha=0.3)
# 5. 残差 vs 自变量
ax5 = plt.subplot(3, 3, 5)
ax5.scatter(results.model.exog[:, 1], results.resid, alpha=0.5)
ax5.axhline(y=0, color='r', linestyle='--')
ax5.set_xlabel(x_name)
ax5.set_ylabel('残差')
ax5.set_title('残差 vs 自变量')
ax5.grid(True, alpha=0.3)
# 6. Cook's Distance
ax6 = plt.subplot(3, 3, 6)
influence = results.get_influence()
cooks_d = influence.cooks_distance[0]
ax6.stem(range(len(cooks_d)), cooks_d, basefmt=" ")
ax6.axhline(y=4/len(cooks_d), color='r', linestyle='--')
ax6.set_xlabel('观测值索引')
ax6.set_ylabel("Cook's Distance")
ax6.set_title('影响点诊断')
ax6.grid(True, alpha=0.3)
# 7. 预测区间图
ax7 = plt.subplot(3, 3, 7)
from statsmodels.sandbox.regression.predstd import wls_prediction_std
prstd, iv_l, iv_u = wls_prediction_std(results)
ax7.scatter(results.model.exog[:, 1], results.model.endog, alpha=0.5)
ax7.plot(results.model.exog[:, 1], results.fittedvalues, 'r-', linewidth=2)
ax7.fill_between(results.model.exog[:, 1], iv_l, iv_u, alpha=0.2, color='r')
ax7.set_xlabel(x_name)
ax7.set_ylabel(y_name)
ax7.set_title('95%预测区间')
ax7.grid(True, alpha=0.3)
plt.suptitle('一元线性回归完整诊断图', fontsize=16)
plt.tight_layout()
plt.show()
# 使用示例
np.random.seed(42)
df = pd.DataFrame({
'mom_daily': np.random.normal(0, 0.1, 50),
'total_return': np.random.normal(0.05, 0.02, 50)
})
df['total_return'] = df['total_return'] + 0.5 * df['mom_daily']
X = df['mom_daily']
y = df['total_return']
X_with_const = sm.add_constant(X)
results = sm.OLS(y, X_with_const).fit()
# 一键生成所有图
plot_regression_**ysis(results, x_name='mom_daily', y_name='total_return')
import seaborn as sns
import matplotlib.pyplot as plt
import statsmodels.api as sm
import warnings
import pandas as pd
import numpy as np
# ==================== 1. 关闭警告 ====================
warnings.filterwarnings('ignore')
# ==================== 2. 设置中文字体(关键!)====================
# 先设置 matplotlib
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
# 再设置 seaborn(重要!)
sns.set_style("whitegrid")
sns.set_context("notebook")
# 关键:通过 rc 参数强制 seaborn 使用中文字体
sns.set(font='SimHei', font_scale=1.2) # 或者用 'Microsoft YaHei'
# ==================== 3. 创建示例数据 ====================
np.random.seed(42)
df = pd.DataFrame({
'mom_daily': np.random.normal(0, 0.1, 50),
'total_return': np.random.normal(0.05, 0.02, 50)
})
df['total_return'] = df['total_return'] + 0.5 * df['mom_daily']
# ==================== 4. 绘图 ====================
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
# 图1: regplot
sns.regplot(data=df, x='mom_daily', y='total_return', ax=axes[0],
scatter_kws={'alpha':0.5}, line_kws={'color':'red'})
axes[0].set_title('散点图与回归线', fontsize=14)
axes[0].set_xlabel('mom_daily', fontsize=12)
axes[0].set_ylabel('total_return', fontsize=12)
# 图2: residplot
sns.residplot(data=df, x='mom_daily', y='total_return', ax=axes[1],
scatter_kws={'alpha':0.5})
axes[1].axhline(y=0, color='red', linestyle='--')
axes[1].set_title('残差图', fontsize=14)
axes[1].set_xlabel('mom_daily', fontsize=12)
axes[1].set_ylabel('残差', fontsize=12)
# 图3: jointplot
g = sns.jointplot(data=df, x='mom_daily', y='total_return', kind='reg',
height=5, ratio=5)
# jointplot 需要单独设置标题
g.fig.suptitle('联合分布与回归线', y=1.02, fontsize=14)
g.ax_joint.set_xlabel('mom_daily', fontsize=12)
g.ax_joint.set_ylabel('total_return', fontsize=12)
plt.tight_layout()
plt.show()


不懂的问我就可以,加我备注入群可以加入专业量化群

可以找我开户专业量化支持

[#动量策略]() [#规律发现]() [#策略回测]() [#策略研究]() [#数据分析]() [#交易研究]()
动量天数对策略表现的影响规律及原因分析
一、收益随动量天数增加先升后降
规律: 收益随动量天数延长先快速攀升,到达顶峰后断崖式下跌,之后虽有短暂反弹但整体震荡下行,长期处于低迷状态。
原因:上升阶段:动量天数过短时,信号受日内噪声和随机波动干扰严重,频繁出现虚假突破,交易方向不稳定,收益无法有效累积。随着动量天数延长到合理区间,信号过滤掉了短期噪音,捕捉到的趋势更接近真实市场方向,趋势跟踪有效性显著提升。
下跌阶段:动量天数过长后,指标对价格变化反应迟钝,入场和出场严重滞后。当趋势已逆转时,动量信号仍指示原方向,策略在行情拐点处承受最大亏损,这种滞后效应一旦突破阈值,收益会迅速恶化。
长期低迷:极长周期动量信号完全钝化,几乎不再对市场变化做出有效响应,在震荡市中反复被收割,在趋势市中因反应太慢吃不到完整波段,策略失去择时能力。
二、最大回撤随动量天数增加先降后升
规律: 最大回撤随动量天数增加先不断改善至最低点,随后急剧放大,且放大后长期维持在高位不再收敛。
原因:改善阶段:动量周期过短时频繁开平仓,震荡中反复止损,小亏损频繁叠加出较大回撤。周期适当延长后交易频率下降,无效止损减少,单笔交易有更充足空间让利润奔跑,回撤自然收窄。
恶化阶段:动量周期过长后信号严重滞后,策略往往在市场顶部做多、底部做空。一旦市场快速反转,策略无法及时止损,单次错误的方向性暴露造成巨大亏损,最大回撤被瞬间拉大,回撤结构从"小亏频繁"变成"大亏偶尔"。
无法修复:信号钝化后策略失去主动管理风险的能力,每一次大的市场波动都可能造成不可逆的净值损失,且因反应太慢,回撤后无法通过后续交易快速收复失地。
三、风险调整后收益(夏普/索提诺/卡玛)与收益同步先升后降,且恶化更快
规律: 夏普、索提诺、卡玛均呈现先升后降的倒U型趋势,峰值与收益峰值重叠,但越过最佳区间后这些指标下降的斜率比收益本身更陡。
原因:
上升阶段:收益快速增加的同时,回撤和波动率都在下降,分子上升、分母下降,风险调整指标自然同步快速走高。
恶化更快:越过甜区后收益开始下降,但回撤和波动率却在加速上升,分子减小、分母增大,形成双杀效应。索提诺尤其敏感是因为它只关注下行波动,而长周期动量恰恰在下行风险上暴露最大;卡玛恶化最快是因为回撤的急剧扩大直接放大了分母,导致该指标率先崩塌。
四、胜率随动量天数变化不明显
规律: 胜率在各动量周期下整体窄幅波动,与动量天数无明确的单调关系。
原因: 动量策略本质上靠的是"大赚小亏"而非高胜率取胜。胜率主要由市场本身的趋势-震荡比例决定,动量天数调整的是每次盈亏的幅度结构而非方向判断的准确率。因此胜率在各周期下差异不大,始终在随机水平附近小幅波动。
五、波动率随动量天数增加先降后升
规律: 波动率随动量天数增加先减小至最低点,随后逐步放大,后期维持在高位震荡。
原因:下降阶段:短周期频繁交易加上噪声干扰,日间收益率起伏剧烈;周期延长后有效过滤了噪音,交易频率适中,净值曲线最为平滑。
上升阶段:信号钝化后策略与市场走势经常出现方向错配,净值要么长期不涨、要么集中性大跌,这种不规则的净值变动推高了整体波动率。同时长周期下交易次数极少,少数几次大盈亏对波动率的贡献极大,无法通过多次交易来平滑。
六、综合规律:策略存在明显的"甜区"效应
规律: 动量周期从短到长,策略表现呈现清晰的"甜区"结构——短周期未达最优,中短周期各项指标同时达到最佳平衡,中长周期策略有效性急剧衰减,长周期进入完全钝化状态。
原因: 这是动量因子"信号-噪声比"随周期先升后降的必然结果。动量周期过短时噪声主导,过长时滞后效应主导。滞后效应在周期过长时会指数级放大尾部风险,而市场本身的趋势持续时间有限,一旦动量窗口超过市场主流趋势的平均长度,信号中包含的更多是噪声和反转信息而非有效趋势信息,导致策略从"跟踪趋势"变成"追逐已结束的趋势"。这是所有趋势跟踪策略共同的底层约束