EigenLedger 的周期字符串与自定义日期表有什么区别?
它们走的是两条完全不同的代码路径,行为差异比参数名看起来大得多。
写法一:周期字符串
rebalance="monthly"。库会从起点开始按固定天数往后推,逐期生成日期并计算该期权重,最后拼成一张权重表。实测中 monthly 生成 45 列、weekly 生成 194 列。
写法二:自定义日期表
传入日期与权重的 DataFrame(列是日期,行是标的),库按你给的日期切段计算收益。适合已有明确调仓记录的场景,权重由你完全控制。
| 对比项 | 周期字符串 | 自定义日期表 | 注意点 |
|---|---|---|---|
| 权重来源 | 按你设定的权重或优化器逐期计算 | 完全由你提供的表决定 | 后者不再受优化器影响 |
| 日期怎么来 | 起点 + 固定天数反复累加 | 你给的日期 | 周期折算成天,可能落在月中或带时分秒 |
| 首元素约定 | 无 | 首列必须等于 start_date | 不相等会直接抛 KeyError |
| 是否需要联网 | 设了优化器才需要 | 设了优化器才需要 | 只改权重不优化时不联网 |
| 实测结果 | 能运行,列数随周期缩短而暴增 | 未能在本站跑通(缺可用的行情数据) | 以你的实际环境为准 |
| 适合场景 | 规则化定投、季度调仓 | 历史真实调仓记录回放 | 研究里两者常需配合使用 |
实测细节:rebalance="monthly" 生成的时间戳形如 2023-02-01 10:00:00、2023-03-03 20:00:00;rebalance="weekly" 的首列甚至是 2023-01-09 00:27:41.538462。也就是说它们不是自然月/自然周边界,而是按天数精确累加的结果,落在哪一天取决于起点与折算天数。
EigenLedger 的「monthly」到底是多少天?
库内部把所有周期换算成一个天数常量,一年按 365 天计。
| 可填的写法 | 折算天数 | 与自然日历的差异 | 实测提示 |
|---|---|---|---|
daily | 1 | 基本相同 | 期数最多,耗时与输出体积最大 |
weekly | 365 ÷ 52 ≈ 7.019 | 不是自然周,会逐次漂移 | 实测 3.7 年区间生成 194 列,日期带小数秒 |
monthly / month / m | 365 ÷ 12 ≈ 30.417 | 不是自然月,约每 5 个月错位一次 | 实测 3.7 年区间生成 45 列,日期落点逐月漂移 |
quarterly / quarter / q | 365 ÷ 4 = 91.25 | 不是自然季度 | 季度对比时注意口径说明 |
6m / 2q | 182.5 | 不是自然半年 | 半年及以上周期样本极少,统计意义弱 |
1y / year / y | 365 | 不处理闰年 | 长区间会累积到与年末错开 |
2y | 730 | 同上 | 期数很少,指标解释力有限 |
rebalance="monthly" 并不等价。要做自然月调仓,应自己生成日期与权重表传入,或对结果做日历对齐后再用于决策。哪三种 EigenLedger 再平衡配置会抛异常?
下面三段报错均为本站实测原文,可直接对照排查。
| 你的写法 | 实测报错 | 触发条件 | 怎么改 |
|---|---|---|---|
rebalance="every-fortnight" | KeyError: 'Not an accepted rebalancing schedule' | 传入的字符串不在允许列表内 | 改用表内的 14 个写法之一,或传自定义日期表 |
区间太短:2023-01-02 到 2023-01-20 配 rebalance="1y" | KeyError: 'Date Range does not encompass rebalancing interval' | 区间天数不覆盖一个完整周期 | 拉长区间,或换更短的周期 |
自定义日期表首列 2023-02-01 与 start_date="2023-01-02" 不一致 | KeyError: "the rebalance dates and start date doesn't match" | 日期表起点必须等于回测起点 | 让第一列等于 start_date,或在表里补上起点列 |
日期表的列名不是 YYYY-MM-DD 字符串 | 本站未能实测该路径(缺可用行情数据) | 源码会截取列名前 10 位当作日期使用 | 列名统一写成 YYYY-MM-DD |
同时传 optimizer 与 rebalance,且区间不足 | 首期求解即可能失败(本机因取不到行情未跑到这一步) | 每期都要重新取数与求解,单期样本过少时优化不可靠 | 拉长区间或降低调仓频率 |
KeyError,但原因完全不同:一个是「周期名不存在」,一个是「区间不够长」,一个是「起点没对齐」。看到 KeyError 时先看引号里的那句话,它已经说明了问题。EigenLedger 自然月调仓该怎么写?
如果你要的是「每月最后一个交易日按目标权重调仓」,得自己造这张表。
列出调仓日期
取每个自然月的最后交易日,形成日期列表;第一个日期必须等于
start_date。为每个日期准备一组权重
权重之和建议归一到 1,行顺序必须与
portfolio一致。组装成表并把日期截成日期字符串
库里会把列名截取前 10 位当作日期使用,因此列名建议统一为
YYYY-MM-DD形式的字符串。传入 rebalance 并写死区间
同时显式传
end_date,避免最后一列被推进到运行当天。
import pandas as pd
from EigenLedger import Engine, portfolio_analysis
# 列 = 调仓日(首列必须等于 start_date),行 = 标的,值 = 该期权重
schedule = pd.DataFrame(
{
"2023-01-03": [0.5, 0.5],
"2023-02-28": [0.4, 0.6],
"2023-03-31": [0.6, 0.4],
},
index=["KO", "AMD"],
)
pf = Engine(
start_date="2023-01-03", # 必须与 schedule 第一列一致
end_date="2023-12-29",
portfolio=["KO", "AMD"],
rebalance=schedule,
)
portfolio_analysis(pf)要点:列名是日期、行是标的,与「权重表」直觉一致;但首列日期必须与 start_date 完全一致,否则触发上表第三种报错。由于本站环境取不到行情数据,这段代码的完整行为未能在本机验证,请以官方实现为准。
开不开再平衡,EigenLedger 报告有哪些差别?
这是「同一组权重、两份报告结论不同」的最常见原因。
| 维度 | 不写 rebalance(买入持有) | 写了 rebalance | 对结论的影响 |
|---|---|---|---|
| 权重含义 | 只在起点成立,之后随价格漂移 | 每个调仓日回到目标权重 | 后者更贴近「规则化调仓」的真实体验 |
| 波动与回撤 | 受强势标的影响越来越大 | 被定期拉回,通常更平滑 | 波动差异可达数个百分点 |
| 收益来源 | 含「让赢家跑」的动量效应 | 含定期再平衡的均值回复效应 | 两者归因完全不同,不能混着解释 |
| 交易成本 | 不计 | 同样不计 | 调仓越频繁,报告越乐观 |
| 输出体积 | 一张权重表(标的 × 1) | 每期一组权重(实测 45~194 列) | 列数就是期数,注意保存与展示成本 |
| 耗时 | 低 | 设了优化器时每期都要重新求解 | 周频 + 优化器的组合最耗时 |
| 结果字段 | orderbook 为资产-权重两行表 | orderbook 为各期权重表 | 处理前要先判断形状 |
什么场景用 EigenLedger 的哪种再平衡?
按你实际会执行的调仓规则来选,而不是按哪个跑得快。
| 你的实际做法 | 建议写法 | 理由 | 报告里必须注明 |
|---|---|---|---|
| 一次性买入,之后不管 | 不写 rebalance | 与买入持有的真实体验一致 | 说明权重会随价格漂移 |
| 每季度按目标比例调仓 | rebalance="quarterly" 或自定义表 | 要贴近自然季度就用自定义表 | 周期折算口径 |
| 每月固定日子定投 | 自定义日期表 | 定投日的现金流无法用周期近似 | 是否计入手续费 |
| 回放历史真实调仓 | 自定义日期表 | 只有这张表能还原真实路径 | 权重来源与调整原因 |
| 验证优化器稳定性 | 周期字符串 + 优化器 | 看每期权重是否剧烈跳动 | 没有计入调仓成本 |
| 高频(日/周)策略 | 不建议用它 | 成本项缺失会让结论严重乐观 | 若仍要出图,须显式声明局限 |
| 对照维度 | EigenLedger 路线 | 本机技能路线 | 建议 |
|---|---|---|---|
| 规则化调仓回测 | 周期或日期表驱动,可脚本化 | 可用自然语言描述调仓规则 | 要精确复现选前者 |
| 调仓成本评估 | 不提供 | 取决于具体技能实现 | 两边都要另行补充 |
| 真实持仓复盘 | 需把持仓导出成权重表 | 持仓与盈亏查询类技能更直接 | 日常复盘选技能路线 |
| 批量对比不同周期 | 改一个参数重跑即可 | 交互式逐次提问 | 批量实验选前者 |
| 调仓记录留档 | orderbook 字段即各期权重表 | 需自行记录过程 | 正式研究把权重表导出 CSV |
| 日历口径对齐 | 需自己做自然月对齐 | 取决于技能实现 | 两边都要说明用的是哪种调仓口径 |
披露:本机技能目录已核验(29 个技能),EigenLedger 与 EasyClaw 无已证实集成;上表为能力对照,不表示结果口径一致。
关于再平衡的常见问题
不写 rebalance 时,权重会变吗?
会变,但是自然漂移。库按「权重 ÷ 首日价格」确定份额,此后只受价格影响,相当于买入并持有。因此报告里的「年化波动」和「最大回撤」描述的是漂移后的组合,而不是恒定权重组合,以官方实现为准。
monthly 和自然月差多少?
库内折算为 365÷12≈30.417 天,而自然月平均约 30.44 天。差异虽小,但会逐期累积:实测 3.7 年区间下,调仓日会从月初逐渐漂到月中甚至月末。若你的策略定义写的是「每月最后一个交易日」,必须用自定义日期表。
再平衡会计算手续费吗?
不会。源码中没有交易成本项,任何频率的再平衡结果都假设「调仓免费且即时成交」。频率越高,报告与真实账户的差距越大,这一点在引用报告时必须说明。
为什么周频再平衡生成了一百多列?
因为每一期都会作为一列写进权重表,列数等于期数。实测 3.7 年区间下 weekly 生成 194 列、monthly 生成 45 列。列数过多会让结果表难以阅读,也会显著增加处理时间,建议按需截取展示。
调仓日期落在非交易日怎么办?
按天数累加出来的日期可能落在周末或假期。库的做法是直接用这个日期去取区间收益,具体行为取决于数据源返回的交易日序列。稳妥做法是用自定义日期表,只填真实交易日,以官方实现为准。
最后一列权重是「今天」的正常吗?
正常。实测输出的最后一列日期就是运行当天,表示从上一个调仓日到今天的这段区间的权重。这也意味着报告结果会随运行日期变化,正式留档时请显式写 end_date 并记录运行快照。
再平衡结果能直接当调仓指令吗?
不能。它是历史区间下的权重序列,没有考虑流动性、最小交易单位、税费与你账户的实际持仓。合理用法是把它作为「如果按这个规则执行会发生什么」的研究材料,而不是执行计划。