在这一讲中我们将会对一个非常简单的策略回测实例进行讲解,让大家对简单的回测框架有一个最直观的认识。
在这里选用了一个均线策略,该策略属于趋势策略,即通过技术指标的状态改变来捕获开仓或平仓信号。均线策略采用的是技术指标MA( Moving Average),关于它的详细解释可以参看:https://en.wikipedia.org/wiki/Moving_average
该策略的逻辑是:选取两条周期不同的MA曲线,一条为周期比较短的SMA,另一条则是周期比较长的LMA,如果SMA上穿LMA说明未来短期有向上趋势因此作为买入信号,反之作为卖出信号。信号产生规则用表达式写出来就是:
if sma(t)>lma(t)&sma(t-1)<lma(t-1) then signal=1(buy)
if sma(t)<lma(t)&sma(t-1)>lma(t-1) then signal=-1(sell)
else signal=0(hold)
策略模块
在策略模块中我们需要解决的是信号的识别,因此输入是bars,输出是信号。在该模块中提供了两个方法,一个是计算MA指标,另一个是根据策略规则产生信号。
MA指标的可以采用Pandas中的rolling_mean进行计算,参数window可设置移动窗口的大小,min_periods可确定需要有值的最小观测数,如果把min_peridos设置为1那么在ma序列中就不会出现NA的数据。关于该方法的其他参数可以参见Pandas的文档pandas.pydata.org/ 。
def MA(self, price, windows = 5, period = 1):
MAprice = pd.rolling_mean(price, windows, period)
return MAprice
信号生成方法是策略模块中最为核心的部分。对于该均线策略,我们信号产生的算法是通过flag来标示T=t时sma是否大于lma,然后对flag做差分。如果flag(t)=1 & flag(t-1)=0 ,那么signal(t)=flag(t)-flag(t-1)=1,即产生了买入信号。
def gen_signal(self):
signals = pd.DataFrame(index=self.bars.index)
signals['flag'] = 0
signals['sma'] = self.MA(self.bars['close'],self.short_window,1)
signals['lma'] = self.MA(self.bars['close'],self.long_window,1)
signals['flag'][self.short_window:] = np.where(signals['sma'][self.short_window:]
> signals['lma'][self.short_window:], 1, 0)
signals['signal'] = signals['flag'].diff().fillna(signals['flag'][0])
return signals
交易模块
策略模块将信号输入到交易模块中,交易模块提供了两个方法。第一个方法是通过信号产生各期买卖的头寸以及持有的头寸,第二个方法是追踪各期的资产情况,如持有头寸的市值、账户剩余的现金以及账户的总资产价值。
def gen_positions(self):
positions = self.signals['flag']*1000
return positions
def trade_positions(self):
positions = self.signals['signal']*1000
return positions
def trade_tracing(self):
capital = pd.DataFrame(index=self.signals.index)
capital['hold'] = self.gen_positions()*self.bars['close']
capital['rest'] = self.init_capital- (self.trade_positions()*bars['close']).cumsum()
capital['total'] = capital['hold']+capital['rest']
capital['return'] = capital['total'].pct_change().fillna(capital['total'][0]/self.init_capital-1)
return capital
我们可以选取一只股票采用上述简单回测框架进行回测。
if __name__ == '__main__':
bars = ts.get_h_data('002337',start='2012-01-01',end='2015-01-01').sort_index()
test_strategy = MAStrategy(bars)
signals = test_strategy.gen_signal()
test_trade = MATrade(bars,signals)
capital = test_trade.trade_tracing()
注意到该回测框架是一个最简单的策略回测系统,没有考虑各种交易成本,策略也进行了最简化的处理,选取该简单策略进行回测的目的是告诉大家回测系统建立的最基本要素和套路。最后,留下两个小问题留给大家思考:
1、该回测框架是针对单一交易品种进行的,如果对一个投资组合进行回测代码应该如何修改?
2、如果我们希望将所有股票都采用该策略一次性进行回测应该怎么做?
完整代码请关注我的微信公众号:我的微信公众号:会掘金的小鹿(NuggetsRoad)
是时候关注一波了!