trader-explain

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Explain 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
trading-analysis
as a
SignedAttributionArtifact
(ADR-126 Phase 6).
Why 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
    mcp__ruflo-sublinear__page-rank-entry
    once that tool is registered in the runtime — until then, the local power-iteration kernel ships in
    signed-attribution.mjs
    and produces the same ordering (seeded mulberry32).
Steps:
  1. Retrieve the signal from the canonical
    trading-signals
    namespace (ADR-126 Phase 1 + Phase 2 lifecycle):
    text
    mcp__claude-flow__memory_retrieve({
      key: "SIGNAL_ID",
      namespace: "trading-signals"
    })
    The signal entry includes
    modelId
    ,
    prediction
    , and the feature vector at the time of inference.
  2. Extract per-feature contribution scores from the model:
    bash
    npx neural-trader --predict --signal "$SIGNAL_ID" --explain --json
    The 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 — if
    --explain
    is not shipped on the installed
    neural-trader
    build (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:
    contribution_i = |input_i - μ_i| / σ_i
    (z-score magnitude). This is a known proxy — not as faithful as attention/SHAP — and the resulting artifact is tagged
    attribution_method: "input-zscore-fallback"
    so 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.
  3. Build the feature-contribution graph:
    • Nodes: one node per feature + one source node
      __signal_output__
      for the prediction.
    • Edges: outgoing edges from
      __signal_output__
      to each feature node, weighted by
      contribution_i
      . When attention co-occurrence data is available, also add edges between feature nodes weighted by
      cooccur
      — this is what makes the PageRank single-entry rather than degenerating to plain top-K.
    • Source:
      __signal_output__
      (index 0 by convention so the smoke can assert reproducibility).
  4. Run single-entry PageRank — preferred path when
    mcp__ruflo-sublinear__page-rank-entry
    is registered:
    text
    mcp__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 (
    localSingleEntryPageRank
    in
    plugins/ruflo-neural-trader/src/signed-attribution.mjs
    ) 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).
  5. Build the top-K
    AttributionFeature[]
    via
    topKFeatures(graph, scores, k=10, excludeIndex=0)
    — excludes the source node from the ranked output. Ties broken by node index (lower index wins) so the ranking is deterministic.
  6. Sign the artifact (reuses the Phase 4 signing primitives — same Ed25519 + canonicalization):
    • Build the
      SignedAttributionArtifact
      body:
      ts
      {
        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:
      1. RUFLO_WITNESS_KEY_PATH
        env var — JSON file with
        { "privateKey": "<hex>" }
        .
      2. verification/witness-key.json
        (the ADR-103 default path).
    • If a key resolves:
      signAttributionArtifact(body, privateKeyHex)
      from
      plugins/ruflo-neural-trader/src/signed-attribution.mjs
      .
    • If NEITHER path resolves: log
      "[WARN] ruflo-neural-trader: no witness signing key found — storing attribution artifact in UNSIGNED degraded mode. Regulator filings will reject UNSIGNED artifacts."
      and store the body unsigned. NEVER silently fall back.
  7. Store the (possibly signed) artifact to the canonical
    trading-analysis
    namespace (ADR-126 Phase 1):
    text
    mcp__claude-flow__memory_store({
      key: "attribution-SIGNAL_ID-TIMESTAMP",
      namespace: "trading-analysis",
      value: JSON.stringify(signedArtifact)
    })
    The
    trading-analysis
    namespace 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.
  8. 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表格形式返回,并作为
SignedAttributionArtifact
持久化存储到
trading-analysis
中(ADR-126第6阶段)。
该技能的重要性:
  • 《欧盟AI法案》和SEC的Reg-AI指南要求,任何涉及零售资本的算法交易系统必须提供可解释的模型输出。这正是整个底层系统一直期待的监管级归因方案。
  • 一旦
    mcp__ruflo-sublinear__page-rank-entry
    工具在运行时注册,同一调用点将使用完整的原生WASM版PageRank;在此之前,本地幂迭代内核将通过
    signed-attribution.mjs
    运行,生成的排序结果一致(使用mulberry32种子)。
步骤:
  1. 从标准
    trading-signals
    命名空间获取信号
    (ADR-126第1阶段+第2阶段生命周期):
    text
    mcp__claude-flow__memory_retrieve({
      key: "SIGNAL_ID",
      namespace: "trading-signals"
    })
    信号条目包含
    modelId
    prediction
    以及推理时的特征向量。
  2. 从模型中提取每个特征的贡献得分
    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
    版本未包含
    --explain
    参数(旧版本;该参数是后续上游PR新增的),该技能将降级为基于信号输入向量的确定性特征重要性启发式算法:
    contribution_i = |input_i - μ_i| / σ_i
    (z分数绝对值)。这是一种已知的替代方案——不如注意力机制/SHAP准确,生成的工件将标记
    attribution_method: "input-zscore-fallback"
    ,以便下游使用者在提交监管文件时将其过滤掉。需在生成的Markdown摘要中记录该备选方案,以便Agent向用户展示。
  3. 构建特征贡献图
    • 节点:每个特征对应一个节点 + 一个代表预测结果的源节点
      __signal_output__
    • :从
      __signal_output__
      到每个特征节点的出边,权重为
      contribution_i
      。当有注意力共现数据时,还需添加特征节点之间的边,权重为
      cooccur
      ——这正是PageRank实现单入口而非退化为普通Top-K排序的关键。
    • 源节点
      __signal_output__
      (按约定索引为0,便于验证重现性)。
  4. 运行单入口PageRank — 当
    mcp__ruflo-sublinear__page-rank-entry
    已注册时优先使用该方案:
    text
    mcp__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
    中的
    localSingleEntryPageRank
    )将运行约30行代码的带种子幂迭代——数学逻辑一致,结果在浮点误差范围内一致,相同种子下排序结果相同(第6阶段的冒烟测试已验证这一点)。
  5. 通过
    topKFeatures(graph, scores, k=10, excludeIndex=0)
    构建Top-K的
    AttributionFeature[]
    — 排名输出中将排除源节点。通过节点索引打破平局(索引较小者胜出),确保排序结果确定性。
  6. 对工件进行签名(复用第4阶段的签名原语——相同的Ed25519算法+规范化流程):
    • 构建
      SignedAttributionArtifact
      主体:
      ts
      {
        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阶段相同:
      1. RUFLO_WITNESS_KEY_PATH
        环境变量——包含
        { "privateKey": "<hex>" }
        的JSON文件。
      2. verification/witness-key.json
        (ADR-103默认路径)。
    • 若找到密钥:调用
      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."
      并存储未签名的主体。绝对不能静默降级。
  7. 将(可能已签名的)工件存储到标准
    trading-analysis
    命名空间
    (ADR-126第1阶段):
    text
    mcp__claude-flow__memory_store({
      key: "attribution-SIGNAL_ID-TIMESTAMP",
      namespace: "trading-analysis",
      value: JSON.stringify(signedArtifact)
    })
    trading-analysis
    命名空间是模型分析输出的标准存储位置(包括 regime分类、技术指标摘要、模型训练结果——现在新增归因排名)。长期存储——无TTL(生存时间)——因为审计追踪是核心交付物。
  8. 向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):
  • trader-explain <signalId>
    returns a ranked feature list whose top-3 features overlap the model's attention argmax (when
    --explain
    available; documented tolerance).
  • Reproducibility: two runs with the same
    signalId
    + same
    --seed
    produce byte-identical rank ordering (asserted by
    scripts/smoke-neural-trader-feature-attribution.mjs
    ).
  • Signed artifact verifies under the trusted pubkey; tampering any feature score or
    graphMetadata.seed
    invalidates the signature.
  • Fallback paths engage cleanly: when MCP unavailable, local kernel runs; when
    --explain
    flag missing, z-score heuristic runs and the artifact is tagged.
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)
  • plugins/ruflo-neural-trader/src/signed-attribution.ts
    (the typed contract)
  • plugins/ruflo-neural-trader/src/signed-attribution.mjs
    (the runtime mirror)
  • scripts/smoke-neural-trader-feature-attribution.mjs
    (the regression smoke)
下游使用者在提交任何监管报告或从测试环境推广到生产环境前,需验证该工件:
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阶段):
  • trader-explain <signalId>
    返回的排名特征列表中,前3个特征与模型注意力机制的argmax结果重叠(当
    --explain
    可用时;文档中已说明容差范围)。
  • 可重现性:相同
    signalId
    + 相同
    --seed
    的两次运行产生完全相同的字节级排序结果(
    scripts/smoke-neural-trader-feature-attribution.mjs
    已验证)。
  • 已签名的工件可通过可信公钥验证;篡改任何特征得分或
    graphMetadata.seed
    都会使签名失效。
  • 备选方案可正常触发:当MCP不可用时,本地内核运行;当
    --explain
    参数缺失时,z分数启发式算法运行并为工件添加标签。
参考资料:
  • 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
    (回归冒烟测试)