用Python编写的第一个回测程序

用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. 策略的收益率

后续补充内容:


  1. 封装成类

  2. 添加绩效策略指标: 一大堆的东西
  3. 优化

  4. 完善绘图程序, 智能地选择输入(data_obj, param, **kwargs)

用Python编写的第一个回测程序

用Python编写的第一个回测程序

用Python编写的第一个回测程序

用Python编写的第一个回测程序