用Python编写的第一个回测程序
2016-08-06
1 def savfig(figureObj, fn_prefix1=\'backtest8\', fn_prefix2=\'_1_\'): 2 import datetime 3 fmt= \'%Y_%m_%d_%H_%M_%S\' 4 now = datetime.datetime.now() 5 fname_savfig = fn_prefix1 + fn_prefix2 + now.strftime(fmt)+ \'.png\' 6 figureObj.savefig(fname_savfig, facecolor=fig.get_facecolor()) 7 8 9 def backtest8(ohlc=ohlc, SD=1.0, n_short=2, n_long=20, f_savfig=False): 10 u\'\'\' 11 双均线策略回测函数 12 signature: backtest8(ohlc=ohlc, SD=1.0, n_short=2, n_long=20, f_savfig=False) 13 param:: 14 ohlc - dohlcva 数据, dataFrame结构的 15 SD - MA1/MA2 > SD 触发多头买入的快均线/慢均线的阀值 16 f_savefig - flag for saving Matplot output figures 17 18 19 20 \'\'\' 21 import matplotlib 22 #import seaborn as sns 23 #sns.set_style(\'white\') 24 25 myfontprops = matplotlib.font_manager.FontProperties( 26 fname=\'C:/Windows/Fonts/msyh.ttf\')#微软雅黑 27 28 maShort = pd.Series.rolling(ohlc.C, n_short).mean() 29 maLong = pd.Series.rolling(ohlc.C, n_long).mean() 30 31 32 fig=plt.figure() # create new figure 33 ohlc.C.plot(grid=True, figsize=(8,4)) 34 maShort.plot(label=\'MA\'+str(n_short)) 35 maLong.plot(grid=True,label=\'MA\'+str(n_long)) 36 # ohlc.iloc[:,[0,1,2,3]].plot(grid=False, figsize=(8,4)) 37 # ohlc.iloc[:,[0,1,2,3]].plot(grid=True,figsize=(8,4)) 38 plt.legend(loc=\'best\') 39 plt.title( s=u\'历史股价\', fontproperties=myfontprops) 40 if f_savfig: 41 savfig(fig, \'backtest8\', \'_0_\') 42 43 # SD=1.0 44 regime = np.where( maShort/maLong > SD, 1, 0) 45 regime = pd.Series(regime, index=maShort.index) 46 print (\'Regime Length = %s\'%regime.size) 47 48 fig=plt.figure() # create new figure 49 regime[:].plot(lw=1.5, ylim=(-0.1, 1.1), figsize=(8,4), title=u\'Regime\') 50 if f_savfig: 51 savfig(fig, \'backtest8\', \'_1_\') 52 53 fig=plt.figure() # create new figure 54 regime[-100:].plot(lw=1.5, ylim=(-0.1, 1.1), figsize=(8,4), title=u\'Regime\') 55 if f_savfig: 56 savfig(fig, \'backtest8\', \'_2_\') 57 58 59 60 pp_ratio_bnh = np.log(ohlc.C / ohlc.C.shift(1) ) 61 pp_ratio_strategy = regime.shift(1) * pp_ratio_bnh 62 #最后我们把每天的收益率求和就得到了最后的累计收益率 63 #(这里因为我们使用的是指数收益率,所以将每日收益累加是合理的), 64 #这个累加的过程也可以通过DataFrame的内置函数cumsum轻松完成: 65 norm_return_bnh = pp_ratio_bnh .cumsum().apply(np.exp) 66 norm_return_strategy = pp_ratio_strategy.cumsum().apply(np.exp) 67 68 fig=plt.figure() # create a new figure 69 norm_return_strategy. plot(lw=1.5, figsize=(8,4), label=u\'Strategy\') 70 norm_return_bnh. plot(lw=1.5, label=u\'BnH\') 71 72 plt.legend(loc=\'best\') 73 plt.title(s=u\'策略收益率与历史价格对比\', fontproperties=myfontprops) 74 if f_savfig: 75 savfig(fig, \'backtest8\', \'_3_\') 76 77 assert (regime.index == ohlc.C.index).all()==True # \'signal index not equals price index\' 78 # assert用来判断语句的真假,如果为假的话将触发AssertionError错误, 为开发人员提示出错的表达式 79 return norm_return_strategy, n_short, n_long, SD
结果图: 有四张, 主要用于质量控制的目的.
1. 历史价格
2. 交易信号
3. 第2的子集, 放大后才能看清楚, 技术指标择时模型的细节(如何触发交易信号)
4. 策略的收益率
后续补充内容:
-
封装成类
- 添加绩效策略指标: 一大堆的东西
-
优化
- 完善绘图程序, 智能地选择输入(data_obj, param, **kwargs)