【手把手教你】基于均线排列的价格动量策略回测

01

引言

动量策略是通过利用市场波动从现有趋势的延续中获利。简单来说,高买高卖,反之亦然(“低买高卖”是均值回归策略思想,与动量策略相反)。价值投资通常基于均值的长期回归,而动量投资基于均值回归发生之前的时间间隔。通常而言,基于过去回报(价格动量策略)或收益意外(称为收益动量策略)的策略是利用市场对不同信息的反应不足。换句话说,收益动量策略是基于对短期收益相关信息的反应不足中获利,而价格动量策略是基于从市场对更广泛信息(包括长期盈利能力)的缓慢反应中获利。动量策略的构建有两种思路,一种是个股历史价格动量,即与过去价格相比计算涨跌幅,也叫时间动量;另一种是截面动量,即对当前市场所有个股进行某期间涨跌幅排序,如欧奈尔的RPS指标。下面以简单的均线为例,构建均线多头排列的时间动量进行历史回测。数据获取、可视化和回测均用到公众号开发的qstock包(免费),关于qstock的数据、可视化、选股等详细教程请参阅以下推文:

【qstock开源了】数据篇之行情交易数据

【qstock数据篇】行业概念板块与资金流

【qstock量化】数据篇之股票基本面数据

【qstock量化】数据篇之宏观指标和财经新闻文本

【qstock量化】动态交互数据可视化

【qstock量化】技术形态与概念热点选股池

【手把手教你】使用qstock实现量化策略选股

02

Python计算均线动量

使用汉明距离(scipy.spatial.distance)度量均线多头排列的动量趋势。汉明距离是信息论里的一个概念,它表示两个(相同长度)字符串对应位置的不同字符的数量。汉明距离对向量按元素进行比较,并对差异的数量进行平均,如果两个向量相同,得到的距离是0之间,如果两个向量完全不同,得到的距离是1。

import numpy as np
import pandas as pd
import scipy.stats as stats
from datetime import timedelta
import scipy.spatial.distance as distance
import matplotlib.pyplot as plt
import qstock as qs


使用qstock获取回测用数据,以中国平安为例,基准指数为沪深300指数,回测期间为2010-2022年。

#获取数据
#data_feed是qstock回测模块获取数据函数,默认基准指数为沪深300
#fqt=2表示后复权数据,等于1表示前复权
df=qs.data_feed('中国平安',index='hs300',start='20100101',end='202201216',fqt=2)
#计算10个均线序列
for i in np.linspace(10, 100, 10):
    df[str(i)+'日均线']=df['close'].rolling(window=int(i),center=False).mean()
df.dropna(inplace=True)

均线数据可视化。

#均线可视化
cols=['close']+[str(i)+'日均线' for i in np.linspace(10, 100, 10)]
qs.line(df['2020':][cols])

4b5d4273ce743ef795cc409042447dfa.jpeg


cols=[str(i)+'日均线' for i in np.linspace(10, 100, 10)]

for date in df.index:
    #围绕每一日的均线大小进行排序
    ranking = stats.rankdata(df.loc[date,cols].values)
    #计算每一日均线之间的汉明距离(scipy.spatial.distance)
    df.loc[date,'scores']= distance.hamming(ranking, range(1,11))

个股价格与均线汉明距离得分数据可视化。

#价格走势与均线排列的汉明距离得分可视化
df[['close','scores']].plot(figsize=(15,7),secondary_y='scores', alpha=0.6)
plt.show()

4a22c0427f41d5226bd4473850f0edd5.jpeg

#描述性统计
df[['close','scores']].describe()

4de708d6a544bf6b7af9e1ddcc2a80de.jpeg

03

动量回测

策略思路:当短期均线大于长期均线呈现多条均线的多头排列时,买入做多,当均线呈现空头排列时卖出。使用汉明距离可以度量均线的多头与空头排列得分,当出现完美的均线多头时(短期均线依次大于长期均线,如10日MA > 20日MA >… 100日MA),得分为1;当出现完美的空头时,即短期均线依次小于长期均线,如10日MA < 20日MA <… <100日MA)得为0,其他均线排列得分位于0-1之间。可以根据得分设定一个门槛值,如当scores得分大于0.5,给出买入或持有的信号,否则为卖出或做空信号。

#封装成函数方便后面进行回测分析
def ma_momentum(code,benchmark='hs300',start='20100101',end='202201219',ma_list=None,threshold=0.8):
    df=qs.data_feed(code,index=benchmark,start=start,end=end,fqt=2)
    ss=np.linspace(10, 100, 10) if ma_list is None else ma_list
    for i in ss:
        df[str(i)+'日均线']=df['close'].rolling(window=int(i),center=False).mean()
    df.dropna(inplace=True)
    cols=[str(i)+'日均线' for i in ss]
    for date in df.index:
        ranking = stats.rankdata(df.loc[date,cols].values)
        df.loc[date,'scores']= distance.hamming(ranking, range(1,len(ss)+1))
    #当日均线多头排列scores=1发出买入信号设置为1
    df.loc[df['scores']>threshold, 'signal'] = 1
    #当日均线空头排列scores=0发出买入信号设置为0
    df.loc[df['scores']<=threshold, 'signal'] = 0
    df['position']=df['signal'].shift(1)
    df['position'].fillna(method='ffill',inplace=True)
    d=df[df['position']==1].index[0]-timedelta(days=1)
    df1=df.loc[d:].copy()
    df1['position'][0]=0
    #当仓位为1时,买入持仓,当仓位为0时,空仓,计算资金净值
    df1['capital_ret']=df1.rets.values*df1['position'].values
    #计算策略累计收益率
    df1['capital_line']=(df1.capital_ret+1.0).cumprod()
    return df1
#可以通过ma_list自定义设置ma均线计算周期
#如ma_list=[3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
#ma_list=None表示默认使用10-100日均线
data=ma_momentum('中国平安',ma_list=None,threshold=0.8)

回测结果。

qs.start_backtest(data)

a70ed0650345417530b2e60591762725.jpeg

e5236facb3f34473bdcff7b43c164b20.jpeg

修改均线参数,同时以贵州茅台个股为例重新进行回测。

fib=[3, 5, 8, 13, 21, 34, 55, 89, 144, 233]
data=ma_momentum('贵州茅台',ma_list=fib,threshold=0.5)
qs.start_backtest(data)

1151b1aaa6ea20aeb16ce23cc3dfcd55.jpeg

f91813053db4f01fc424640d6dbbc324.jpeg

此外,介绍一个非常简单易上手的回测框架quantstats,下面使用它展示历史回测结果。注意quantstats要先使用"pip install QuantStats"进行安装,注意安装的时候包含大写字母,导入使用小写字母。quantstats与pyfolio类似,一行代码可以实现丰富的回测图表,下面只展示部分结果。如下面输入qst.reports.html(data.capital_ret),可以生成本地基于web的html回测结果。关于pyfolio的回测用法可以参照推文:《Pyfolio一行代码实现专业量化回测图表》

import quantstats as qst
qst.reports.full(data.capital_ret)

9cebbc217ca2a7d3cbf7429145e3fe6c.jpeg

20c5c08c69311610157d805cb9548e37.png

68c564c1382392d3d068adb469ec1849.png

e86228f40fc14edd95e88f15d47b3e06.png

bced559321749fb342bc51bd42049209.png

a5cc585dacfc631449aa22724d413128.png

3432593285d6600c93c4e680320066bf.png

04

结语

本文利用汉明距离计算均线排列的得分来评估股价的动量趋势,并以此构建择时交易策略,即当呈现多头均线排列的趋势时买入,空头排列时卖出。以中国平安和贵州茅台个股为例进行了历史回测,结果显示该交易策略优于买入持有和基准指数。

对于历史上证明有效的任何策略,通常有两种解释,该策略已经补偿了它所承担的额外风险,或者存在溢价行为因素。那为什么动量策略有效?动量策略起作用的逻辑在于,投资者表现出一长串行为偏见和情绪错误。然而,这说起来容易做起来难,因为趋势不会永远持续下去,并且在达到顶峰和结束时可能会迅速逆转。动量交易比大多数其他策略具有更高程度的波动性,并试图利用市场波动性。通过使用适当的风险管理技术和止损,正确安排买卖时间以避免损失非常重要。

最后为有意加入知识星球的新用户送上100张89元的优惠券,新用户或续费用户在加入前可先添加星主微信 “sky2blue2” 了解更多优惠信息。

abfe37c37ad65df80828eff99b175fba.png

8a07cf9cc15f9678fadd3ae1259d522b.png

关于Python金融量化

6d525ab32960cfdce0155c11dd7d22f7.png

专注于分享Python在金融量化领域的应用。加入知识星球,可以免费获取qstock源代码、30多g的量化投资视频资料、量化金融相关PDF资料、公众号文章Python完整源码、与博主直接交流、答疑解惑等。添加个人微信sky2blue2可获取相关优惠。

5889131e379abc23fcb4b06dfb982c39.jpeg

猜你喜欢

转载自blog.csdn.net/ndhtou222/article/details/128379464