楼主: 九十久
198 0

[程序化交易] 自研股票策略回测框架——绩效指标计算 [推广有奖]

  • 0关注
  • 0粉丝

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2023-8-2
最后登录
2023-8-2

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

[color=rgba(0, 0, 0, 0.9)]前面文章[color=var(--weui-LINK)]自研股票策略回测框架分享我们分享了一个股票日频策略的回测框架,本文我们继续完善这个框架,并对绩效指标这个模块展开说明一下。

[color=rgba(0, 0, 0, 0.9)]回测引擎调用策略函数后,会得到一个目标持仓矩阵,每一行是一个交易日,每一列的一只股票,可表示策略每一天目标要持有的标的及权重。如下图:

[color=rgba(0, 0, 0, 0.9)]

[color=rgba(0, 0, 0, 0.9)]目标持仓矩阵进入到清算模块,分别计算开仓,平仓,持仓三种情况的收益率,并扣除手续费,就得到最终策略的收益率序列。

[color=rgba(0, 0, 0, 0.9)]

[color=rgba(0, 0, 0, 0.9)]收益率序列进入绩效分析模块,会逐年计算各项绩效指标,并计算所有交易日总体绩效指标。这个模块的代码如下:

def compute_report(self):
    self.report = pd.DataFrame(
        columns=['tradeDays', 'totalRtn', 'YearlyRtn', 'YearlyVol', 'Maxdd', 'Sharp', 'Calmar',
                 'indexRtn', 'totalRtn_excess', 'yearlyRtn_excess', 'yearlyVol_excess', 'maxDD_excess', 'sharp_excess',
                 'calmar_excess', 'Turnover'])

    pnl_year = self.pnl.resample('A').sum()

    self.index_pnl = self.data_obj.index_daily['pct_chg']

    for y in pnl_year.index:
        self.report.loc[str(y.year), :] = self.computeIndicator(self.pnl[str(y.year)], self.index_pnl[str(y.year)], np.array(self.turnover[str(y.year)]))
    self.report.loc['Total', :] = self.computeIndicator(self.pnl, self.index_pnl, np.array(self.turnover))
    self.hold_num = self.positionDF.apply(np.sign).sum(axis=1)
    self.hold_pct = self.positionDF.sum(axis=1)
    self.nav = (self.pnl + 1).cumprod()
    self.index_nav = (self.index_pnl + 1).cumprod()
    self.excess_nav = (self.pnl - self.index_pnl + 1).cumprod()

[color=rgba(0, 0, 0, 0.9)]最终得到分年度及汇总绩效报告如下:

[color=rgba(0, 0, 0, 0.9)]

[color=rgba(0, 0, 0, 0.9)]下面分别展示主要指标的计算:

[color=rgba(0, 0, 0, 0.9)]通过策略的日收益率序列,可以得到交易天数(tradeDays),总收益率(totalRtn, 复利),年化收益率(yearlyRtn, 以每年240个交易日折算),年化波动率(yearlyVol)

tradeDays = dailyPnl.shape[0]
totalRtn = (dailyPnl + 1).cumprod()[-1] - 1
yearlyRtn = np.power(1 + totalRtn, 240.0 / tradeDays) - 1
yearlyVol = dailyPnl.std() * np.sqrt(240)

[color=rgba(0, 0, 0, 0.9)]最大回撤的计算,先得到策略净值曲线,定位到回撤的起止点下标,然后计算得到最高点到回撤最低点的回撤幅度(maxDD)。

nav = (dailyPnl + 1).cumprod()
tmpnav = np.maximum.accumulate(nav) - nav
idx_e = tmpnav.idxmax()
idx_s = nav[:idx_e].idxmax()
maxDD = -(nav[idx_e] - nav[idx_s]) / nav[idx_s]

[color=rgba(0, 0, 0, 0.9)]夏普(sharp)和卡玛(calmar)的计算,这里夏普没有减无风险利率rf,可以自行设置。

sharp = yearlyRtn / yearlyVol
calmar = yearlyRtn / maxDD

[color=rgba(0, 0, 0, 0.9)]基于基准指数的日收益率数据,得到日超额收益率序列,并计算各项超额指标。

indexRtn = (pnl_index + 1).cumprod()[-1] - 1
excessDaily = dailyPnl - pnl_index
excessDaily.fillna(0,inplace=True)
totalRtn_excess = (excessDaily + 1).cumprod()[-1] - 1
yearlyRtn_excess =  np.power(1 + totalRtn_excess, 240.0 / tradeDays) - 1
yearlyVol_excess = excessDaily.std() * np.sqrt(240)

[color=rgba(0, 0, 0, 0.9)]再有就是用换手率,手续费数据进行统计汇总。





[color=rgba(0, 0, 0, 0.9)]至此就是一个相对完整的股日频策略的回测框架了,大家可以下载源码,逐个模块进行分析,并根据自己的需要进行调整。

我们已经将本文用到的全部源数据+源代码+Python环境打包好了,做到开箱即用,一键运行,自己多动手才是学习的最佳途径。

感兴趣的朋友请关注公众号,添加下面微信获取(微信号:jsj99_01)。



二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:策略回测 指标计算 绩效指标 Indicator Dataframe 量化投资 量化分析

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jr
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-5-3 01:41