python量化策略——移动平均波动率策略、稳定性策略

波动率策略简介

一个更简单的移动平均策略移动平均策略——单/双均线策略

————————————————————分——————————_————————

  1. 读取tushare pro财经数据,这里用到沪深300,以下程序都需注册此数据库并获得token码 才能运行,这里获取token码,若自己有数据,只需换掉数据部分即可。
  2. 数据预处理,计算沪深300的净值波动率,
  3. 策略细则:if 100天平均波动率大于最近20天的波动率 并且最近20天的波动率小于上一个20天波动率,则是做多信号
  4. 计算收益+统计

策略代码分解

  1. 所需的库
# coding=utf-8
import math
import tushare as ts
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import talib
import pandas as pd
from datetime import datetime, date
import seaborn as sns  
sns.set(style="darkgrid", palette="muted", color_codes=True) 
from scipy import stats,integrate
%matplotlib inline 
sns.set(color_codes=True)
matplotlib.rcParams['axes.unicode_minus']=False
plt.rcParams['font.sans-serif']=['SimHei']
  1. 读取数据,就是这里需要token码
ts.set_token('此处填入token码')
pro = ts.pro_api()
#读取数据的时间范围
star="20060602"
end="20200905"
df = pro.index_daily( ts_code='000300.SH', start_date=star, end_date=end)
df=df.sort_index(ascending=False)#排序
df.index=pd.to_datetime(df.trade_date,format='%Y-%m-%d')#设置日期序列索引
df_close=df.close/df.close[0]#计算净值

  1. 计算20天的波动率
df.trade_date=None
for i in range(20,len(df.index)):#计算20天的波动率
    df.trade_date[i]=np.std(np.log(df_close[i-20:i] /df_close[i-20:i].shift(-1)))*np.sqrt(252)*100#波动率计算
df1=df.trade_date.dropna()
df1

这里可以打印下数据结果:

trade_date
2006-06-30    28.0057
2006-07-03    27.7961
2006-07-04    28.5801
2006-07-05    18.6095
2006-07-06    19.4827
               ...   
2020-08-31    17.4778
2020-09-01    17.6335
2020-09-02    17.7192
2020-09-03    17.6655
2020-09-04    17.2246
Name: trade_date, Length: 3454, dtype: object
  1. 计算策略信号判断
t=20#一20天为时间段计算波动率
T=100#波动率移动平均时间段。
df1=pd.Series(df1,dtype=float)#转换类型
df2= talib.MA(pd.Series(  pd.Series(df.trade_date.dropna() ,dtype=np.float) ), timeperiod=T)
sig=pd.Series(0,df1.index)
for i in range(math.ceil(T/t), math.floor(len(df1)/t)-1):#信号判断
     if df1[i*t+t]<df2[i*t+t] and  df1[i*t]>df1[i*t+t]:#这里可以作为检验,即去掉if  查看波动
        for j in range(i*t+1,(i+1)*t+1):
            sig[j]=1
df_close=df_close.sort_index()
ret=(df_close-df_close.shift(1))/df_close.shift(1)
ret1=ret.tail(len(df1)).sort_index()*sig
cum=np.cumprod(ret1+1).dropna()
cum=cum.tail(len(cum)-T-2)#组合累计净值

  1. 比较基准函数 直接调用
def bj_standard(code,lab='沪深300指数',col='k'):#针对沪深股票,直接画出比较基准(收益情况)
    standard_base = pro.index_daily( ts_code=code, start_date=star, end_date=end)
    standard_base=standard_base.head(len( standard_base)-T-20)
    standard_base=standard_base.sort_index()
    standard_base.index=pd.to_datetime(standard_base.trade_date,format='%Y-%m-%d')#设置日期索引
    close_base= standard_base.close
    standard_ret=standard_base.change/standard_base.close.shift(-1)
    standard_sig=pd.Series(0,index=close_base.index) 
    standard_trade=standard_sig.shift(1).dropna()/100#shift(1)整体下移一行
    standard_SmaRet=standard_ret*standard_trade.dropna()
    standard_cum=np.cumprod(1+standard_ret[standard_SmaRet.index[0:]])-1
    plt.plot(close_base/close_base[-1],label=lab,color=col)
    return close_base/close_base[-1] #standard_cum
###########################################################################   
  1. 结果统计函数年化收益等。直接调用
def Tongji(cum):
    cum=cum.sort_index()
    NH=(cum[-1]-1)*100*252/len(cum.index)
    BD=np.std(np.log(cum/cum.shift(-1)))*np.sqrt(252)*100
    SR=(NH-4)/BD
    return_list=cum
    MHC=((np.maximum.accumulate(return_list) - return_list) / np.maximum.accumulate(return_list)).max()*100
    print("年化收益率:{:.2f}%:,年化夏普率:{:.2f},波动率为:{:.2f}%,最大回撤:{:.2f}%".format( NH,SR,BD,MHC))
Tongji(cum)
############################################################################
  1. 输出结果
if __name__=="__main__":
    bj_standard('000300.SH')
    plt.plot(cum,label="策略组合净值",color='r',linestyle='-')
    plt.title("策略净值走势图")
    plt.legend() 

结果为:

年化收益率:24.16%:,年化夏普率:1.51,波动率为:13.33%,最大回撤:42.28%

在这里插入图片描述
还是比较平稳的

  1. 再看下其他结果——参数t,T改变
    在这里插入图片描述

  2. 回测最近十年的结果
    在这里插入图片描述

  3. 用更长的数据+更大的参数变动
    在这里插入图片描述
    虽然图形没有前面好看,主要是07-08年的牛市没有完全抓住。但是但是但是,我们看看他们的年化率

年化收益率:27.35%:,年化夏普率:2.07,波动率为:11.29%,最大回撤:27.91%
年化收益率:11.97%:,年化夏普率:0.52,波动率为:15.24%,最大回撤:38.17%
年化收益率:28.02%:,年化夏普率:1.83,波动率为:13.11%,最大回撤:48.18%
年化收益率:20.00%:,年化夏普率:1.17,波动率为:13.72%,最大回撤:58.95%
年化收益率:28.97%:,年化夏普率:1.83,波动率为:13.65%,最大回撤:48.18%

这里就觉得还可以了吧。

13.为了说明结果的有效性,我们换种思路,将做多做空信号相反,我们看看他是怎么反向跑输的,而且是大概率输
先来最近五年的
在这里插入图片描述
再来2010-2015年的

在这里插入图片描述
大概率贴边,最后也是输面大

2005-2010
在这里插入图片描述
完败————————————

此外,使用商品期货市场指数再次来验证

在这里插入图片描述

有效

回测结果总结

不管市参数扰动,还是回测时间变动以下,其都有相对稳定的回报。
股市没有一直输的策略,同时也没有用远胜的策略,我们追求的不就是高概率胜码。
另外我也试过其他更广泛的区间,大概率正向比反向表现好,且正向超过基准的次数,远远超过负向。
但是以上都为考虑交易费用等成本,可将t延长,以此减少信号判断次数。
原有策略一年交易信号:0-13次。

其他量化
1.python量化——alpha股票-指数期货对冲策略
2.多因子选股策略
3.海龟交易策略
4.移动平均策略——单/双均线策略
5.改进的美林时钟(介绍)
6.改进的美林时钟策略(一)
7.改进的美林时钟策略(二)
8.改进的美林时钟策略(三)
9.F-F三因子(改进代码+结果)

完整代码

# coding=utf-8
import math
import tushare as ts
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import talib
import pandas as pd
from datetime import datetime, date
import seaborn as sns  
sns.set(style="darkgrid", palette="muted", color_codes=True) 
from scipy import stats,integrate
%matplotlib inline 
sns.set(color_codes=True)

matplotlib.rcParams['axes.unicode_minus']=False
plt.rcParams['font.sans-serif']=['SimHei']
ts.set_token('0a输入token码')#获取地址 https://tushare.pro/register?reg=385920
pro = ts.pro_api()
#读取数据
star="20040602"
end="20200905"
df = pro.index_daily( ts_code='000300.SH', start_date=star, end_date=end)
df=df.sort_index(ascending=False)
df.index=pd.to_datetime(df.trade_date,format='%Y-%m-%d')#设置日期索引
df_close=df.close/df.close[0]#计算净值

df.trade_date=None
for i in range(20,len(df.index)):#计算20天的波动率
    df.trade_date[i]=np.std(np.log(df_close[i-20:i] /df_close[i-20:i].shift(-1)))*np.sqrt(252)*100#波动率计算
df1=df.trade_date.dropna()
def CL_fun(t,T,df1=df1,df_close=df_close):
    df1=pd.Series(df1,dtype=float)
    df2= talib.MA(pd.Series(  pd.Series(df.trade_date.dropna() ,dtype=np.float) ), timeperiod=T)
    sig=pd.Series(0,df1.index)
    for i in range(math.ceil(T/t), math.floor(len(df1)/t)-1):
         if df1[i*t+t]>df2[i*t+t] and  df1[i*t]<df1[i*t+t]:#这里可以作为检验,即去掉if  查看波动
            for j in range(i*t+1,(i+1)*t+1):
                sig[j]=1
    df_close=df_close.sort_index()
    ret=(df_close-df_close.shift(1))/df_close.shift(1)
    ret1=ret.tail(len(df1)).sort_index()*sig
    cum=np.cumprod(ret1+1).dropna()
    cum=cum.tail(len(cum)-T-2)

    def bj_standard(code,lab='沪深300指数',col='k'):#针对沪深股票,直接画出比较基准(收益情况)
        standard_base = pro.index_daily( ts_code=code, start_date=star, end_date=end)
        standard_base=standard_base.head(len( standard_base)-T-20)
        standard_base=standard_base.sort_index()
        standard_base.index=pd.to_datetime(standard_base.trade_date,format='%Y-%m-%d')#设置日期索引
        close_base= standard_base.close
        standard_ret=standard_base.change/standard_base.close.shift(-1)
        standard_sig=pd.Series(0,index=close_base.index) 
        standard_trade=standard_sig.shift(1).dropna()/100#shift(1)整体下移一行
        standard_SmaRet=standard_ret*standard_trade.dropna()
        standard_cum=np.cumprod(1+standard_ret[standard_SmaRet.index[0:]])-1
        plt.plot(close_base/close_base[-1],label=lab,color=col)
        print( close_base/close_base[-1] )#standard_cum
###########################################################################   

    def Tongji(cum):
        cum=cum.sort_index()
        NH=(cum[-1]-1)*100*252/len(cum.index)
        BD=np.std(np.log(cum/cum.shift(-1)))*np.sqrt(252)*100
        SR=(NH-4)/BD
        return_list=cum
        MHC=((np.maximum.accumulate(return_list) - return_list) / np.maximum.accumulate(return_list)).max()*100
        print("年化收益率:{:.2f}%:,年化夏普率:{:.2f},波动率为:{:.2f}%,最大回撤:{:.2f}%".format( NH,SR,BD,MHC))

    return Tongji(cum),cum
if __name__=="__main__":
############################################################################
    plt.plot( CL_fun(10,100,)[1],label="t=10,T=100",color='r',linestyle='-')
    plt.plot( CL_fun(30,100,)[1],label="t=30,T=100",color='g',linestyle='-')
    plt.plot( CL_fun(20,110,)[1],label="t=20,T=110",color='b',linestyle='-')
    plt.plot( CL_fun(20,80,)[1],label="t=20,T=80",color='y',linestyle='-')
    plt.plot( CL_fun(20,130,)[1],label="t=20,T=130",color='m',linestyle='-')
    plt.title("2005-2010年 反向—移动波动率策略策略净值走势图 ")
    plt.legend()        

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小李、不姓李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值