问题A
由bqrz626f创建,最终由bqrz626f 被浏览 2 用户
我已经完整查看了题目说明,并解压检查了两张数据表。总体判断是:这道题真正考察的不是把夏普做得多高,而是能否建立一个不存在前视偏差、换月处理合理、成本口径清楚,并且经得起敏感性检验的回测。
题目要求来源:D:\Users\言承洋\Desktop\题目A\众量投资 · 量化CTA投研实习生笔试题(题目A).docx
数据核查来源:C:\Users\言承洋\Documents\Codex\2026-10-14\d-users-desktop-a\work\topic_a\data\futures_daily_contracts.csv C:\Users\言承洋\Documents\Codex\2026-10-14\d-users-desktop-a\work\topic_a\data\instruments.csv C:\Users\言承洋\Documents\Codex\2026-10-14\d-users-desktop-a\work\topic_a\data\数据说明.txt
一、数据中已经确认的问题
- 行情表共有 816,754 行、29个品种,日期为 2012-01-04 至 2024-12-31,共3157个交易日;品种与 instruments.csv 能完全对应,没有重复主键记录。
- 题目字段表写有 pre_settle,实际 CSV 并没有这个字段。不能直接照题面引用,必须在报告中明确说明,并自行用同一合约上一条有效 settle 构造前结算价,或者改用收盘到收盘收益。
- 郑商所合约代码只有三位年月,例如 CF201 既可能对应2012年1月,也可能对应2022年1月。直接按 contract 分组会把相隔约九年的两个合约错误接起来。必须结合交易日期恢复完整交割年份,构造真正唯一的合约ID。
- 有13条记录的 open/high/low/close 全部缺失,集中在2023年的郑商所合约。
- 另有146条 OHLC 全为0,全部集中在2024年郑商所合约;这些记录仍可能有非零结算价和持仓量,不能拿0计算收益。
- 有112,970条记录成交量为0但持仓量大于0,占全表约13.8%。这类记录不能自然地解释为“当日可按该价格成交”。
- 有46,353条记录的 close 不在 low-high 区间内,其中46,312条是零成交记录。说明无成交合约的 OHLC、收盘价或结算价可能采用了不同的填充口径。
- 还有41条正成交记录出现收盘价不在高低区间内,主要是临近交割、极低成交的大商所合约,需要过滤或单独说明。
- 不同品种上市时间不同,早期每天只有17至18个品种,后期才逐步达到29个。不能从2012年开始就固定除以29。
- 原油、镍等品种存在真实的极端行情,例如2022年镍合约单日结算收益可超过15%。不能因为数值很大就机械删除,但应单独做事件检查。
二、连续收益序列最需要注意的地方
- 建议直接构造“连续收益”,不要先拼接未经调整的连续价格再 pct_change()。换月时新旧合约存在期限价差,直接跨合约算价格变化会把基差误当成收益。
- 每天先确定下一持有期对应的实际合约,再计算该同一合约从当天到下一交易日的收益。
- 基准换月规则可以选“前一日持仓量最大合约”或“前一日成交量最大合约”。使用前一日数据更容易避免在收盘时同时观察、选择并成交造成的前视问题。
- 如果采用当日成交量或持仓量选合约,要明确假设这些数据在收盘成交前可知;这是需要承认的理想化假设。
- 主力合约发生切换时,即使策略方向和仓位不变,也发生了卖出旧合约、买入新合约的两笔单边交易,必须计入换月成本。
- 给换月增加稳定规则,例如新合约连续两天领先、领先一定比例,或者进入交割月前强制换月,可避免主力合约在两个合约之间频繁跳动。
- 必须制定可交易过滤条件。至少应排除价格缺失、价格小于等于0,以及成交量为0的候选合约。
- 可考虑避开临近到期合约,但数据没有明确到期日,需要从合约月份推导并说明近似处理。
- 题目要求至少检验一个替代选择。最有价值的是“持仓量主力 vs 成交量主力”,也可以比较“收盘收益 vs 结算收益”或不同换月缓冲规则。
- 郑商所甲醇早期合约代码使用过 ME,而品种代码是 MA。不能仅靠合约代码前缀识别品种,应以 symbol 字段为准。
三、信号和波动率实现
- “过去L日累计收益”要明确是复合收益、对数收益之和,还是简单收益之和。建议使用对数收益之和,信号取其符号。
- 必须明确窗口是否包含第t日收益。按题意,t日收盘生成信号,可使用截至t日的信息,但策略收益必须从t+1日开始。
- L={20,60,120,250} 的起始日期不同。主结果可以各自从数据充足时开始,但横向比较最好再给一份共同样本期结果。
- 事前波动率可使用60日滚动标准差或EWMA,并严格 shift 检查,确保没有用到t+1收益。
- 年化波动率应说明使用的交易日数,例如252日。
- 20% / σ 在低波动期可能产生很高杠杆。基准最好严格遵循题目;另做波动率下限或杠杆上限的稳健性检验,并明确这属于附加约束。
- 新上市品种、换月后历史不足、波动率为0或缺失时应不持仓,而不是填成无限大仓位。
- 建议保存中间表:日期、品种、所选合约、信号、波动率、目标仓位、下一日收益、换月标记和成本。这样面试时容易解释和排错。
四、组合和成本计算
- 单品种目标组合权重应写成 a(i,t)=w(i,t)/N(t),其中 N(t) 是当日真正可交易且历史数据充分的品种数。
- “等权平均”不等于每个品种固定等名义仓位;应先按波动率缩放单品种仓位,再在有效品种之间平均。
- 成本率为单边万分之三。普通调仓成本可按 0.0003 × |目标权重-调仓前权重| 计算。
- 更严谨时,调仓前权重应考虑上一日价格变动后的自然漂移;若时间有限,用目标权重一阶差分近似也可以,但必须说明。
- 换月日不能只看组合权重差。如果旧合约换成新合约、品种权重未变,仍应按卖旧和买新两边分别计成本。
- 动态品种数量会使原有品种权重变化,因此新上市、暂停交易和重新进入组合也会产生换手成本。
- 数据没有合约乘数、保证金和涨跌停可成交信息,因此可以做名义资金比例回测,但不能声称已经完整模拟实际手数、保证金占用和市场冲击。
五、结果统计与可信度
- 年化收益要明确采用算术年化还是复合年化;CTA回测通常同时给累计净值和复合年化收益更清楚。
- 年化波动、夏普和t统计量应基于同一组日收益与同一无风险利率假设。
- 普通t统计量可能忽略策略收益的自相关。建议至少补充 Newey-West/HAC t统计量,或在正文说明普通t值的局限。
- 最大回撤应基于复利净值曲线计算,并报告对应的开始、谷底和恢复日期。
- 单品种结果不能只给平均值,至少报告中位数、四分位数、正收益品种比例、最优和最差品种;最好附一张排序图或箱线图。
- 四个L高度相关,不能把其中最好一个当成独立发现。应展示四组结果整体是否一致,避免事后挑选。
- 建议做前后半样本、逐年收益、剔除最佳年份、剔除最极端若干日等稳健性检验。
- 29个品种并非29个独立样本,例如黑色、化工、农产品内部高度相关。横截面品种数不能直接当作独立观测数。
- 重点检查结果是否主要来自2020年原油、2021年商品上涨、2022年镍等少数事件。
- 可信度结论应同时讨论换月敏感性、价格口径、零成交记录、交易成本、参数选择、样本长度和极端事件依赖。
六、第三部分建议选题
我最建议的问题是:“时间序列动量收益是否由少数极端年份或极端交易日驱动?”
这个问题与“结果是否可信”直接相连,且实现成本低。可以比较完整样本、逐年样本、剔除最佳年份、剔除绝对收益最大的5至10个交易日,以及前后半样本。即使发现收益明显消失,这也是有价值的负面结论,比再调一个参数更符合评分标准。
七、提交材料容易失分的地方
- PDF正文最多5页,应该把主要空间留给数据判断、连续收益构造、核心结果和可信度,不要塞大量参数表。
- 附录可放详细单品种结果、额外稳健性检验和数据异常清单。
- 代码必须能从原始 CSV 一键运行,固定随机种子,并附环境、入口命令、输出文件说明。
- 不要在代码里写死本机绝对路径。
- 研究日志不超过1页,而且必须按时间顺序记录决策、失败尝试和放弃原因。
- 日志必须明确列出至少一处AI建议或代码的问题。例如:“AI最初建议直接按原始 contract 分组,但郑商所三位代码十年重名,会错误连接不同交割年份,因此未采纳。”
- 报告中的每个关键选择都要能在代码中找到对应实现,尤其是可交易过滤、合约选择、收益对齐、波动率滞后和换月成本。
- 最后最好准备三项自动检查:信号日期早于收益日期、所选合约当日确实存在、成本后收益永远等于成本前收益减去非负成本。
如果由我完整作答,我会把核心目标定为:先建立一个时间对齐严格、换月收益干净、成本可以解释的基准回测,再用少量但有针对性的稳健性检验判断结果是否可信。不会把时间花在不断调参寻找最高夏普上。
题目依据:D:\Users\言承洋\Desktop\题目A\众量投资 · 量化CTA投研实习生笔试题(题目A).docx
数据依据:C:\Users\言承洋\Documents\Codex\2026-10-14\d-users-desktop-a\work\topic_a\data\futures_daily_contracts.csv C:\Users\言承洋\Documents\Codex\2026-10-14\d-users-desktop-a\work\topic_a\data\instruments.csv
一、先明确基准方案
我的基准设定会是:
- 合约选择:使用前一交易日持仓量最大的、当日有成交的合约。
- 合约切换:设置两日确认,避免主力合约在两个合约之间来回跳。
- 收益口径:同一实际合约的收盘到收盘收益。
- 信号:过去L日连续复合收益的符号,L={20,60,120,250}。
- 波动率:过去60个交易日的日收益标准差乘以 sqrt(252)。
- 执行:t日收盘形成目标仓位,持有到t+1日收盘。
- 组合:当日有效品种的目标仓位等权平均。
- 成本:对实际名义仓位交易量收取单边3bp,换月时计入卖旧、买新两边。
- 替代方案:把持仓量主力改成成交量主力,比较结果是否改变。
- 自选问题:检验动量收益是否由少数极端年份或极端交易日驱动。
这是容易解释、代码复杂度适中,又能覆盖题目核心风险的一套方案。
二、第一步:数据清洗与合约标识
首先读入行情表和品种表,统一日期和数值类型,然后做以下处理:
- 检查 (trade_date, exchange, symbol, contract) 是否唯一。
- 排除价格缺失或小于等于0的记录。
- 把成交量、持仓量保持为原值,不随意填补。
- 识别零成交记录,不能默认这些价格可成交。
- 根据上市日期构造每日可用的历史品种池。
- 给郑商所三位年月合约恢复完整年份。
最后一点尤其重要。例如2021年的 CF201 应解释为2022年1月合约,而2012年的 CF201 是2012年1月合约。我的代码会创建类似:
exchange + symbol + delivery_year + delivery_month
这样的 contract_id,不直接把原始 contract 当作永久唯一标识。
同时生成一张数据质量汇总表,包括:
- 每个品种的起止日期;
- 每年记录数;
- 缺失和零价格数量;
- 零成交比例;
- 异常收益记录;
- 每日有效合约数;
- 每日有效品种数。
三、第二步:选择每个品种的交易合约
设 c(i,t) 为品种i在t日收盘需要交易的合约。
为了避免前视偏差,我不会用t+1日成交量来决定t日持有什么合约。基准规则是:
候选合约:
价格有效
成交量 > 0
持仓量 > 0
尚未明显进入交割状态
排序指标:
使用 t-1 日持仓量
换月规则:
新合约连续两日排名第一后才切换
两日确认不是唯一正确答案,但可以减少新旧主力短暂交替造成的无意义换手。
如果原合约已经不再可交易,则允许立即切换。所有这些特殊情况都会记录到 roll_flag 和 roll_reason 中,方便检查。
替代方案使用前一日成交量最大合约。最终比较:
- 主力合约切换次数;
- 平均持有天数;
- 连续收益相关性;
- 策略绩效变化;
- 交易成本变化。
四、第三步:构造连续收益,而不是粗暴拼接价格
我不会把不同合约的价格直接首尾相接后计算涨跌幅,因为换月价差会被误认为收益。
正确做法是:t日收益必须来自t-1日实际持有的同一个合约:
r(i,t) = P(c(i,t-1),t) / P(c(i,t-1),t-1) - 1
这里 c(i,t-1) 是t-1日收盘已经确定并买入的合约。
这意味着:
- 如果没有换月,正常计算原合约收益;
- 如果t-1日发生换月,则t日收益来自新合约自身的收盘变化;
- 不计算“旧合约昨日价格到新合约今日价格”的跨合约收益;
- 新旧合约价差只影响真实换月成交,不伪装成市场收益。
若选中的合约在下一日没有有效价格,我不会回头选择一个“恰好有下一日价格”的合约,因为那会使用未来信息。基准做法是将该品种下一日标记为不可计算,并在稳健性分析中说明影响;正常主力合约上这种情况应该很少。
五、第四步:构造动量信号
对每个品种的连续收益计算过去L日累计收益:
R(i,t,L) = product(1 + r(i,t-L+1:t)) - 1
s(i,t,L) = sign(R(i,t,L))
也可以使用对数收益之和,二者在价格均为正时信号基本一致。我会在报告里明确采用复合收益。
需要严格检查:
- 信号窗口只到t日为止;
- 策略收益从t+1日开始;
- 历史不足L日时不生成信号;
- 累计收益等于0时仓位设为0;
- 不把缺失收益自动填成0后继续滚动。
四个L各自可以从满足历史长度时开始,但为了公平比较,我还会补一张共同样本期结果表。
六、第五步:估计事前波动率
基准使用过去60个有效交易日的日收益标准差:
sigma(i,t) = std(r(i,t-59:t)) × sqrt(252)
w(i,t) = s(i,t) × 20% / sigma(i,t)
因为t日收盘生成仓位,使用截至t日的收益估计波动率符合题意。代码中仍会显式检查最终仓位没有引用t+1日数据。
具体规则:
- 至少需要40个有效观察值;
- 波动率为0或缺失时不持仓;
- 基准结果不随意截断仓位,以尽量遵守题目公式;
- 另外报告最大杠杆和仓位分位数;
- 稳健性检验中加入5%波动率下限或仓位上限,观察结果是否依赖极端杠杆。
还可以用EWMA作为补充,但正文篇幅有限,我会优先保留与换月规则有关的替代检验。
七、第六步:组合收益
设当日有 N(t) 个品种满足信号、波动率和可交易条件,则组合中的品种权重为:
a(i,t) = w(i,t) / N(t)
下一日成本前组合收益为:
gross_return(t+1)
= sum[a(i,t) × r(i,t+1)]
这里必须使用动态的 N(t)。2012年只有约17个品种可用,不能固定除以29。
我还会保存:
- 多头品种数和空头品种数;
- 总名义敞口;
- 净名义敞口;
- 每个品种的风险贡献;
- 当日组合中实际有效的品种数。
这样可以判断看似稳定的收益是否只是由个别品种承担了大部分风险。
八、第七步:交易成本
普通调仓时,简单近似的交易量是:
turnover(i,t) = |a(i,t) - a(i,t-1)|
更严谨的实现会先根据上一日收益计算调仓前漂移权重,再与新目标权重比较。
换月必须特殊处理。若品种权重没变但合约由A换成B,仍然发生:
卖出A:|旧权重|
买入B:|新权重|
因此换月交易量约为:
|旧权重| + |新权重|
每日成本和净收益为:
cost(t) = 0.0003 × sum(turnover(i,t))
net_return(t) = gross_return(t) - cost(t)
这一步很容易低估成本。只对品种层面的权重差收费,会漏掉“权重不变但合约变化”的换月交易。
九、第八步:绩效统计
每个L分别报告成本前和成本后:
- 算术年化收益:日均收益乘252;
- 复合年化收益,作为补充;
- 年化波动率;
- 夏普比率;
- 普通t统计量;
- Newey-West调整后的t统计量;
- 最大回撤;
- 最长回撤恢复时间;
- 年均换手率和年均成本;
- 累计净值曲线。
最大回撤从复利净值计算:
equity(t) = cumulative_product(1 + return(t))
drawdown(t) = equity(t) / running_max(equity(t)) - 1
单品种层面会给出:
- 年化收益、波动率、夏普和最大回撤;
- 中位数和四分位数;
- 正收益品种比例;
- 最好和最差的品种;
- 品种结果排序图或箱线图。
单品种测试也使用同样的信号和波动率方法,但不再除以组合品种数。
十、第九步:可信度检验
我会优先做以下检验,而不是继续增加参数:
- 持仓量主力与成交量主力是否得到相近结论。
- 成本前结论在3bp成本后是否仍然存在。
- 前半样本与后半样本是否一致。
- 逐年收益是否只集中在少数年份。
- 去掉表现最好的年份后结论是否仍成立。
- 去掉组合绝对收益最大的5至10个交易日后是否仍成立。
- 结果是否主要由镍、原油或某一产业组贡献。
- 四个L是否方向一致,而不是只有一个参数偶然漂亮。
- 使用共同样本期后,不同L的排序是否改变。
- 加入波动率下限后,结果是否发生根本变化。
最后我不会简单写“夏普高,所以策略可信”。我会给出分层结论,例如:
- 统计上是否显著;
- 对换月规则是否稳健;
- 对极端事件是否敏感;
- 成本后是否仍有经济意义;
- 是否存在可实现性限制;
- 哪些结果仍需更多数据验证。
十一、第三部分我会做什么
我会提出:
时间序列动量收益是否由少数危机时期和极端交易日驱动?
具体检验:
- 画逐年成本后收益;
- 分别计算2012–2017、2018–2024;
- 剔除最佳一年;
- 剔除绝对组合收益最大的5日和10日;
- 剔除镍2022年极端行情;
- 比较处理前后的年化收益、夏普和t统计量。
如果剔除少数事件后收益明显消失,我会直接报告“样本内动量表现高度依赖尾部事件”。这不是失败,反而很好地回答了结果可信度问题。
十二、代码组织
我会把项目整理为:
README.md
config.py
src/
load_data.py
clean_contracts.py
select_contracts.py
build_returns.py
signals.py
portfolio.py
metrics.py
run.py
outputs/
tables/
figures/
report/
report.pdf
research_log.pdf
run.py 从原始CSV开始,一次生成全部表格和图片。路径使用相对路径,参数集中在 config.py,并设置断言检查:
- 合约ID唯一;
- 没有未来数据参与合约选择;
- 信号至少滞后一个收益期;
- 每日净收益等于毛收益减成本;
- 成本始终非负;
- 换月日确实产生换月交易量;
- 同一天组合权重使用同一个有效品种数。
十三、5页正文安排
- 第1页:问题、数据异常、核心方法和时间线。
- 第2页:连续收益、换月规则、信号和波动率方法。
- 第3页:四个L的核心绩效表与净值图。
- 第4页:单品种分布、换月替代方案和成本影响。
- 第5页:极端事件检验、可信度判断、局限与结论。
- 附录:详细年度表、29个品种结果、异常记录和补充检验。
研究日志则真实记录决策过程,包括发现 pre_settle 缺失、郑商所合约代码重名、零成交价格异常,以及哪些AI建议被修改或否决。这样整份答卷的重点会落在“研究判断是否可靠”,而不是“代码是否成功跑出一条漂亮曲线”。