问题描述
def print_position_info(context):
total_holding_return = 0
total_holding_cost = 0
省略了一段
historical_returns = context.portfolio.portfolio_value - context.portfolio.starting_cash
historical_return_rate = (historical_returns / context.portfolio.starting_cash) * 100
total_return = total_holding_return + historical_returns
total_cost = total_holding_cost + context.portfolio.starting_cash
total_return_rate = (total_return / total_cost) * 100 if total_cost != 0 else 0
overall_return_rate = (total_return / context.portfolio.starting_cash) * 100
print('累计收益={:.2f}, 累计收益率={:.2f}%'.format(total_return, overall_return_rate))
正确的写法应该是什么?
解决方案
您好!您在日志中输出的累计收益与聚宽官方计算不一致,主要是因为重复计算了持仓收益。
错误原因分析
在您的代码中:
historical_returns = context.portfolio.portfolio_value - context.portfolio.starting_cash
context.portfolio.portfolio_value(在最新 API 中推荐使用 total_value)代表的是总资产,它已经包含了您当前账户的可用现金以及所有持仓标的的当前总价值。也就是说,持仓的浮动盈亏(total_holding_return)已经体现在 portfolio_value 中了。
随后您又执行了:
total_return = total_holding_return + historical_returns
这导致持仓的浮动盈亏被加了两次,因此您计算出的累计收益会偏大(或在亏损时偏小),从而与聚宽官方的收益曲线不一致。
正确的写法
在 JoinQuant 平台中,context.portfolio 对象已经为您提供了非常便捷的属性来直接获取这些数据,无需手动累加持仓收益。考虑到策略运行过程中可能会有出入金(inout_cash),最严谨且与官方一致的计算方式如下:
def print_position_info(context):
# 获取总资产 (包含现金和持仓总价值)
total_value = context.portfolio.total_value
# 获取累计出入金 (初始资金 + 后续转入 - 后续转出)
inout_cash = context.portfolio.inout_cash
# 计算累计收益绝对值
total_return = total_value - inout_cash
# 获取累计收益率 (聚宽已直接提供该属性,值为小数,需乘以100转为百分比)
overall_return_rate = context.portfolio.returns * 100
# 打印结果
print('累计收益={:.2f}, 累计收益率={:.2f}%'.format(total_return, overall_return_rate))
相关 API 属性说明
context.portfolio.total_value:总权益(总资产),包括现金、保证金或者仓位的总价值,用来计算收益。context.portfolio.inout_cash:累计出入金。比如初始资金 10000,后来没有出入金,则这个值就是 10000。context.portfolio.returns:总权益的累计收益率。计算公式相当于(total_value / inout_cash) - 1。- 注:
context.portfolio.portfolio_value和context.portfolio.starting_cash在新版 API 中已标记为过时,建议使用total_value和inout_cash代替。