EigenLedger 的 Engine 参数怎么填?16 个参数逐个讲清
Engine 是这个库唯一的核心抽象:它同时承担「输入参数容器」和「结果对象」两个角色。参数填错不会报错,只会安静地给出另一份数字——这正是组合分析最难排查的一类问题。
本页按 EigenLedger/main.py 源码逐个核对参数、默认值与副作用,并给出把一份分析固定下来的写法。
EigenLedger 的 Engine 有哪 16 个参数?
下表的默认值均取自源码签名,不是文档转述。
| 参数 | 默认值 | 作用 | 必须知道的注意点 |
|---|---|---|---|
start_date | 无(必填) | 组合与基准回测起点 | 字符串或日期都可,内部按 %Y-%m-%d 解析,格式不符会直接抛异常 |
portfolio | 无(必填) | 标的代码列表 | 顺序决定权重顺序,改顺序等于改组合 |
weights | None | 各标的权重 | 留空且在未设优化器时自动等权(1/n);长度必须与标的数一致 |
benchmark | ["SPY"] | 用于 Alpha/Beta 与相对绩效 | 默认是美股宽基,A 股组合用它算 Alpha 没有意义 |
end_date | 运行当天 | 回测终点 | 不写死的话,同一份脚本隔天重跑结果会变 |
rebalance | None | 再平衡周期字符串或自定义日期权重表 | 一旦传入,构造 Engine 时就会立刻执行再平衡计算 |
optimizer | None | "EF"/"MEANVAR"/"HRP"/"MINVAR" 或自定义函数 | 同样在构造期就算权重,会联网取历史价格 |
max_vol | 0.15 | 仅 MEANVAR 使用,作为年化波动上限 | 与报告里「年化波动」的算法口径不同,不能直接对照 |
diversification | 1 | L2 正则强度(gamma) | 调大可抑制权重过度集中,同时也会拉离理论最优点 |
expected_returns | None | 预期收益模型,仅接受 mean_historical_return/ema_historical_return/capm_return | 传其它值会被断言拦下;EF 默认用历史均值,MEANVAR/MINVAR 默认用 CAPM |
risk_model | None | 协方差估计方法,仅接受 sample_cov/semicovariance/exp_cov/ledoit_wolf 系列/oracle_approximating | EF 默认 sample_cov,其余默认 ledoit_wolf;换方法会改变权重 |
min_weights / max_weights | None | 给优化器加单标的下限/上限约束 | 约束过紧时优化器可能无解;只对三种均值方差类优化器生效 |
risk_manager | None | 字典,可用 "Stop Loss"/"Take Profit"/"Max Drawdown" 提前截断回测 | 源码只读字典的第一个键,同时写多个不会同时生效 |
data | 空表 | 传入本地价格数据,绕开网络 | 列名须为标的代码,且基准列也在其中时基准才会走本地数据 |
benchmark_data | 空表 | 单独传入基准价格序列 | 非空时组合基准收益会改用组合自身数据计算,语义与传 data 不同 |
源码中两处校验是「断言」而不是友好提示:expected_returns 与 risk_model 传了不在白名单里的值会直接 AssertionError,报错信息里会列出允许的取值。
EigenLedger 哪些参数一填就会联网?
这是最容易踩的一脚:以为只是「配置对象」,实际已经触发下载与优化。
| 构造 Engine 时传入 | 构造期就会发生的事 | 适用场景 | 注意点 |
|---|---|---|---|
optimizer="EF" 等 | 调用 PyPortfolioOpt,先用 yfinance 拉全部标的的复权收盘价,再解优化问题 | 想让库直接给权重 | 断网、标的缺失或区间太短都会在这里就失败,而不是在分析时 |
optimizer=自定义函数 | 直接调用你的函数并把返回值当权重 | 接入自有打分或风险预算逻辑 | 函数必须返回与标的一一对应的权重列表 |
rebalance="monthly" | 逐期生成日期与权重,最后打印整张再平衡表 | 定期调仓、定投 | 设了优化器时每期都要重新取数并求解,期数越多越慢 |
rebalance=[自定义日期] | 按你给的日期与权重表切段计算 | 已有明确调仓记录 | 日期表首列必须等于 start_date,否则抛 KeyError |
只传 portfolio 与 weights | 不联网,仅保存参数 | 先构造、后分析 | 取数发生在 portfolio_analysis() |
risk_manager={"Stop Loss": -0.2} | 不额外联网,但在分析阶段按阈值截断收益序列 | 模拟「跌到止损位就退出」 | 截断后区间变短,年化与夏普都会被改写 |
data= 传本地表 | 组合收益走本地数据 | 离线复现研究结果 | 发布版仍会为基准联网取数,无法完全离线 |
min_weights / max_weights | 构造期即参与求解 | 限制单一标的占比 | 约束过紧时求解器无解,报错来自底层库 |
怎样让一份 EigenLedger 组合报告三个月后还能重跑?
EigenLedger 只解决了「参数集中」,剩下的复现责任仍在使用者身上。
写死区间,不依赖运行当天
始终显式传
end_date。默认取date.today()会让「同一份报告」每天长大一天,区间指标随之漂移。记录库版本组合
至少记录 EigenLedger、QuantStats、PyPortfolioOpt、yfinance、pandas 的版本号。这些库任意一个升级都可能改变指标或让代码直接报错。
记录数据口径
写明数据源、是否复权、复权方式、数据截止日。
记录假设参数
无风险利率
rf、VaR 的sigma与confidence、基准代码、是否启用risk_manager。同时留存输入与输出
保存权重列表、原始价格表摘要和最终指标表三样东西。只留一张图,等于没留证据。
| 要留的证据 | 从哪拿 | 为什么必须留 | 常见错误 |
|---|---|---|---|
| 起止日期 | 你传入的 Engine 参数 | 所有区间指标都由它决定 | 只写「最近三年」 |
| 标的与顺序 | portfolio | 权重按位置对应,顺序即含义 | 只存 ticker 集合,丢了顺序 |
| 权重 | pf.weights | 等权、手填、优化三种来源结果差别很大 | 只写「等权」不写具体数值 |
| 基准 | pf.benchmark | Alpha/Beta/信息比率都依赖它 | 沿用默认 SPY 却当成 A 股基准 |
| 依赖版本 | pip freeze 或环境锁文件 | 旧依赖是这套工具链的常态 | 只记 EigenLedger 一个版本号 |
| 数据截止日 | 取数结果的首末日期 | 数据源可能只到上个交易日 | 用运行日期代替数据日期 |
| 指标参数 | rf/sigma_value/confidence_value | 直接影响夏普与 VaR 数值 | 改动后未同步更新报告说明 |
| 标的上市时间 | 价格表首日与每日缺值情况 | 起点早于上市日会引入填充值 | 假定所有标的在区间起点都可交易 |
| 运行快照 | 输出文件与日志目录 | 区分「没信号」与「没取到数」 | 只留最终截图,不留中间输出 |
哪三个 EigenLedger 默认值会让报告不知不觉变味?
它们都不报错,只是安静地改变结论。
默认基准是 SPY
源码里 BENCHMARK = ["SPY"]。分析 A 股或港股组合时,Alpha 会变成「相对美股宽基的超额」,这个数在业务上没有解释力。
默认无风险利率是 0
portfolio_analysis(pf, rf=0.0)。夏普与 Sortino 都按零利率计算,会系统性高估风险调整后收益;与券商或平台口径对比时差异主要来自这里。
默认终点是今天
end_date=TODAY,而 TODAY 在导入模块时求值。今天跑和下周跑不是同一份报告,跨月对比要格外小心。
| 你看到的现象 | 可能原因 | 验证方式 | 处理建议 |
|---|---|---|---|
| 同一脚本两次跑出的年化不同 | 未写 end_date,区间随当天漂移 | 打印引擎的 start_date / end_date | 显式写死两端日期 |
| 夏普比平台显示的高 | rf=0 与平台的国债利率口径不同 | 用平台同样的 rf 重算一次 | 报告里注明 rf 取值 |
| Alpha 看起来很大但组合是纯 A 股 | 基准仍是默认 SPY | 检查 pf.benchmark | 换成对应市场指数 |
| 优化权重每天都不一样 | 优化区间随当天延长,且样本协方差每天变 | 固定区间重跑 | 先冻区间,再谈权重 |
| 回撤统计与预期不符 | 启用了 risk_manager,序列被提前截断 | 看引擎实际 end_date 是否被改写 | 截断前后各出一份报告对比 |
end_date 打印出来,并在触发止损/止盈/回撤阈值时改写它。如果你发现打印的结束日期早于你填写的日期,说明 risk_manager 生效了。EigenLedger 一份「可复现」的最小写法长什么样?
关键差别只有两处:显式日期,以及把用到的假设全部写在代码里。
import EigenLedger
from EigenLedger import Engine, portfolio_analysis
pf = Engine(
start_date="2022-01-03", # 显式起点
end_date="2024-12-31", # 显式终点,不用默认的“今天”
portfolio=["KO", "AMD", "JNJ"], # 顺序 = 权重顺序
weights=[0.4, 0.3, 0.3],
benchmark=["^GSPC"], # 明确写出基准,不用默认 SPY
)
# 假设参数同样写死,并打印留档
result = portfolio_analysis(pf, rf=0.02, sigma_value=1, confidence_value=0.95)
print("EigenLedger:", getattr(EigenLedger, "__version__", "unknown"))
print("weights:", pf.weights)
print("start/end:", pf.start_date, pf.end_date)运行后应当核对的三件事:
- 打印出的起始/结束日期与你填写的一致(不一致说明
risk_manager截断了序列)。 - 打印出的权重与预期一致(若同时设了
weights与optimizer,以优化器结果为准)。 - 指标表里的基准口径与
benchmark参数对应。
实测补充:本站已在隔离环境中验证该库可导入、Engine 可构造、17 项指标表能算出;但由于本机无法取到行情数据(见「安装与运行时边界」页的实测记录),完整流程未在本站跑通,因此本页不提供运行输出截图,也不承诺该片段在你机器上必然可运行。
EigenLedger 的 Engine 管不到什么?
知道它不负责什么,比知道它支持什么更重要。
不管交易成本
收益序列由复权价格直接算出,源码中没有手续费、印花税、滑点项;调仓频率越高,报告与真实账户的差距越大。
不管分红现金流
用复权价格近似包含分红影响,但没有单独的现金分红与再投资记录,无法回答「这一年收了多少股息」。
不管数据质量
取数失败会抛错,取到错误数据却不会报警。停牌、拆股、代码变更都需要使用者自己检查。
| 你想做的事 | EigenLedger 路线 | 本机技能路线 | 建议 |
|---|---|---|---|
| 把一组标的与权重固定下来跑报告 | Engine 参数即配置 | 用自然语言描述组合,由技能取数分析 | 要版本化、要复用选前者 |
| 临时问一只票的指标 | 要写代码且只能回归区间统计 | a-share-metrics-card 等技能直出体检结果 | 一次性查询选后者 |
| 把参数与结论一起留档 | 需自行保存脚本与版本 | 对话记录本身即过程留痕 | 正式报告仍建议用脚本 |
| 核对无风险利率口径 | 自己传 rf | 取决于各技能内部实现 | 两边都要写明口径再对比 |
| 留存每次分析的取数快照 | 需自己把价格表导出留档 | 取数过程留在对话记录里 | 正式研究统一导出 CSV 快照 |
| 换数据源后重跑同一套指标 | 改 data= 参数即可 | 需重新描述任务 | 要求口径一致时选脚本路线 |
| 对比不同权重方案的敏感性 | 改 weights 循环重跑即可 | 需逐次描述方案 | 方案多于三个时选脚本路线 |
| 把参数交给同事接手 | 脚本本身就是参数文档 | 需导出对话上下文 | 跨人协作选脚本路线 |
披露:EasyClaw 与本机技能目录的关系已核验,但 EigenLedger 与 EasyClaw 之间没有已证实的集成;上表是能力对照,不代表二者可互相调用。
关于 Engine 参数的常见问题
只传 portfolio 不传 weights 会怎样?
在同时没有设置 optimizer 的情况下,库会自动等权(每个标的 1/n),源码里对应 equal_weighting()。如果设置了优化器,权重由优化结果覆盖,你手填的 weights 不会生效——这一点在源码里没有提示,务必以实际运行结果为准。
weights 的长度必须和标的一一对应吗?
是。取数阶段会校验两者长度,不一致直接抛 ValueError: Weights and stocks lists must have the same length.。顺序也是按位置匹配的,交换两个权重等于换了一个组合,不会报错。
可以同时设置止损和止盈吗?
不建议依赖。risk_manager 是字典,但源码只取 list(keys)[0] 判断分支,也就是说只有第一个键会被处理。想要「先止损再止盈」这类组合逻辑,需要自己在外部实现,以官方实现为准。
传 data= 之后还会联网吗?
取决于基准。若 data 中同时包含 benchmark 指定的列,基准也会走本地数据,全程不联网;否则仍会为基准发起一次下载。想完全离线,请把基准列一并放进数据表,具体行为以官方实现为准。
expected_returns 能自己传数值序列吗?
不能。源码只接受三个字符串方法名(mean_historical_return、ema_historical_return、capm_return),传入其它值会触发断言失败。要使用自定义预期收益,只能走自定义优化器函数这条路。
diversification 调大是不是就更安全?
它是 L2 正则的惩罚系数(gamma),作用是抑制权重极端集中,不是风险预算工具。调大通常会让权重更平均,但同时会偏离「最大夏普」这个原始目标;判断是否更安全要看优化后的实际波动与回撤,以官方实现为准。
为什么同样的参数,别人跑出来的数字和我不同?
常见原因按概率排序:库版本不同(尤其 QuantStats 与 pandas)、数据源返回的区间不同(数据只到最近交易日)、默认 end_date 取了各自运行当天、rf 与 VaR 参数不同、基准代码不同。逐项对齐后才能比较,以双方的实际输入与官方实现为准。