Engine 参数与可复现性

EigenLedger 的 Engine 参数怎么填?16 个参数逐个讲清

Engine 是这个库唯一的核心抽象:它同时承担「输入参数容器」和「结果对象」两个角色。参数填错不会报错,只会安静地给出另一份数字——这正是组合分析最难排查的一类问题。

本页按 EigenLedger/main.py 源码逐个核对参数、默认值与副作用,并给出把一份分析固定下来的写法。

Engine(参数)
取复权价
加权日收益
17 项指标
图表 / PDF
结论审计
示意图:一次组合分析的参数流与结果流。图中不含任何真实收益数据。
EigenLedger · 参数表

EigenLedger 的 Engine 有哪 16 个参数?

下表的默认值均取自源码签名,不是文档转述。

参数默认值作用必须知道的注意点
start_date无(必填)组合与基准回测起点字符串或日期都可,内部按 %Y-%m-%d 解析,格式不符会直接抛异常
portfolio无(必填)标的代码列表顺序决定权重顺序,改顺序等于改组合
weightsNone各标的权重留空且在未设优化器时自动等权(1/n);长度必须与标的数一致
benchmark["SPY"]用于 Alpha/Beta 与相对绩效默认是美股宽基,A 股组合用它算 Alpha 没有意义
end_date运行当天回测终点不写死的话,同一份脚本隔天重跑结果会变
rebalanceNone再平衡周期字符串或自定义日期权重表一旦传入,构造 Engine 时就会立刻执行再平衡计算
optimizerNone"EF"/"MEANVAR"/"HRP"/"MINVAR" 或自定义函数同样在构造期就算权重,会联网取历史价格
max_vol0.15MEANVAR 使用,作为年化波动上限与报告里「年化波动」的算法口径不同,不能直接对照
diversification1L2 正则强度(gamma调大可抑制权重过度集中,同时也会拉离理论最优点
expected_returnsNone预期收益模型,仅接受 mean_historical_returnema_historical_returncapm_return传其它值会被断言拦下;EF 默认用历史均值,MEANVAR/MINVAR 默认用 CAPM
risk_modelNone协方差估计方法,仅接受 sample_covsemicovarianceexp_covledoit_wolf 系列/oracle_approximatingEF 默认 sample_cov,其余默认 ledoit_wolf;换方法会改变权重
min_weights / max_weightsNone给优化器加单标的下限/上限约束约束过紧时优化器可能无解;只对三种均值方差类优化器生效
risk_managerNone字典,可用 "Stop Loss""Take Profit""Max Drawdown" 提前截断回测源码只读字典的第一个键,同时写多个不会同时生效
data空表传入本地价格数据,绕开网络列名须为标的代码,且基准列也在其中时基准才会走本地数据
benchmark_data空表单独传入基准价格序列非空时组合基准收益会改用组合自身数据计算,语义与传 data 不同

源码中两处校验是「断言」而不是友好提示:expected_returnsrisk_model 传了不在白名单里的值会直接 AssertionError,报错信息里会列出允许的取值。

EigenLedger · 副作用

EigenLedger 哪些参数一填就会联网?

这是最容易踩的一脚:以为只是「配置对象」,实际已经触发下载与优化。

构造 Engine 时传入构造期就会发生的事适用场景注意点
optimizer="EF"调用 PyPortfolioOpt,先用 yfinance 拉全部标的的复权收盘价,再解优化问题想让库直接给权重断网、标的缺失或区间太短都会在这里就失败,而不是在分析时
optimizer=自定义函数直接调用你的函数并把返回值当权重接入自有打分或风险预算逻辑函数必须返回与标的一一对应的权重列表
rebalance="monthly"逐期生成日期与权重,最后打印整张再平衡表定期调仓、定投设了优化器时每期都要重新取数并求解,期数越多越慢
rebalance=[自定义日期]按你给的日期与权重表切段计算已有明确调仓记录日期表首列必须等于 start_date,否则抛 KeyError
只传 portfolioweights不联网,仅保存参数先构造、后分析取数发生在 portfolio_analysis()
risk_manager={"Stop Loss": -0.2}不额外联网,但在分析阶段按阈值截断收益序列模拟「跌到止损位就退出」截断后区间变短,年化与夏普都会被改写
data= 传本地表组合收益走本地数据离线复现研究结果发布版仍会为基准联网取数,无法完全离线
min_weights / max_weights构造期即参与求解限制单一标的占比约束过紧时求解器无解,报错来自底层库
把它接进自动化脚本时,务必把「构造 Engine」当作一次真实任务来处理:加重试、加超时、把每次取数的交易日记录到日志。否则你无法区分「今天没信号」和「今天没取到数据」。
EigenLedger · 可复现

怎样让一份 EigenLedger 组合报告三个月后还能重跑?

EigenLedger 只解决了「参数集中」,剩下的复现责任仍在使用者身上。

  1. 写死区间,不依赖运行当天

    始终显式传 end_date。默认取 date.today() 会让「同一份报告」每天长大一天,区间指标随之漂移。

  2. 记录库版本组合

    至少记录 EigenLedger、QuantStats、PyPortfolioOpt、yfinance、pandas 的版本号。这些库任意一个升级都可能改变指标或让代码直接报错。

  3. 记录数据口径

    写明数据源、是否复权、复权方式、数据截止日。

  4. 记录假设参数

    无风险利率 rf、VaR 的 sigmaconfidence、基准代码、是否启用 risk_manager

  5. 同时留存输入与输出

    保存权重列表、原始价格表摘要和最终指标表三样东西。只留一张图,等于没留证据。

要留的证据从哪拿为什么必须留常见错误
起止日期你传入的 Engine 参数所有区间指标都由它决定只写「最近三年」
标的与顺序portfolio权重按位置对应,顺序即含义只存 ticker 集合,丢了顺序
权重pf.weights等权、手填、优化三种来源结果差别很大只写「等权」不写具体数值
基准pf.benchmarkAlpha/Beta/信息比率都依赖它沿用默认 SPY 却当成 A 股基准
依赖版本pip freeze 或环境锁文件旧依赖是这套工具链的常态只记 EigenLedger 一个版本号
数据截止日取数结果的首末日期数据源可能只到上个交易日用运行日期代替数据日期
指标参数rfsigma_valueconfidence_value直接影响夏普与 VaR 数值改动后未同步更新报告说明
标的上市时间价格表首日与每日缺值情况起点早于上市日会引入填充值假定所有标的在区间起点都可交易
运行快照输出文件与日志目录区分「没信号」与「没取到数」只留最终截图,不留中间输出
EigenLedger · 默认值陷阱

哪三个 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 · 最小示例

EigenLedger 一份「可复现」的最小写法长什么样?

关键差别只有两处:显式日期,以及把用到的假设全部写在代码里。

Python · 可复现最小示例(示意,未在本站运行) 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 截断了序列)。
  • 打印出的权重与预期一致(若同时设了 weightsoptimizer,以优化器结果为准)。
  • 指标表里的基准口径与 benchmark 参数对应。

实测补充:本站已在隔离环境中验证该库可导入、Engine 可构造、17 项指标表能算出;但由于本机无法取到行情数据(见「安装与运行时边界」页的实测记录),完整流程未在本站跑通,因此本页不提供运行输出截图,也不承诺该片段在你机器上必然可运行。

EigenLedger · 边界

EigenLedger 的 Engine 管不到什么?

知道它不负责什么,比知道它支持什么更重要。

不管交易成本

收益序列由复权价格直接算出,源码中没有手续费、印花税、滑点项;调仓频率越高,报告与真实账户的差距越大。

不管分红现金流

用复权价格近似包含分红影响,但没有单独的现金分红与再投资记录,无法回答「这一年收了多少股息」。

不管数据质量

取数失败会抛错,取到错误数据却不会报警。停牌、拆股、代码变更都需要使用者自己检查。

你想做的事EigenLedger 路线本机技能路线建议
把一组标的与权重固定下来跑报告Engine 参数即配置用自然语言描述组合,由技能取数分析要版本化、要复用选前者
临时问一只票的指标要写代码且只能回归区间统计a-share-metrics-card 等技能直出体检结果一次性查询选后者
把参数与结论一起留档需自行保存脚本与版本对话记录本身即过程留痕正式报告仍建议用脚本
核对无风险利率口径自己传 rf取决于各技能内部实现两边都要写明口径再对比
留存每次分析的取数快照需自己把价格表导出留档取数过程留在对话记录里正式研究统一导出 CSV 快照
换数据源后重跑同一套指标data= 参数即可需重新描述任务要求口径一致时选脚本路线
对比不同权重方案的敏感性weights 循环重跑即可需逐次描述方案方案多于三个时选脚本路线
把参数交给同事接手脚本本身就是参数文档需导出对话上下文跨人协作选脚本路线

披露:EasyClaw 与本机技能目录的关系已核验,但 EigenLedger 与 EasyClaw 之间没有已证实的集成;上表是能力对照,不代表二者可互相调用。

FAQ

关于 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_returnema_historical_returncapm_return),传入其它值会触发断言失败。要使用自定义预期收益,只能走自定义优化器函数这条路。

diversification 调大是不是就更安全?

它是 L2 正则的惩罚系数(gamma),作用是抑制权重极端集中,不是风险预算工具。调大通常会让权重更平均,但同时会偏离「最大夏普」这个原始目标;判断是否更安全要看优化后的实际波动与回撤,以官方实现为准。

为什么同样的参数,别人跑出来的数字和我不同?

常见原因按概率排序:库版本不同(尤其 QuantStats 与 pandas)、数据源返回的区间不同(数据只到最近交易日)、默认 end_date 取了各自运行当天、rf 与 VaR 参数不同、基准代码不同。逐项对齐后才能比较,以双方的实际输入与官方实现为准。

参数填完,报告里那些数字代表什么?

17 项指标分四类,看懂分类就不会被单个数字带偏。