跳到正文

研究指南

股票策略开发

股票月末效应研究案例:只按交易日历切换现金与固定篮子

月末月初股票篮子策略,首先需要冻结交易所会话,而不是先寻找价格指标。明确篮子以后,在本月最后一个会话的开盘买入,在下月第四个会话开盘请求退出,其余时间持有现金。简单统计周一至周五不够,因为交易所休市会改变第四个实际会话对应的日期。

本文使用一小段真实NYSE日历日期和两只普通股票的合成价格,不是ETF策略,也不是全年季节效应业绩研究。CoTrading的自动日历获取、篮子成交和缺bar处理仍属规划或待核实。可下载脚本只实现下面写明的有限夹具,不代表交易平台已经完整支持。

篮子成员和日历安排分别冻结

本例在所示月末之前固定篮子:A四十股,B二十股。证券标识和数量都是输入,不根据之后哪只股票上涨而重新选取。扩展研究时,还需定义成员、权重、变更何时可知,以及退市证券怎样继续保留记录。日历效应不能成为看到收益后替换亏损成员的理由。

排期函数只有日期输入,不读收盘价、波动、收益或之后表现,所以交易时间由什么决定可以直接检查。若未来加入趋势过滤、流动性排名或财报排除,就形成了新的条件策略,应保存独立实验记录,不能仍然称作完全相同的纯日历规则。输入的冻结时间与后续策略版本也应一起保存。

账户起始现金一千、零持仓。给定数量在进入价格下使用八百本金,不宣称恰好满仓,保留的现金承担费用及未投资余额。每笔实际完成的股票订单收费一单位,两只股票进入收费二,退出再收费二。本例没有融资、卖空或现金利息。这些约定先于结果确定,而不是为了让某个月盈利再选择成本模型。

计数对象是给定真实交易会话

NYSE交易时间与休市日历列明2026年7月3日为独立日观察休市。本例提供的会话依次是6月29、6月30、7月1、7月2、7月6、7月7、7月8。6月30日作为经过确认的六月最后会话单独输入,函数不能从任意截断行情的末行自行发现“真正月末”。

七月前四个会话因此是7月1日、2日、6日、7日,进入计划为6月30日,退出计划为7月7日。如果只枚举工作日,就会把7月3日算进去,得到错误的第四日7月6日。即使某个合成价格让错误日期更赚钱,它仍然是日历错误,不能据此把失误解释为合理优化。

输入必须唯一且递增,确认的月末必须存在,同一个月不能再有更晚的给定会话。紧接着的下一个自然月必须至少有四条会话,不能取三条七月记录再借一条八月日期凑数。脚本对这种不完整日历直接报错,不悄悄改变“下月第四会话”的含义。

本夹具另外明确拒绝已知休市日7月3日,但它不是通用假日核验库。真实长期研究仍需外部冻结完整交易所日历,包括相关特殊会话。日期排好序且数量足够,只能证明结构完整,不能证明任意手写会话表都符合交易所实际安排,更不能证明未来日历修改已经被处理。

开盘执行不能依赖同日后来价格

在日历已经确认的条件下,月末和下一月前四个会话能够提前排期。6月30日开盘请求两笔买入,不读取当天收盘。7月7日开盘请求两笔清仓。这是开盘至开盘的暴露窗口,不应写成只隔夜持仓,也不能把账户描述成按月末收盘价成交。

实际系统还需记录交易所时区、订单截止时间和进入开盘机制的资格。计划日期不保证具体价格或必然成交。本夹具提供可执行开盘与简单费用;税、价差、集合竞价不确定性、汇率和实际券商限制都需要另行输入。它们不能在文中被假定为已经包括在一单位费用内。

全年回测还应处理首尾不完整月份。若数据从计划进入之后才开始,不得凭空补出此前买入;若在下月第四会话之前结束,应报告尚未退出或另列终端估值。把最后一行一律清仓会引入数据边界规则,而该规则并不是月末日历策略本身要求的退出。

正常路径逐笔闭合两股账户

6月30日买A四十股、每股10,本金400;买B二十股、每股20,本金也是400。两笔费用合计二,从一千现金扣除后剩198,持仓A四十、B二十,累计费用二。以当次进入价估值,开仓后权益为998,等于初始资本减已收费用。

7月7日卖A四十股、每股10.5,扣费净收419;卖B二十股、每股19,扣费净收379。结束现金198加419加379等于996,持仓清空,累计费用四。A价格贡献正二十,B贡献负二十,两者价格损益抵消,最终净亏四完全来自费用。

样例断言精确方向、数量、价格、单笔费用、进入后现金、末现金和空持仓,不只检查一个末权益。数量和费用错误有可能彼此抵消,恰好留下相同总数,却代表不同的篮子或成本模型。逐笔记录能让这种“总数对了但机制错了”的情况被发现。

个股缺行情与交易所休市不是同一问题

独立的执行反例保留7月7日这个正常会话,只移除B的可执行开盘。日历计划不改变,当天仍然请求退出。A正常卖出,B保持二十股并记录missing_executable_bar。卖A以后现金617,B仍有二十股,累计费用三,不能提前把尚未卖出的持仓转成现金。

下一给定会话7月8日,B有有效开盘18.5,二十股扣费后净收到369,最终现金986、零持仓、费用四。它比正常账户少十,来自二十股B乘半单位价格下降。原因是退出执行延后,不是把“第四会话”悄悄改成了7月8日,也不是多收了一笔没有成交的订单费用。

不能用B的旧价假装7月7日已经成交,也不能因为个股缺bar就说整个交易所当天休市。股票层面的数据或交易障碍与交易所日历关闭是不同机制。更复杂组合可以采用别的受阻政策,但应保存原请求日、拒绝理由、未退库存和最终成交日,才能解释暴露为什么延长。

运行夹具并保留研究边界

下载完整示例,在Python 3.12或更新版本执行python R593.py,只需标准库。价格和账户都是合成数据,短会话日期窗口依据引用日历冻结。输出显示给定日期、计划进入退出、正常订单、缺bar拒绝和延后清仓账户,便于把排期和实际执行并排核对。

断言还拒绝下月会话不足、正式休市日以及借用八月日期凑满四期。排期函数没有任何价格输入,因此追加未来有利行情不能更改原定日期。扩展研究时应冻结更多真实会话与当时可知成员,比较多个周期,不只挑一个看起来成功的月末。一个受控现金桥只能验证机制,真实经济证据仍需另行取得。

报告同时保存原请求和实际退出

组合报告应对两股都保留7月7日原退出请求,分别列A已经成交、B缺bar被拒,再连接B在7月8日的真实夹具成交。如果只给最终空仓,会隐藏多持有一个会话的暴露;如果只给日历信号,又会隐藏现金后果。日历版本、行情覆盖状态和账户账本需要一起保存,后来补齐一条bar应作为新数据版本评估,不能静默重写原实验。

补入行情后,先核它在当时是否确实可用于执行,再决定新运行应如何改变。数据供应商今天回补一个开盘,并不能单独证明当时账户真的能取得或执行该价。若策略执行条件还依赖停牌、开盘集合竞价资格或订单提前提交,这些也要单独留证。当前夹具只验证声明的有效bar与延后退出政策。扩展到全年之前,还应在每个月检查月末确认和下月前四会话完整性,不能在跨年时借错月份或让最后一条行情替代正式月末。一段窗口通过不等于其他月份日历已经齐备。

对缺bar控制还应按股逐笔检查:A净收419,B延后净收369,原现金198,加总986。费用仍四而不是五,因为被拒的B请求没有成交。这能把价格延迟损失与错误拒单收费区分开,防止同一个十单位差异被解释成完全不同的成本来源。

常见问题

为什么7月7日退出而不是7月6日?

给定2026年窗口中7月3日休市,所以7月7日才是七月第四个真实会话。7月6日来自把休市日误算为工作日的捷径。

个股缺bar是否会改变日历信号?

不会。它阻止该股票执行。反例保留7月7日的原退出请求,另行记录7月8日实际清仓。

相关阅读