跳到正文

研究指南

股票回测与实验

股票回测最后一天收益为何变了:核对强制平仓与末期费用

股票回测最后一条权益,可能在正常快照生成之后又因期末结算改变。持仓先按标记价估值、显示未实现损益,强制清算再应用退出价、滑点和费用,最后留下现金。报告末值应服从声明的结算口径,不能意外保留尚未扣退出成本的旧标记,更不能把费用从两个地方重复扣除。

本文用一个合成股票多头重建完整桥。本地参考引擎静态代码先以end_of_backtest关闭仓位,再替换最后快照;下面独立标准库程序没有运行参考引擎。CoTrading对应报告、市场资格和真实执行能力仍为规划或待核实,不能把本地会计夹具升级为产品或券商成交证据。

先区分三种结束状态

仅估值报告保留股票、现金及明确价格标记;策略主动退出,是条件请求产生卖出;期末结算,是实验结束导致模拟关闭。三种记录可能都出现在图表末端,触发原因和含义却不同。强制会计退出不能标成策略已经独立决定卖出,否则会扭曲持有期、退出归因和对规则本身的理解。

比较结果之前先冻结报告口径。把仅估值账户换成清仓账户,即使股票价格完全一样,也会增加成本并改变库存。一个策略在退出费前、另一个在结算后比较,会混用报告基础。保存平仓前快照和结算后状态,读者才知道差额来自价格、成本还是库存处理,而不是只能猜测曲线为何最后跳变。

夹具没有入金、分红、融资、税或汇率,每笔实际完成订单收费一。多头退出按标记下浮百分之一,进入则明确按十、不加进入滑点。两个方向假设不对称,但已经事先声明,不能在报告里统称包括所有成本,或让读者误以为进入与退出采用完全相同的成交模型。

Investor.gov费用说明解释交易费用会影响账户价值,不规定本例一单位佣金和百分之一滑点。真实研究需要日期适用的成本证据。这里都是受控会计输入,未从真实券商账单估计,也不保证现实费用只在这两处出现。

重建最后一次正常估值

初始现金一千,以十买四十股、付费用一,剩599现金、持仓四十。三期给定收盘标记依次十、十一、十二,在期末结算之前,权益分别999、1039、1079;相对进入价十,未实现价格损益分别零、四十、八十。股数始终由订单决定,不会因为标记变化而自动增加。

最后正常快照中,股票市值四十乘十二等于480,加现金599得到1079。进入费用已经通过现金少一反映,但退出佣金和退出滑点尚未发生。因此1079是持仓估值,不能叫作已经卖出、可以直接使用的账户现金。把持仓市值与可用资金混用,还可能让后续资金安排产生额外错误。

脚本精确断言平仓前记录:索引二、现金599、股数四十、标记十二、未实现八十、权益1079,并保留之前快照。只有末值,没有这些字段,难以区分真实价格变化、结算成本修订或意外删除持仓。对账应该能够从一条有库存的快照走到一条空仓现金快照,而不是只说最后收益变了。

退出价格与费用只记一次

多头清算以标记十二应用百分之一不利滑点,执行价11.88。四十股卖出本金475.20,扣退出费用一,净加现金474.20。原599加上它,结束现金1073.20、持仓零、累计费用二。此处现金已经净扣费用,后续汇总不能再从这个余额重复扣同一笔佣金。

从1079下降5.80,滑点解释四十乘十二减11.88,即4.80,佣金解释一。应独立计算这条桥,不从一个四舍五入收益率倒推出总成本。中间分量可见,重复扣费或滑点方向写反就容易被发现;只核大致百分比会把小而系统性的差额隐藏起来。

已实现价格损益为四十乘11.88减十,即75.20,两笔佣金后,相对初始资本的净现金损益为73.20。毛价格利润与净现金利润不同,原未实现八十不能再加一次,它属于此前标记快照,仓位关闭时已经由实际退出价格替代。先前账面盈利转成现金,不是新增第二份收益。

Python Decimal文档支持本例十进制价格与现金计算。数值断言允许同值的不同尾零格式,避免把字符串显示差别误认为经济差异,但成交记录仍要求精确方向、数量、费用和11.88退出价。数字相等与字段语义一致都要核对,不能只挑其中一项。

替换末快照,不增加虚构日期

结算后把第三条快照权益换成现金1073.20,库存与未实现损益设零,索引仍为终点二。列表仍只有三条,之前999和1039不变,另存的平仓前记录继续解释原1079。这样既保留差额证据,也避免为了记退出费用而凭空增加一个没有真实会话的新日期。

追加日期可能改变指标使用的长度和时间;保留旧末快照会遗漏退出成本;现金已扣后再从权益扣一次则重复收费。因此断言要求最后权益等于现金、持仓清空、未实现为零、总费恰好二。末快照不是孤立汇总,它应与实际模型账户状态一致,不能图表和明细各自保留不同口径。

清仓后再次调用终端关闭函数,不得增加成交、费用或现金变化,空仓不能卖第二遍。这是生命周期检查,不声称任何复杂引擎重试都已具有事务保证。范围只是一份多头和确定的终端记账,不包括并发订单、部分结算失败或真实券商确认延迟,扩展这些行为还需另写契约。

主动退出作为不同机制反例

独立控制在索引一明确给出策略退出请求,标记十一按同样滑点变10.89。四十股本金435.60、扣费净收434.60,加原599得到1033.60,持仓零、总费二。这不是期末根据结果倒选的退出日,而是提前声明的另一条事件路径,原因字段保存为signal。

后来实验结束时已经没有仓位,因此不再增加end_of_backtest卖出,也不因为循环到了末行再收一次费用。此控制区分退出原因并检查重复清算,不只是把成功末期案例的卖价换低。报告若把主动退出和终端关闭混在一个标签下,可能错误统计策略的真实退出次数。

仅估值参考则关闭强制结算,保留四十股、现金599、末权益1079,只付进入费。较高末值不能证明不付退出费是一种更优可执行策略,因为它报告的是不同结束状态。比较之前应统一口径,或把两者之间5.80结算差额单列,不能直接把未卖出标记当作已经实现的盈利优势。

会计清仓与市场可卖分别核实

某些期末记账路径可能绕过日常可卖与原始bar检查。夹具允许附带市场受阻标记,仍计算同样合成结算,并明确终端执行未经核实。该标记不是完整停牌或T+1模拟器,只把解释限制写出来。模型空仓不能证明真实券商当天可以卖出,也不能授权放松真实市场约束。

最后标记若陈旧,按它进行会计清算更不同于真实可执行价。应保存标记来源、年龄、相关市场限制及运行结束原因,真实清算另核这些条件。不能用终端现金宣称停牌或刚买入受限股份已经当日释放。需要真实变现分析时,应继续报告未退风险,而不是用强制结算把问题从账户中删除。

运行并审阅期末结算桥

下载完整示例,使用Python 3.12或更新版本执行python R603.py。仅标准库、合成标记与固定成本输入,输出终端账户、仅估值参考、主动退出控制及受阻注释,不连接券商,不运行产品回测。所有金额都是声明机制的验算,不代表真实股票历史收益。

实际最后一天出现差异时,收集平仓前数量与标记、终端成交及理由、滑点、退出费用、结束现金和被替换快照,逐项比较后再改策略。完成诊断应交付可以解释的账户桥,而不是只让最后曲线与某个期望数吻合。真实清算可行性仍需独立市场证据,不能由合成结果推导。

本例最终标记十二完整可得,未验收缺标记时自动采用成本价或其他替代价。若接入资料缺失,应另定可追溯估值政策和错误状态,不能因为当前现金桥正确就默认所有价格回退都合理。

常见问题

为什么1079变成1073.20?

合成结算增加4.80滑点和一笔退出费用,前者是持仓标记,后者是模型现金。

末持仓为零能否证明当天可交易?

不能。这里强制结算是会计约定,市场资格和真实执行需要独立证据。

相关阅读