事件回测的最大好处是基本上可以避免未来函数的出现。
代码如下:
# -*- coding: utf-8 -*- from __future__ import division # %matplotlib inline import tushare as ts import pandas as pd import numpy as np data = ts.get_hist_data("510050",start="2017-01-01",end="2017-09-08") data = data.sort_values("date") df = pd.DataFrame() df['close'] = data['close'] df['change'] = df['close']- df['close'].shift(1) df = df.dropna() #将带有Na的去掉,返回一个新的对像 close5_array = np.zeros(5) #缓存过去5天收盘价 close20_array = np.zeros(20) last_signal = 0 #最近交易信号,初始化为0。因为双均线策略要使用前一天的收盘价,就需要将信号缓存下来,第2天计算仓位的时候使用 last_pos = 0 #最近的持仓,初始化为0 dr_list = [] #每日盈亏结果列表 class DailyResult: """每日盈亏结果""" def _init__(self): self.date = '' self.close = 0 self.change = 0 self.pos = 0 self.last_pos = 0 #昨日持仓 self.pnl = 0 self.fee = 0 self.net_pnl = 0 def calculate(self,date,close,change, last_signal, last_pos): """计算每日盈亏""" #赋值原始数据 self.date = date self.close = close self.change = change self.pos = last_signal self.last_pos = last_pos #计算结果数据 self.pnl = self.change * self.pos self.fee = abs(self.pos-self.last_pos) * 1.5/10000 self.net_pnl = self.pnl - self.fee #运行回溯 #iterrows生成迭代器,enumerate在迭代过程中返回当前的变量的计数情况。df刚好有date, close, change三列。叠代过程中会以tuple的形式返回每一行,其中的第一个元素是日期,第二个元素是数值段。 for i, row in enumerate(df.iterrows()): date = row[0] close =row[1]['close'] change = row[1]['change'] #将数组中的数据平移一格 close5_array[0:4] = close5_array[1:5] close20_array[0:19] = close20_array[1:20] #将新数据添加到数组末尾 close5_array[-1] = close close20_array[-1] = close #如果尚未有20个数据点的缓存数量,则不执行后续逻辑 if i < 20: continue #计算当日持仓盈亏 dr = DailyResult() dr.calculate(date, close, change, last_signal,last_pos) dr_list.append(dr) #记录当日持仓 last_pos = dr.pos #计算信号数据 ma5 = close5_array.mean() ma20 = close20_array.mean() if ma5 > ma20: last_signal = 10000 else: last_signal = -10000 #显示回测结果 result_df = pd.DataFrame() result_df['net_pnl'] = [dr.net_pnl for dr in dr_list] #将dailyresult列表中的数据转换为pandas的dataframe result_df.index = [dr.date for dr in dr_list] #添加日期索引 result_df['cum_pnl'] = result_df['net_pnl'].cumsum() #累积求和 result_df['cum_pnl'].plot()
在jupyter运行结果如下: