trader-explain
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExplain a trading signal by building a feature-contribution graph and running single-entry forward-push PageRank from the signal output node. Top-K ranked features are returned as a markdown table AND persisted to as a (ADR-126 Phase 6).
trading-analysisSignedAttributionArtifactWhy this skill matters:
- EU AI Act + SEC Reg-AI guidance require interpretable model output for any algorithmic trading system that touches retail capital. This is the regulator-grade attribution path the rest of the substrate has been waiting for.
- The same call site picks up the full native-WASM PageRank from once that tool is registered in the runtime — until then, the local power-iteration kernel ships in
mcp__ruflo-sublinear__page-rank-entryand produces the same ordering (seeded mulberry32).signed-attribution.mjs
Steps:
-
Retrieve the signal from the canonicalnamespace (ADR-126 Phase 1 + Phase 2 lifecycle):
trading-signalstextmcp__claude-flow__memory_retrieve({ key: "SIGNAL_ID", namespace: "trading-signals" })The signal entry includes,modelId, and the feature vector at the time of inference.prediction -
Extract per-feature contribution scores from the model:bash
npx neural-trader --predict --signal "$SIGNAL_ID" --explain --jsonThe expected output shape:ts{ features: Array<{ name: string; contribution: number }>; // for Transformers, also includes per-head attention co-occurrence: attention?: Array<{ head: string; cooccur: Array<[number, number, number]> }>; }Fallback path — ifis not shipped on the installed--explainbuild (older versions; the flag was scoped for a follow-up upstream PR), the skill degrades to a deterministic feature-importance heuristic over the signal's input vector:neural-trader(z-score magnitude). This is a known proxy — not as faithful as attention/SHAP — and the resulting artifact is taggedcontribution_i = |input_i - μ_i| / σ_iso downstream consumers can filter it out for regulator filings. Document the fallback path in the resulting markdown summary so the agent surfaces it to the user.attribution_method: "input-zscore-fallback" -
Build the feature-contribution graph:
- Nodes: one node per feature + one source node for the prediction.
__signal_output__ - Edges: outgoing edges from to each feature node, weighted by
__signal_output__. When attention co-occurrence data is available, also add edges between feature nodes weighted bycontribution_i— this is what makes the PageRank single-entry rather than degenerating to plain top-K.cooccur - Source: (index 0 by convention so the smoke can assert reproducibility).
__signal_output__
- Nodes: one node per feature + one source node
-
Run single-entry PageRank — preferred path whenis registered:
mcp__ruflo-sublinear__page-rank-entrytextmcp__ruflo-sublinear__page-rank-entry({ nodes: GRAPH_NODES, edges: GRAPH_EDGES, sourceIndex: 0, damping: 0.85, maxIterations: 100, tolerance: 1e-8, seed: 42 })The local fallback (inlocalSingleEntryPageRank) runs ~30 LOC of seeded power-iteration when the MCP tool is not available — same math, same result up to floating-point tolerance, same ordering for the same seed (the Phase 6 smoke asserts this).plugins/ruflo-neural-trader/src/signed-attribution.mjs -
Build the top-Kvia
AttributionFeature[]— excludes the source node from the ranked output. Ties broken by node index (lower index wins) so the ranking is deterministic.topKFeatures(graph, scores, k=10, excludeIndex=0) -
Sign the artifact (reuses the Phase 4 signing primitives — same Ed25519 + canonicalization):
- Build the body:
SignedAttributionArtifactts{ signalId: SIGNAL_ID, modelId: SIGNAL.modelId, features: TOP_K_FEATURES, // from step 5 graphMetadata: { nodeCount: GRAPH.nodes.length, edgeCount: COUNT_EDGES, pageRankIterations: PR_RESULT.iterations, seed: SEED // load-bearing for reproducibility }, generatedAt: NEW_DATE_ISO } - Resolve the witness signing key — same lookup order as Phase 4:
- env var — JSON file with
RUFLO_WITNESS_KEY_PATH.{ "privateKey": "<hex>" } - (the ADR-103 default path).
verification/witness-key.json
- If a key resolves: from
signAttributionArtifact(body, privateKeyHex).plugins/ruflo-neural-trader/src/signed-attribution.mjs - If NEITHER path resolves: log and store the body unsigned. NEVER silently fall back.
"[WARN] ruflo-neural-trader: no witness signing key found — storing attribution artifact in UNSIGNED degraded mode. Regulator filings will reject UNSIGNED artifacts."
- Build the
-
Store the (possibly signed) artifact to the canonicalnamespace (ADR-126 Phase 1):
trading-analysistextmcp__claude-flow__memory_store({ key: "attribution-SIGNAL_ID-TIMESTAMP", namespace: "trading-analysis", value: JSON.stringify(signedArtifact) })Thenamespace is the canonical home for model-analysis output (regime classifications, technical-indicator summaries, model-training results — and now attribution rankings). Long-lived — no TTL — because the audit trail is the deliverable.trading-analysis -
Return the markdown summary to the agent. Suggested format:
## Feature attribution for signal `SIGNAL_ID` (model: MODEL_ID) | Rank | Feature | Score | |------|---------|-------| | 1 | NAME | 0.42 | | 2 | NAME | 0.18 | | … | … | … | - PageRank iterations: N - Graph: nodeCount nodes, edgeCount edges - Seed: 42 (reproducible — same seed → same ordering) - Path: mcp | local - Signature: ed25519:abcd… (or UNSIGNED — degraded warning above)
通过构建特征贡献图并从信号输出节点运行单入口前推PageRank算法来解释交易信号。排名前K的特征将以Markdown表格形式返回,并作为持久化存储到中(ADR-126第6阶段)。
SignedAttributionArtifacttrading-analysis该技能的重要性:
- 《欧盟AI法案》和SEC的Reg-AI指南要求,任何涉及零售资本的算法交易系统必须提供可解释的模型输出。这正是整个底层系统一直期待的监管级归因方案。
- 一旦工具在运行时注册,同一调用点将使用完整的原生WASM版PageRank;在此之前,本地幂迭代内核将通过
mcp__ruflo-sublinear__page-rank-entry运行,生成的排序结果一致(使用mulberry32种子)。signed-attribution.mjs
步骤:
-
从标准命名空间获取信号(ADR-126第1阶段+第2阶段生命周期):
trading-signalstextmcp__claude-flow__memory_retrieve({ key: "SIGNAL_ID", namespace: "trading-signals" })信号条目包含、modelId以及推理时的特征向量。prediction -
从模型中提取每个特征的贡献得分:bash
npx neural-trader --predict --signal "$SIGNAL_ID" --explain --json预期输出结构:ts{ features: Array<{ name: string; contribution: number }>; // 对于Transformer模型,还包含每头注意力共现数据: attention?: Array<{ head: string; cooccur: Array<[number, number, number]> }>; }备选方案 — 如果已安装的版本未包含neural-trader参数(旧版本;该参数是后续上游PR新增的),该技能将降级为基于信号输入向量的确定性特征重要性启发式算法:--explain(z分数绝对值)。这是一种已知的替代方案——不如注意力机制/SHAP准确,生成的工件将标记contribution_i = |input_i - μ_i| / σ_i,以便下游使用者在提交监管文件时将其过滤掉。需在生成的Markdown摘要中记录该备选方案,以便Agent向用户展示。attribution_method: "input-zscore-fallback" -
构建特征贡献图:
- 节点:每个特征对应一个节点 + 一个代表预测结果的源节点。
__signal_output__ - 边:从到每个特征节点的出边,权重为
__signal_output__。当有注意力共现数据时,还需添加特征节点之间的边,权重为contribution_i——这正是PageRank实现单入口而非退化为普通Top-K排序的关键。cooccur - 源节点:(按约定索引为0,便于验证重现性)。
__signal_output__
- 节点:每个特征对应一个节点 + 一个代表预测结果的源节点
-
运行单入口PageRank — 当已注册时优先使用该方案:
mcp__ruflo-sublinear__page-rank-entrytextmcp__ruflo-sublinear__page-rank-entry({ nodes: GRAPH_NODES, edges: GRAPH_EDGES, sourceIndex: 0, damping: 0.85, maxIterations: 100, tolerance: 1e-8, seed: 42 })当MCP工具不可用时,本地备选方案(中的plugins/ruflo-neural-trader/src/signed-attribution.mjs)将运行约30行代码的带种子幂迭代——数学逻辑一致,结果在浮点误差范围内一致,相同种子下排序结果相同(第6阶段的冒烟测试已验证这一点)。localSingleEntryPageRank -
通过构建Top-K的
topKFeatures(graph, scores, k=10, excludeIndex=0)— 排名输出中将排除源节点。通过节点索引打破平局(索引较小者胜出),确保排序结果确定性。AttributionFeature[] -
对工件进行签名(复用第4阶段的签名原语——相同的Ed25519算法+规范化流程):
- 构建主体:
SignedAttributionArtifactts{ signalId: SIGNAL_ID, modelId: SIGNAL.modelId, features: TOP_K_FEATURES, // 来自步骤5 graphMetadata: { nodeCount: GRAPH.nodes.length, edgeCount: COUNT_EDGES, pageRankIterations: PR_RESULT.iterations, seed: SEED // 对重现性至关重要 }, generatedAt: NEW_DATE_ISO } - 获取见证签名密钥——查找顺序与第4阶段相同:
- 环境变量——包含
RUFLO_WITNESS_KEY_PATH的JSON文件。{ "privateKey": "<hex>" } - (ADR-103默认路径)。
verification/witness-key.json
- 若找到密钥:调用中的
plugins/ruflo-neural-trader/src/signed-attribution.mjs。signAttributionArtifact(body, privateKeyHex) - 若两个路径都未找到:记录日志并存储未签名的主体。绝对不能静默降级。
"[WARN] ruflo-neural-trader: no witness signing key found — storing attribution artifact in UNSIGNED degraded mode. Regulator filings will reject UNSIGNED artifacts."
- 构建
-
将(可能已签名的)工件存储到标准命名空间(ADR-126第1阶段):
trading-analysistextmcp__claude-flow__memory_store({ key: "attribution-SIGNAL_ID-TIMESTAMP", namespace: "trading-analysis", value: JSON.stringify(signedArtifact) })命名空间是模型分析输出的标准存储位置(包括 regime分类、技术指标摘要、模型训练结果——现在新增归因排名)。长期存储——无TTL(生存时间)——因为审计追踪是核心交付物。trading-analysis -
向Agent返回Markdown摘要。建议格式:
## 信号`SIGNAL_ID`的特征归因(模型: MODEL_ID) | 排名 | 特征 | 得分 | |------|---------|-------| | 1 | NAME | 0.42 | | 2 | NAME | 0.18 | | … | … | … | - PageRank迭代次数: N - 图结构: nodeCount个节点, edgeCount条边 - 种子: 42(可重现——相同种子→相同排序) - 执行路径: mcp | local - 签名: ed25519:abcd…(或UNSIGNED——上方有降级警告)
Verification
验证
Downstream consumers verify the artifact before any regulator-facing report or paper→live promotion:
ts
import { verifyAttributionArtifact } from 'plugins/ruflo-neural-trader/src/signed-attribution.mjs';
const ok = await verifyAttributionArtifact(artifact, trustedPublicKey);
if (!ok) {
// [ERROR] attribution verification failed — refuse to publish.
// Pin to trustedPublicKey from project config; do NOT trust the
// artifact.witnessPublicKey field (CWE-347 / #1922 — attacker-controllable).
return;
}Acceptance criteria (ADR-126 Phase 6):
- returns a ranked feature list whose top-3 features overlap the model's attention argmax (when
trader-explain <signalId>available; documented tolerance).--explain - Reproducibility: two runs with the same + same
signalIdproduce byte-identical rank ordering (asserted by--seed).scripts/smoke-neural-trader-feature-attribution.mjs - Signed artifact verifies under the trusted pubkey; tampering any feature score or invalidates the signature.
graphMetadata.seed - Fallback paths engage cleanly: when MCP unavailable, local kernel runs; when flag missing, z-score heuristic runs and the artifact is tagged.
--explain
Refs:
- ADR-126 Phase 6 (this skill's authoring ADR)
- ADR-126 Phase 4 (the signing scheme this reuses)
- ADR-123 (single-entry PageRank substrate; the same family that Phase 3 leverages for portfolio CG)
- (the typed contract)
plugins/ruflo-neural-trader/src/signed-attribution.ts - (the runtime mirror)
plugins/ruflo-neural-trader/src/signed-attribution.mjs - (the regression smoke)
scripts/smoke-neural-trader-feature-attribution.mjs
下游使用者在提交任何监管报告或从测试环境推广到生产环境前,需验证该工件:
ts
import { verifyAttributionArtifact } from 'plugins/ruflo-neural-trader/src/signed-attribution.mjs';
const ok = await verifyAttributionArtifact(artifact, trustedPublicKey);
if (!ok) {
// [ERROR] 归因验证失败——拒绝发布。
// 绑定到项目配置中的trustedPublicKey;不要信任
// artifact.witnessPublicKey字段(CWE-347 / #1922 — 攻击者可控)。
return;
}验收标准(ADR-126第6阶段):
- 返回的排名特征列表中,前3个特征与模型注意力机制的argmax结果重叠(当
trader-explain <signalId>可用时;文档中已说明容差范围)。--explain - 可重现性:相同+ 相同
signalId的两次运行产生完全相同的字节级排序结果(--seed已验证)。scripts/smoke-neural-trader-feature-attribution.mjs - 已签名的工件可通过可信公钥验证;篡改任何特征得分或都会使签名失效。
graphMetadata.seed - 备选方案可正常触发:当MCP不可用时,本地内核运行;当参数缺失时,z分数启发式算法运行并为工件添加标签。
--explain
参考资料:
- ADR-126第6阶段(该技能的编写依据)
- ADR-126第4阶段(复用的签名方案)
- ADR-123(单入口PageRank底层系统;第3阶段用于投资组合CG的同系列方案)
- (类型化合约)
plugins/ruflo-neural-trader/src/signed-attribution.ts - (运行时镜像)
plugins/ruflo-neural-trader/src/signed-attribution.mjs - (回归冒烟测试)
scripts/smoke-neural-trader-feature-attribution.mjs