alphacouncil-agent 0.9.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/alpha.md +22 -3
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +4 -4
- package/.grok/commands/alpha.md +22 -3
- package/.opencode/command/alpha.md +22 -3
- package/AGENTS.md +42 -4
- package/CHANGELOG.md +164 -0
- package/CLAUDE.md +59 -7
- package/README.ja.md +25 -11
- package/README.md +44 -12
- package/README.zh-CN.md +37 -12
- package/commands/alpha.md +22 -3
- package/data/authored/core-seats.mjs +808 -0
- package/data/authored/growth-seats.mjs +581 -0
- package/data/authored/index.mjs +114 -0
- package/data/authored/quant-seats.mjs +564 -0
- package/data/authored/value-seats.mjs +663 -0
- package/data/build-profile.v1.json +2 -1
- package/data/council-evaluation-protocol.v1.json +7 -4
- package/data/master-selector-method-locales.v1.mjs +296 -0
- package/data/persona-v3-ai-assisted-solo-profile.v1.json +2 -2
- package/data/persona-v3-build-specs.v1.mjs +60 -3
- package/docs/INSTALL.md +43 -6
- package/docs/personas.md +2 -1
- package/docs/plans/v1.0-roadmap.md +487 -0
- package/docs/releases/v0.9.3.md +86 -0
- package/docs/releases/v0.9.4.md +79 -0
- package/docs/releases/v0.9.5.md +96 -0
- package/docs/releases/v1.0.0.md +164 -0
- package/docs/report-contract.md +75 -2
- package/knowledge/ai-assisted-solo/experiments/runs/a.json +13 -13
- package/knowledge/ai-assisted-solo/experiments/runs/b.json +2 -2
- package/knowledge/ai-assisted-solo/experiments/runs/c.json +2 -2
- package/knowledge/ai-assisted-solo/experiments/runs/d13.json +126 -126
- package/knowledge/ai-assisted-solo/experiments/runs/d26.json +274 -254
- package/knowledge/ai-assisted-solo/experiments/runs/e-d13.json +129 -129
- package/knowledge/ai-assisted-solo/experiments/runs/e-d26.json +277 -257
- package/knowledge/ai-assisted-solo/experiments/runs/h_ai_reference.json +278 -258
- package/knowledge/ai-assisted-solo/experiments/simulation-input.json +7278 -556
- package/knowledge/ai-assisted-solo/experiments/simulation-manifest.json +22 -22
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_ackman/reviews/{change_value_bridge.ai-review.json → market_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_ackman/reviews/{power_map.ai-review.json → owner_earnings_yield.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_aschenbrenner/reviews/{compute_power_bridge.ai-review.json → market_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_aschenbrenner/reviews/{timeline_reverse_valuation.ai-review.json → price_implied_cash_yield.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_asness/reviews/{crowding_cost_stress.ai-review.json → nominal_earnings_yield_gap.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_asness/reviews/{factor_decomposer.ai-review.json → real_earnings_yield_gap.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/expected_return_over_long_bond.ai-review.json +277 -0
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/fundamental_expected_return.ai-review.json +277 -0
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_buffett/reviews/{incremental_returns.ai-review.json → market_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_buffett/reviews/{owner_earnings_rebuilder.ai-review.json → owner_earnings_yield.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_burry/reviews/{mispricing_carry.ai-review.json → net_current_asset_surplus_per_share.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_burry/reviews/{capital_structure_reader.ai-review.json → net_current_asset_value_per_share.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_cathie_wood/reviews/{cost_adoption_curve.ai-review.json → current_cash_yield.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_cathie_wood/reviews/{capture_valuation_bridge.ai-review.json → market_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_dalio/reviews/{debt_driver_stress.ai-review.json → policy_real_rate.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_dalio/reviews/{regime_classifier.ai-review.json → real_curve_slope.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_damodaran/reviews/{reverse_valuation.ai-review.json → implied_equity_risk_premium.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_damodaran/reviews/{story_dcf.ai-review.json → premium_versus_long_run_average.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_druckenmiller/reviews/{liquidity_revision_map.ai-review.json → liquidity_curve_impulse.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_druckenmiller/reviews/{inflection_payoff.ai-review.json → policy_real_rate.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_duan_yongping/reviews/{opportunity_cost.ai-review.json → five_year_opportunity_cost.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_duan_yongping/reviews/{user_value_evidence.ai-review.json → margin_retention.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_fisher/reviews/{research_productivity.ai-review.json → margin_retention.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_fisher/reviews/{scuttlebutt_graph.ai-review.json → reinvestment_spread.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_forensic_short/reviews/{borrow_catalyst.ai-review.json → cash_conversion_gap.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_forensic_short/reviews/{accounting_rebuilder.ai-review.json → cash_cover_of_leverage.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_graham/reviews/{asset_floor.ai-review.json → defensive_hurdle_base.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_graham/reviews/{normalized_earnings.ai-review.json → half_normalised_earnings_yield.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_jhunjhunwala/reviews/{penetration_liquidity.ai-review.json → cash_quality_gap.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_jhunjhunwala/reviews/{promoter_governance.ai-review.json → real_structural_growth.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_klarman/reviews/{recovery_waterfall.ai-review.json → downside_asset_coverage.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_klarman/reviews/{cash_catalyst_compare.ai-review.json → market_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_li_lu/reviews/{promise_integrity_ledger.ai-review.json → cash_backed_decade_return.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_li_lu/reviews/{ten_year_return_bridge.ai-review.json → decade_return_over_long_bond.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_lynch/reviews/{story_numbers_check.ai-review.json → growth_justified_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_lynch/reviews/{category_classifier.ai-review.json → market_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_marks/reviews/{cycle_temperature.ai-review.json → credit_cycle_position.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_marks/reviews/{implied_expectations.ai-review.json → equity_over_corporate_debt.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_munger/reviews/{failure_path_graph.ai-review.json → debt_service_cushion.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_munger/reviews/{incentive_map.ai-review.json → reported_earnings_cash_gap.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_natenberg/reviews/{surface_builder.ai-review.json → normalised_skew.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_natenberg/reviews/{greeks_payoff.ai-review.json → round_trip_cost.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_pabrai/reviews/{downside_floor.ai-review.json → downside_floor_coverage.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_pabrai/reviews/{discrete_payoff.ai-review.json → market_capitalisation.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_simons/reviews/{oos_cost_test.ai-review.json → absolute_session_move.ai-review.json} +42 -42
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_simons/reviews/{leakage_audit.ai-review.json → session_move_over_implied.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_sinclair/reviews/{realized_vol_forecast.ai-review.json → round_trip_cost.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_sinclair/reviews/{net_edge_sizer.ai-review.json → volatility_per_unit_of_width.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_soros/reviews/{reversal_monitor.ai-review.json → credit_cycle_position.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_soros/reviews/{reflexivity_graph.ai-review.json → financing_burden.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_taleb/reviews/{tail_friction.ai-review.json → debt_service_cushion.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_taleb/reviews/{payoff_ruin.ai-review.json → normalised_skew.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_thorp/reviews/{edge_recalculator.ai-review.json → edge_per_unit_of_volatility.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_thorp/reviews/{fractional_kelly.ai-review.json → net_edge.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/review-manifest.json +288 -270
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-adjudications/index.json +2 -2
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-extractions/index.json +2 -2
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-skeptic-reviews/index.json +2 -2
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-source-prereviews/index.json +6 -2
- package/knowledge/solo-test/masters/master_ackman/decision_policy.json +122 -11
- package/knowledge/solo-test/masters/master_ackman/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_ackman/manifest.json +27 -10
- package/knowledge/solo-test/masters/master_ackman/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_ackman/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_ackman/tools.json +56 -30
- package/knowledge/solo-test/masters/master_aschenbrenner/decision_policy.json +101 -10
- package/knowledge/solo-test/masters/master_aschenbrenner/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_aschenbrenner/manifest.json +26 -8
- package/knowledge/solo-test/masters/master_aschenbrenner/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_aschenbrenner/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_aschenbrenner/tools.json +56 -30
- package/knowledge/solo-test/masters/master_asness/decision_policy.json +89 -10
- package/knowledge/solo-test/masters/master_asness/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_asness/manifest.json +25 -8
- package/knowledge/solo-test/masters/master_asness/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_asness/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_asness/tools.json +56 -30
- package/knowledge/solo-test/masters/master_bogle/counterfactuals.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/decision_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/decision_policy.json +170 -0
- package/knowledge/solo-test/masters/master_bogle/doctrine.jsonl +14 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/calibration_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/experiments.json +5 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/golden_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/pairwise_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/failures.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/manifest.json +141 -0
- package/knowledge/solo-test/masters/master_bogle/memory_policy.json +5 -0
- package/knowledge/solo-test/masters/master_bogle/provisional-index.json +41 -0
- package/knowledge/solo-test/masters/master_bogle/research_policy.json +11 -0
- package/knowledge/solo-test/masters/master_bogle/sources.jsonl +1 -0
- package/knowledge/solo-test/masters/master_bogle/tools.json +120 -0
- package/knowledge/solo-test/masters/master_bogle/voice.en.md +7 -0
- package/knowledge/solo-test/masters/master_bogle/voice.zh.md +7 -0
- package/knowledge/solo-test/masters/master_buffett/decision_policy.json +102 -11
- package/knowledge/solo-test/masters/master_buffett/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_buffett/manifest.json +24 -8
- package/knowledge/solo-test/masters/master_buffett/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_buffett/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_buffett/tools.json +55 -29
- package/knowledge/solo-test/masters/master_burry/decision_policy.json +102 -12
- package/knowledge/solo-test/masters/master_burry/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_burry/manifest.json +26 -10
- package/knowledge/solo-test/masters/master_burry/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_burry/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_burry/tools.json +56 -30
- package/knowledge/solo-test/masters/master_cathie_wood/decision_policy.json +74 -12
- package/knowledge/solo-test/masters/master_cathie_wood/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_cathie_wood/manifest.json +26 -10
- package/knowledge/solo-test/masters/master_cathie_wood/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_cathie_wood/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_cathie_wood/tools.json +56 -30
- package/knowledge/solo-test/masters/master_dalio/decision_policy.json +123 -16
- package/knowledge/solo-test/masters/master_dalio/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_dalio/manifest.json +24 -8
- package/knowledge/solo-test/masters/master_dalio/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_dalio/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_dalio/tools.json +56 -30
- package/knowledge/solo-test/masters/master_damodaran/decision_policy.json +58 -10
- package/knowledge/solo-test/masters/master_damodaran/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_damodaran/manifest.json +23 -8
- package/knowledge/solo-test/masters/master_damodaran/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_damodaran/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_damodaran/tools.json +54 -28
- package/knowledge/solo-test/masters/master_druckenmiller/decision_policy.json +89 -10
- package/knowledge/solo-test/masters/master_druckenmiller/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_druckenmiller/manifest.json +25 -8
- package/knowledge/solo-test/masters/master_druckenmiller/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_druckenmiller/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_druckenmiller/tools.json +55 -29
- package/knowledge/solo-test/masters/master_duan_yongping/decision_policy.json +138 -13
- package/knowledge/solo-test/masters/master_duan_yongping/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_duan_yongping/manifest.json +31 -11
- package/knowledge/solo-test/masters/master_duan_yongping/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_duan_yongping/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_duan_yongping/tools.json +82 -30
- package/knowledge/solo-test/masters/master_fisher/decision_policy.json +102 -11
- package/knowledge/solo-test/masters/master_fisher/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_fisher/manifest.json +27 -10
- package/knowledge/solo-test/masters/master_fisher/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_fisher/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_fisher/tools.json +58 -32
- package/knowledge/solo-test/masters/master_forensic_short/decision_policy.json +93 -14
- package/knowledge/solo-test/masters/master_forensic_short/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_forensic_short/manifest.json +20 -8
- package/knowledge/solo-test/masters/master_forensic_short/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_forensic_short/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_forensic_short/tools.json +53 -27
- package/knowledge/solo-test/masters/master_graham/decision_policy.json +103 -12
- package/knowledge/solo-test/masters/master_graham/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_graham/manifest.json +26 -8
- package/knowledge/solo-test/masters/master_graham/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_graham/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_graham/tools.json +67 -28
- package/knowledge/solo-test/masters/master_jhunjhunwala/decision_policy.json +77 -12
- package/knowledge/solo-test/masters/master_jhunjhunwala/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_jhunjhunwala/manifest.json +25 -10
- package/knowledge/solo-test/masters/master_jhunjhunwala/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_jhunjhunwala/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_jhunjhunwala/tools.json +54 -28
- package/knowledge/solo-test/masters/master_klarman/decision_policy.json +105 -14
- package/knowledge/solo-test/masters/master_klarman/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_klarman/manifest.json +22 -6
- package/knowledge/solo-test/masters/master_klarman/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_klarman/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_klarman/tools.json +55 -29
- package/knowledge/solo-test/masters/master_li_lu/decision_policy.json +101 -10
- package/knowledge/solo-test/masters/master_li_lu/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_li_lu/manifest.json +27 -10
- package/knowledge/solo-test/masters/master_li_lu/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_li_lu/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_li_lu/tools.json +58 -32
- package/knowledge/solo-test/masters/master_lynch/decision_policy.json +127 -16
- package/knowledge/solo-test/masters/master_lynch/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_lynch/manifest.json +28 -10
- package/knowledge/solo-test/masters/master_lynch/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_lynch/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_lynch/tools.json +67 -28
- package/knowledge/solo-test/masters/master_marks/decision_policy.json +71 -9
- package/knowledge/solo-test/masters/master_marks/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_marks/manifest.json +25 -10
- package/knowledge/solo-test/masters/master_marks/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_marks/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_marks/tools.json +54 -28
- package/knowledge/solo-test/masters/master_munger/decision_policy.json +141 -16
- package/knowledge/solo-test/masters/master_munger/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_munger/manifest.json +24 -10
- package/knowledge/solo-test/masters/master_munger/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_munger/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_munger/tools.json +52 -26
- package/knowledge/solo-test/masters/master_natenberg/decision_policy.json +59 -11
- package/knowledge/solo-test/masters/master_natenberg/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_natenberg/manifest.json +23 -10
- package/knowledge/solo-test/masters/master_natenberg/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_natenberg/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_natenberg/tools.json +50 -24
- package/knowledge/solo-test/masters/master_pabrai/decision_policy.json +125 -14
- package/knowledge/solo-test/masters/master_pabrai/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_pabrai/manifest.json +22 -6
- package/knowledge/solo-test/masters/master_pabrai/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_pabrai/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_pabrai/tools.json +55 -29
- package/knowledge/solo-test/masters/master_simons/decision_policy.json +59 -11
- package/knowledge/solo-test/masters/master_simons/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_simons/manifest.json +22 -8
- package/knowledge/solo-test/masters/master_simons/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_simons/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_simons/tools.json +43 -30
- package/knowledge/solo-test/masters/master_sinclair/decision_policy.json +59 -11
- package/knowledge/solo-test/masters/master_sinclair/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_sinclair/manifest.json +22 -10
- package/knowledge/solo-test/masters/master_sinclair/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_sinclair/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_sinclair/tools.json +54 -28
- package/knowledge/solo-test/masters/master_soros/decision_policy.json +98 -10
- package/knowledge/solo-test/masters/master_soros/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_soros/manifest.json +24 -11
- package/knowledge/solo-test/masters/master_soros/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_soros/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_soros/tools.json +54 -28
- package/knowledge/solo-test/masters/master_taleb/decision_policy.json +124 -13
- package/knowledge/solo-test/masters/master_taleb/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_taleb/manifest.json +23 -9
- package/knowledge/solo-test/masters/master_taleb/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_taleb/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_taleb/tools.json +50 -24
- package/knowledge/solo-test/masters/master_thorp/decision_policy.json +61 -13
- package/knowledge/solo-test/masters/master_thorp/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_thorp/manifest.json +25 -10
- package/knowledge/solo-test/masters/master_thorp/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_thorp/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_thorp/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/compilation-manifest.json +290 -264
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/price_implied_cash_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/nominal_earnings_yield_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/real_earnings_yield_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/components/tools.json +120 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/expected_return_over_long_bond.derived-proxy-evidence.json +77 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/fundamental_expected_return.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/net_current_asset_surplus_per_share.derived-proxy-evidence.json +77 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/net_current_asset_value_per_share.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/current_cash_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/real_curve_slope.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/implied_equity_risk_premium.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/{reverse_valuation.derived-proxy-evidence.json → premium_versus_long_run_average.derived-proxy-evidence.json} +29 -16
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_curve_impulse.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/components/tools.json +84 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/five_year_opportunity_cost.derived-proxy-evidence.json +102 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/components/tools.json +60 -34
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/reinvestment_spread.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/components/tools.json +55 -29
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/{accounting_rebuilder.derived-proxy-evidence.json → cash_conversion_gap.derived-proxy-evidence.json} +28 -15
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/cash_cover_of_leverage.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/components/tools.json +69 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/defensive_hurdle_base.derived-proxy-evidence.json +89 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/half_normalised_earnings_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/cash_quality_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/real_structural_growth.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/downside_asset_coverage.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/components/tools.json +60 -34
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/cash_backed_decade_return.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/decade_return_over_long_bond.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/components/tools.json +69 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/growth_justified_capitalisation.derived-proxy-evidence.json +89 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/equity_over_corporate_debt.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/components/tools.json +54 -28
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/reported_earnings_cash_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/components/tools.json +52 -26
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/provisional-derivations/{surface_builder.derived-proxy-evidence.json → normalised_skew.derived-proxy-evidence.json} +27 -14
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor_coverage.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/components/tools.json +45 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/{master_natenberg/provisional-derivations/greeks_payoff.derived-proxy-evidence.json → master_simons/provisional-derivations/absolute_session_move.derived-proxy-evidence.json} +17 -17
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/session_move_over_implied.derived-proxy-evidence.json +77 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/volatility_per_unit_of_width.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/financing_burden.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/components/tools.json +52 -26
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/{tail_friction.derived-proxy-evidence.json → normalised_skew.derived-proxy-evidence.json} +27 -14
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_per_unit_of_volatility.derived-proxy-evidence.json +77 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/net_edge.derived-proxy-evidence.json +76 -0
- package/mcp/lib/breadth.mjs +122 -0
- package/mcp/lib/codex.mjs +3 -3
- package/mcp/lib/constants.mjs +76 -25
- package/mcp/lib/council-options.mjs +95 -40
- package/mcp/lib/council-selection.mjs +95 -9
- package/mcp/lib/damodaran.mjs +119 -0
- package/mcp/lib/fred.mjs +246 -0
- package/mcp/lib/fund-holdings-parsers.mjs +297 -0
- package/mcp/lib/fundamentals.mjs +801 -0
- package/mcp/lib/funds.mjs +750 -0
- package/mcp/lib/gates.mjs +149 -15
- package/mcp/lib/grounding.mjs +188 -36
- package/mcp/lib/index-aggregate.mjs +718 -0
- package/mcp/lib/insider-ownership.mjs +149 -0
- package/mcp/lib/instrument-facts.mjs +557 -0
- package/mcp/lib/instruments.mjs +191 -0
- package/mcp/lib/lang.mjs +109 -2
- package/mcp/lib/markdown.mjs +620 -138
- package/mcp/lib/master-catalog.mjs +32 -3
- package/mcp/lib/orchestrator.mjs +1121 -290
- package/mcp/lib/packets.mjs +227 -21
- package/mcp/lib/personas/engine.mjs +44 -31
- package/mcp/lib/personas-v3/compiler.mjs +2 -0
- package/mcp/lib/personas-v3/deterministic-executor.mjs +13 -2
- package/mcp/lib/personas-v3/ga-external-evidence.mjs +3 -2
- package/mcp/lib/personas-v3/ga-gate.mjs +2 -1
- package/mcp/lib/personas-v3/ga-package-evidence.mjs +5 -4
- package/mcp/lib/personas-v3/grounding-adapter.mjs +309 -2
- package/mcp/lib/personas-v3/loader.mjs +10 -7
- package/mcp/lib/personas-v3/production-root.mjs +5 -4
- package/mcp/lib/personas-v3/release-formula-evidence.mjs +14 -7
- package/mcp/lib/personas-v3/release-source-evidence.mjs +2 -1
- package/mcp/lib/personas-v3/releases.mjs +5 -4
- package/mcp/lib/personas-v3/runtime-release-integrity.mjs +6 -5
- package/mcp/lib/personas-v3/semantic-source-adjudication.mjs +2 -1
- package/mcp/lib/personas-v3/semantic-source-extraction.mjs +2 -1
- package/mcp/lib/personas-v3/semantic-source-skeptic-review.mjs +2 -1
- package/mcp/lib/personas-v3/source-acquisition.mjs +10 -3
- package/mcp/lib/personas-v3/source-review-operations.mjs +3 -2
- package/mcp/lib/personas-v3/staging.mjs +22 -3
- package/mcp/lib/prompts.mjs +119 -2
- package/mcp/lib/quotes.mjs +5 -0
- package/mcp/lib/rpc.mjs +101 -42
- package/mcp/lib/run-store.mjs +28 -3
- package/mcp/lib/sec.mjs +32 -0
- package/mcp/lib/tables.mjs +11 -0
- package/mcp/lib/voice.mjs +122 -0
- package/mcp/lib/xbrl-aggregates.mjs +153 -0
- package/mcp/lib/xbrl-series.mjs +339 -0
- package/mcp/lib/xlsx.mjs +155 -0
- package/package.json +5 -5
- package/personas/masters/masters-value/bogle.md +145 -0
- package/schemas/council-evaluation-protocol-v1.schema.json +2 -2
- package/schemas/persona-v3-ai-assisted-solo-profile-v1.schema.json +2 -2
- package/schemas/persona-v3-ai-machine-simulation-v1.schema.json +1 -1
- package/schemas/persona-v3-build-spec-v1.schema.json +3 -3
- package/schemas/persona-v3-release-formula-review-evidence-v1.schema.json +3 -3
- package/schemas/persona-v3-release-manifest-v1.schema.json +6 -6
- package/schemas/persona-v3-release-source-review-evidence-v1.schema.json +3 -3
- package/schemas/persona-v3-tool-graph-v1.schema.json +1 -1
- package/schemas/persona-v3.schema.json +37 -2
- package/schemas/source-review-batch-v1.schema.json +9 -9
- package/scripts/assemble-persona-v3-release.mjs +3 -2
- package/scripts/build-persona-v3-solo-test-packs.mjs +6 -8
- package/scripts/check-persona-v3-ga.mjs +1 -1
- package/scripts/check-persona-v3-production-candidates.mjs +1 -1
- package/scripts/compile-persona-v3-formulas.mjs +19 -18
- package/scripts/doctor.mjs +11 -9
- package/scripts/export-persona-source-review-batch.mjs +1 -1
- package/scripts/generate-persona-v3-drafts.mjs +2 -2
- package/scripts/lib/build-profile.mjs +24 -0
- package/scripts/lib/council-evaluation-protocol.mjs +7 -6
- package/scripts/lib/host-capabilities.mjs +2 -1
- package/scripts/lib/packaged-host-parity.mjs +63 -8
- package/scripts/lib/persona-v3-ai-assisted-solo-status.mjs +6 -4
- package/scripts/lib/persona-v3-ai-formula-review.mjs +6 -5
- package/scripts/lib/persona-v3-ai-machine-simulations.mjs +32 -4
- package/scripts/lib/persona-v3-build-specs.mjs +3 -2
- package/scripts/lib/persona-v3-draft-packs.mjs +2 -2
- package/scripts/lib/persona-v3-formula-pipeline.mjs +11 -10
- package/scripts/lib/persona-v3-production-candidates.mjs +10 -9
- package/scripts/lib/persona-v3-solo-formula-pipeline.mjs +182 -16
- package/scripts/lib/persona-v3-solo-test-packs.mjs +143 -16
- package/scripts/package-smoke.mjs +32 -12
- package/scripts/report-persona-corpus-gaps.mjs +4 -1
- package/scripts/review-persona-v3-solo-formulas.mjs +12 -8
- package/scripts/run-tests.mjs +23 -2
- package/scripts/scaffold-persona-v3-staging.mjs +1 -1
- package/skills/agent-skills-governance/SKILL.md +8 -2
- package/skills/alphacouncil-agent/SKILL.md +60 -9
- package/skills/public-equity-investing/SKILL.md +17 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/change_value_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/power_map.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/compute_power_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/timeline_reverse_valuation.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/crowding_cost_stress.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/factor_decomposer.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/incremental_returns.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_rebuilder.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/capital_structure_reader.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/mispricing_carry.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/capture_valuation_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/cost_adoption_curve.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/debt_driver_stress.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/regime_classifier.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/story_dcf.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/inflection_payoff.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_revision_map.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/opportunity_cost.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/user_value_evidence.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/research_productivity.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/scuttlebutt_graph.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/borrow_catalyst.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/asset_floor.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/normalized_earnings.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/penetration_liquidity.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/promoter_governance.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/cash_catalyst_compare.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/recovery_waterfall.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/promise_integrity_ledger.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/ten_year_return_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/category_classifier.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/story_numbers_check.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/cycle_temperature.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/implied_expectations.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/failure_path_graph.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/incentive_map.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/discrete_payoff.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/leakage_audit.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/oos_cost_test.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/net_edge_sizer.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/realized_vol_forecast.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reflexivity_graph.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reversal_monitor.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/payoff_ruin.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_recalculator.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/fractional_kelly.derived-proxy-evidence.json +0 -64
package/mcp/lib/fred.mjs
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keyless FRED series, with history.
|
|
3
|
+
*
|
|
4
|
+
* The macro block already gives point-in-time market prices, and a snapshot is enough for a
|
|
5
|
+
* level but not for an impulse. A "liquidity impulse" or a "growth regime" computed from one
|
|
6
|
+
* day of quotes is fabricated precision, so those readings need an actual series behind them.
|
|
7
|
+
*
|
|
8
|
+
* `api.stlouisfed.org` requires a key; the CSV graph endpoint does not, and it returns the
|
|
9
|
+
* full observation history. That is the only reason this module exists as a separate feed:
|
|
10
|
+
* everything here is a dated observation published by the source, so it can carry real
|
|
11
|
+
* lineage into the typed-fact pack instead of being asserted at the run's `as_of`.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately NOT here: any single number claiming to be "the regime". The series are
|
|
14
|
+
* inputs. The composites below are named for exactly what they compute and carry their own
|
|
15
|
+
* window, so a reader can disagree with the window rather than with an opaque score.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { LIMITS } from "./constants.mjs";
|
|
19
|
+
import { fetchText } from "./quotes.mjs";
|
|
20
|
+
|
|
21
|
+
const FRED_CSV = "https://fred.stlouisfed.org/graph/fredgraph.csv?id=";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Units are not uniform across FRED and mixing them silently is the obvious way to produce a
|
|
25
|
+
* confident wrong number: WALCL is millions of dollars while RRPONTSYD is billions. Every
|
|
26
|
+
* series therefore declares its scale, and the composites below convert explicitly.
|
|
27
|
+
*/
|
|
28
|
+
export const FRED_SERIES = Object.freeze({
|
|
29
|
+
DGS10: { fact: "macro.long_bond_yield", unit: "percent", label: "10-year Treasury constant maturity" },
|
|
30
|
+
DGS2: { fact: "macro.short_bond_yield", unit: "percent", label: "2-year Treasury constant maturity" },
|
|
31
|
+
DGS3MO: { fact: null, unit: "percent", label: "3-month Treasury constant maturity" },
|
|
32
|
+
T10Y3M: { fact: "macro.term_structure_slope", unit: "percent", label: "10-year minus 3-month Treasury" },
|
|
33
|
+
DFII10: { fact: "macro.real_rate", unit: "percent", label: "10-year TIPS real yield" },
|
|
34
|
+
T5YIE: { fact: "macro.breakeven_inflation", unit: "percent", label: "5-year breakeven inflation" },
|
|
35
|
+
AAA: { fact: "macro.aaa_corporate_yield", unit: "percent", label: "Moody's seasoned Aaa corporate bond yield" },
|
|
36
|
+
BAMLH0A0HYM2: { fact: "macro.credit_spread", unit: "percent", label: "ICE BofA US high yield option-adjusted spread" },
|
|
37
|
+
WALCL: { fact: null, unit: "usd_millions", label: "Federal Reserve total assets" },
|
|
38
|
+
RRPONTSYD: { fact: null, unit: "usd_billions", label: "Overnight reverse repurchase agreements" },
|
|
39
|
+
WTREGEN: { fact: null, unit: "usd_millions", label: "Treasury General Account balance" },
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export function seriesUrl(id) {
|
|
43
|
+
return `${FRED_CSV}${encodeURIComponent(id)}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* FRED writes `.` for a missing observation on a holiday or a not-yet-published date. Those
|
|
48
|
+
* rows are dropped rather than carried forward: a stale value silently reused as today's
|
|
49
|
+
* reading is the failure mode this whole pipeline is built to avoid.
|
|
50
|
+
*/
|
|
51
|
+
export function parseFredCsv(csv, id) {
|
|
52
|
+
const lines = String(csv || "").trim().split(/\r?\n/);
|
|
53
|
+
if (lines.length < 2) throw new Error(`empty FRED series ${id}`);
|
|
54
|
+
const header = lines[0].split(",");
|
|
55
|
+
if (header.length < 2) throw new Error(`unexpected FRED header for ${id}: ${lines[0]}`);
|
|
56
|
+
const observations = [];
|
|
57
|
+
for (const line of lines.slice(1)) {
|
|
58
|
+
const [date, raw] = line.split(",");
|
|
59
|
+
if (!/^\d{4}-\d{2}-\d{2}$/u.test(String(date || "").trim())) continue;
|
|
60
|
+
const value = Number(raw);
|
|
61
|
+
if (!Number.isFinite(value)) continue;
|
|
62
|
+
observations.push({ date: date.trim(), value });
|
|
63
|
+
}
|
|
64
|
+
if (!observations.length) throw new Error(`no numeric observations in FRED series ${id}`);
|
|
65
|
+
return observations;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function fetchFredSeries(id, { signal, asOf = null } = {}) {
|
|
69
|
+
if (!Object.prototype.hasOwnProperty.call(FRED_SERIES, id)) {
|
|
70
|
+
throw new Error(`unknown FRED series: ${id}`);
|
|
71
|
+
}
|
|
72
|
+
const url = seriesUrl(id);
|
|
73
|
+
const observations = parseFredCsv(await fetchText(url, LIMITS.QUOTE_FETCH_MS * 2, signal), id);
|
|
74
|
+
// A historical cutoff must not see observations published after it.
|
|
75
|
+
const visible = asOf ? observations.filter((row) => row.date <= String(asOf).slice(0, 10)) : observations;
|
|
76
|
+
if (!visible.length) throw new Error(`FRED series ${id} has no observation at or before ${asOf}`);
|
|
77
|
+
const last = visible.at(-1);
|
|
78
|
+
return Object.freeze({
|
|
79
|
+
id,
|
|
80
|
+
...FRED_SERIES[id],
|
|
81
|
+
observations: visible,
|
|
82
|
+
latest: last.value,
|
|
83
|
+
// The observation date IS the publication anchor for this feed, so it never has to be
|
|
84
|
+
// stamped with the run time.
|
|
85
|
+
public_at: `${last.date}T00:00:00.000Z`,
|
|
86
|
+
observation_date: last.date,
|
|
87
|
+
source_url: url,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Value `windowDays` calendar days before the latest observation, or null when unavailable. */
|
|
92
|
+
export function valueBefore(series, windowDays) {
|
|
93
|
+
const rows = series?.observations;
|
|
94
|
+
if (!Array.isArray(rows) || !rows.length) return null;
|
|
95
|
+
const cutoff = new Date(`${rows.at(-1).date}T00:00:00Z`);
|
|
96
|
+
cutoff.setUTCDate(cutoff.getUTCDate() - windowDays);
|
|
97
|
+
const target = cutoff.toISOString().slice(0, 10);
|
|
98
|
+
const prior = rows.filter((row) => row.date <= target);
|
|
99
|
+
return prior.length ? prior.at(-1) : null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Where the latest observation sits in its own history, as a 0-1 rank.
|
|
104
|
+
*
|
|
105
|
+
* Reported with the sample it was computed against, because "the 92nd percentile" means
|
|
106
|
+
* nothing without saying percentile of what and since when.
|
|
107
|
+
*/
|
|
108
|
+
export function percentileRank(series, { sinceDays = 365 * 10 } = {}) {
|
|
109
|
+
const rows = series?.observations;
|
|
110
|
+
if (!Array.isArray(rows) || rows.length < 2) return null;
|
|
111
|
+
const start = valueBefore(series, sinceDays);
|
|
112
|
+
const sample = start ? rows.filter((row) => row.date >= start.date) : rows;
|
|
113
|
+
if (sample.length < 30) return null;
|
|
114
|
+
const latest = rows.at(-1).value;
|
|
115
|
+
const below = sample.filter((row) => row.value < latest).length;
|
|
116
|
+
return {
|
|
117
|
+
percentile: Number((below / sample.length).toFixed(4)),
|
|
118
|
+
sample_size: sample.length,
|
|
119
|
+
sample_start: sample[0].date,
|
|
120
|
+
sample_end: rows.at(-1).date,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Fed balance sheet less the two largest sterilising liabilities, in millions of dollars.
|
|
126
|
+
*
|
|
127
|
+
* This is the common "net liquidity" construction, not an official series. It is labelled as
|
|
128
|
+
* derived and its inputs are returned so the arithmetic can be checked, including the
|
|
129
|
+
* billions-to-millions conversion on the reverse repo leg.
|
|
130
|
+
*/
|
|
131
|
+
export function netLiquidity({ walcl, rrp, tga }) {
|
|
132
|
+
if (!walcl?.observations?.length) return null;
|
|
133
|
+
const byDate = (series) => new Map((series?.observations || []).map((row) => [row.date, row.value]));
|
|
134
|
+
const rrpByDate = byDate(rrp);
|
|
135
|
+
const tgaByDate = byDate(tga);
|
|
136
|
+
const nearest = (map, date) => {
|
|
137
|
+
if (!map.size) return null;
|
|
138
|
+
const keys = [...map.keys()].filter((key) => key <= date);
|
|
139
|
+
return keys.length ? map.get(keys.at(-1)) : null;
|
|
140
|
+
};
|
|
141
|
+
const observations = [];
|
|
142
|
+
for (const row of walcl.observations) {
|
|
143
|
+
const rrpValue = nearest(rrpByDate, row.date);
|
|
144
|
+
const tgaValue = nearest(tgaByDate, row.date);
|
|
145
|
+
if (rrpValue === null || tgaValue === null) continue;
|
|
146
|
+
// RRPONTSYD is billions; WALCL and WTREGEN are millions.
|
|
147
|
+
observations.push({ date: row.date, value: row.value - (rrpValue * 1000) - tgaValue });
|
|
148
|
+
}
|
|
149
|
+
if (!observations.length) return null;
|
|
150
|
+
return Object.freeze({
|
|
151
|
+
id: "NET_LIQUIDITY",
|
|
152
|
+
unit: "usd_millions",
|
|
153
|
+
label: "Fed total assets less reverse repo and Treasury General Account",
|
|
154
|
+
derived_from: ["WALCL", "RRPONTSYD", "WTREGEN"],
|
|
155
|
+
observations,
|
|
156
|
+
latest: observations.at(-1).value,
|
|
157
|
+
observation_date: observations.at(-1).date,
|
|
158
|
+
public_at: `${observations.at(-1).date}T00:00:00.000Z`,
|
|
159
|
+
source_url: [walcl.source_url, rrp?.source_url, tga?.source_url].filter(Boolean),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Change in net liquidity over a window, as a fraction of the level at the start of it.
|
|
165
|
+
*
|
|
166
|
+
* A level tells you nothing about direction, and direction is the whole content of this
|
|
167
|
+
* reading, so the window is part of the value and travels with it.
|
|
168
|
+
*/
|
|
169
|
+
export function liquidityImpulse(series, { windowDays = 91 } = {}) {
|
|
170
|
+
const start = valueBefore(series, windowDays);
|
|
171
|
+
if (!start || !series?.observations?.length || !start.value) return null;
|
|
172
|
+
const latest = series.observations.at(-1);
|
|
173
|
+
return {
|
|
174
|
+
value: Number(((latest.value - start.value) / Math.abs(start.value)).toFixed(6)),
|
|
175
|
+
window_days: windowDays,
|
|
176
|
+
from_date: start.date,
|
|
177
|
+
to_date: latest.date,
|
|
178
|
+
from_value: start.value,
|
|
179
|
+
to_value: latest.value,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const REGIME_STATES = Object.freeze([
|
|
184
|
+
"rising_growth_rising_inflation",
|
|
185
|
+
"rising_growth_falling_inflation",
|
|
186
|
+
"falling_growth_rising_inflation",
|
|
187
|
+
"falling_growth_falling_inflation",
|
|
188
|
+
]);
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* The growth/inflation quadrant, from the direction of two market-priced series.
|
|
192
|
+
*
|
|
193
|
+
* Growth uses the curve slope (steepening prices growth and term premium, inversion prices
|
|
194
|
+
* the opposite) and inflation uses the breakeven. Returns null rather than a quadrant when
|
|
195
|
+
* either axis lacks the history to have a direction at all -- an unknown regime is a gap, and
|
|
196
|
+
* a seat that needs one should decline rather than receive a coin flip.
|
|
197
|
+
*/
|
|
198
|
+
export function growthInflationRegime({ slope, breakeven, windowDays = 91 }) {
|
|
199
|
+
const direction = (series) => {
|
|
200
|
+
const start = valueBefore(series, windowDays);
|
|
201
|
+
if (!start || !series?.observations?.length) return null;
|
|
202
|
+
return series.observations.at(-1).value - start.value;
|
|
203
|
+
};
|
|
204
|
+
const growth = direction(slope);
|
|
205
|
+
const inflation = direction(breakeven);
|
|
206
|
+
if (growth === null || inflation === null) return null;
|
|
207
|
+
const state = `${growth >= 0 ? "rising" : "falling"}_growth_${inflation >= 0 ? "rising" : "falling"}_inflation`;
|
|
208
|
+
if (!REGIME_STATES.includes(state)) return null;
|
|
209
|
+
return {
|
|
210
|
+
state,
|
|
211
|
+
window_days: windowDays,
|
|
212
|
+
growth_axis: { series: slope.id, change: Number(growth.toFixed(4)) },
|
|
213
|
+
inflation_axis: { series: breakeven.id, change: Number(inflation.toFixed(4)) },
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export const MACRO_FRED_SERIES = Object.freeze([
|
|
218
|
+
"DGS10", "DGS2", "T10Y3M", "DFII10", "T5YIE", "AAA", "BAMLH0A0HYM2",
|
|
219
|
+
"WALCL", "RRPONTSYD", "WTREGEN",
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Fetch the macro series set concurrently. A failed series is a named gap, never a zero.
|
|
224
|
+
*/
|
|
225
|
+
export async function fetchMacroSeries({ ids = MACRO_FRED_SERIES, signal, asOf = null } = {}) {
|
|
226
|
+
const results = await Promise.all(ids.map((id) => fetchFredSeries(id, { signal, asOf })
|
|
227
|
+
.then((series) => ({ ok: true, id, series }))
|
|
228
|
+
.catch((error) => ({ ok: false, id, error: String(error?.message || error) }))));
|
|
229
|
+
const series = {};
|
|
230
|
+
const unavailable = [];
|
|
231
|
+
for (const result of results) {
|
|
232
|
+
if (result.ok) series[result.id] = result.series;
|
|
233
|
+
else unavailable.push(`FRED ${result.id}: ${result.error}`);
|
|
234
|
+
}
|
|
235
|
+
const liquidity = netLiquidity({ walcl: series.WALCL, rrp: series.RRPONTSYD, tga: series.WTREGEN });
|
|
236
|
+
return {
|
|
237
|
+
series,
|
|
238
|
+
net_liquidity: liquidity,
|
|
239
|
+
liquidity_impulse: liquidity ? liquidityImpulse(liquidity) : null,
|
|
240
|
+
regime: series.T10Y3M && series.T5YIE
|
|
241
|
+
? growthInflationRegime({ slope: series.T10Y3M, breakeven: series.T5YIE })
|
|
242
|
+
: null,
|
|
243
|
+
credit_spread_percentile: series.BAMLH0A0HYM2 ? percentileRank(series.BAMLH0A0HYM2) : null,
|
|
244
|
+
unavailable,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-issuer holdings parsers.
|
|
3
|
+
*
|
|
4
|
+
* Four issuers publish the same thing in four shapes -- iShares as CSV with a preamble, SSGA as
|
|
5
|
+
* an XLSX workbook, Invesco as JSON, Vanguard as a paged JSON feed -- and none of them agrees on
|
|
6
|
+
* a column name or a date format. The parsing lives here so `funds.mjs` reads as fetch, cache
|
|
7
|
+
* and aggregate rather than as a tour of four vendors' quirks.
|
|
8
|
+
*
|
|
9
|
+
* Every parser returns the same record shape and refuses rather than guessing: a row with no
|
|
10
|
+
* resolvable weight is dropped and counted, not defaulted to zero.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readWorkbook, unzip, xlsxRows, xmlText } from "./xlsx.mjs";
|
|
14
|
+
|
|
15
|
+
const WEIGHT_SUM_TOLERANCE = 0.02;
|
|
16
|
+
|
|
17
|
+
/** The one record shape every issuer's rows are normalised into. */
|
|
18
|
+
const holding = ({ ticker, name, weight, units, asset_class = null }) => ({
|
|
19
|
+
ticker: ticker ? String(ticker).trim().toUpperCase() : null,
|
|
20
|
+
name: name ? String(name).trim() : null,
|
|
21
|
+
weight,
|
|
22
|
+
units,
|
|
23
|
+
asset_class,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parse the SSGA daily holdings workbook.
|
|
28
|
+
*
|
|
29
|
+
* The sheet opens with a few label/value rows (fund name, ticker, "As of 27-Jul-2026") before
|
|
30
|
+
* the table, and closes with disclosure prose, so the header row is located by content rather
|
|
31
|
+
* than by a fixed offset -- SSGA moves it when the disclaimer text changes length.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Merge Vanguard's pages, refusing an incomplete pagination.
|
|
35
|
+
*
|
|
36
|
+
* Each page states the fund's full `size`, so a short walk is detectable. This matters more
|
|
37
|
+
* than usual here because the payload's own `next` link is dead: a caller that trusts it gets
|
|
38
|
+
* page one and a fund that looks like it holds 500 names.
|
|
39
|
+
*/
|
|
40
|
+
/**
|
|
41
|
+
* Parse Invesco's cache payload, refusing a silently truncated one.
|
|
42
|
+
*
|
|
43
|
+
* `loadType=initial` returns 10 holdings while `totalNumberOfHoldings` still says 108. The
|
|
44
|
+
* count the issuer states about itself is therefore the check: if it disagrees with the array
|
|
45
|
+
* it shipped, the file is short and no weight computed from it means anything.
|
|
46
|
+
*/
|
|
47
|
+
/**
|
|
48
|
+
* Parse an iShares holdings CSV, refusing the HTML-body-with-HTTP-200 trap.
|
|
49
|
+
*
|
|
50
|
+
* The retired `.ajax?fileType=csv` endpoint returns status 200 and `Content-Type: text/csv`
|
|
51
|
+
* and a full HTML product page as the body. Nothing about the response envelope reveals this,
|
|
52
|
+
* so the check is on the first bytes of the body: a status code and a content type are both
|
|
53
|
+
* claims made by the server, and here both are false.
|
|
54
|
+
*/
|
|
55
|
+
/**
|
|
56
|
+
* Do the published weights add up to the whole fund?
|
|
57
|
+
*
|
|
58
|
+
* A holdings file that sums to 0.62 is a truncated download, not a concentrated fund, and it
|
|
59
|
+
* is the failure every adapter here can suffer. This never repairs the weights by rescaling:
|
|
60
|
+
* rescaling a truncated file produces a plausible-looking portfolio that does not exist.
|
|
61
|
+
*/
|
|
62
|
+
/** RFC4180-ish field splitter; iShares quotes every value and embeds commas inside them. */
|
|
63
|
+
/** Issuer numbers arrive as "1,167,700,000.00", "7.75" or "1.81367013E8". */
|
|
64
|
+
/**
|
|
65
|
+
* The issuers state their date in three different shapes and none of them is ISO. A date this
|
|
66
|
+
* module cannot parse becomes null, which downstream reports as a gap -- it never falls back
|
|
67
|
+
* to "today", because stamping a run time onto an issuer's file is how stale holdings start
|
|
68
|
+
* looking fresh.
|
|
69
|
+
*/
|
|
70
|
+
const MONTHS = Object.freeze({
|
|
71
|
+
jan: "01", feb: "02", mar: "03", apr: "04", may: "05", jun: "06",
|
|
72
|
+
jul: "07", aug: "08", sep: "09", oct: "10", nov: "11", dec: "12",
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export function isoDate(text) {
|
|
76
|
+
const raw = String(text || "").trim().replace(/^as of\s+/iu, "");
|
|
77
|
+
if (!raw) return null;
|
|
78
|
+
const iso = /^(\d{4}-\d{2}-\d{2})/u.exec(raw);
|
|
79
|
+
if (iso) return iso[1];
|
|
80
|
+
// "Jul 27, 2026" (iShares)
|
|
81
|
+
const mdy = /^([A-Za-z]{3})[a-z]*\.?\s+(\d{1,2}),?\s+(\d{4})$/u.exec(raw);
|
|
82
|
+
if (mdy && MONTHS[mdy[1].toLowerCase()]) {
|
|
83
|
+
return `${mdy[3]}-${MONTHS[mdy[1].toLowerCase()]}-${String(mdy[2]).padStart(2, "0")}`;
|
|
84
|
+
}
|
|
85
|
+
// "27-Jul-2026" (SSGA)
|
|
86
|
+
const dmy = /^(\d{1,2})-([A-Za-z]{3})[a-z]*-(\d{4})$/u.exec(raw);
|
|
87
|
+
if (dmy && MONTHS[dmy[2].toLowerCase()]) {
|
|
88
|
+
return `${dmy[3]}-${MONTHS[dmy[2].toLowerCase()]}-${String(dmy[1]).padStart(2, "0")}`;
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function numeric(value) {
|
|
94
|
+
if (value === null || value === undefined) return null;
|
|
95
|
+
const cleaned = String(value).replace(/[",\s%]/gu, "");
|
|
96
|
+
if (!cleaned || cleaned === "-") return null;
|
|
97
|
+
const parsed = Number(cleaned);
|
|
98
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function csvFields(line) {
|
|
102
|
+
const out = [];
|
|
103
|
+
let field = "";
|
|
104
|
+
let quoted = false;
|
|
105
|
+
for (let i = 0; i < line.length; i += 1) {
|
|
106
|
+
const ch = line[i];
|
|
107
|
+
if (quoted) {
|
|
108
|
+
if (ch === '"' && line[i + 1] === '"') { field += '"'; i += 1; continue; }
|
|
109
|
+
if (ch === '"') { quoted = false; continue; }
|
|
110
|
+
field += ch;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (ch === '"') { quoted = true; continue; }
|
|
114
|
+
if (ch === ",") { out.push(field); field = ""; continue; }
|
|
115
|
+
field += ch;
|
|
116
|
+
}
|
|
117
|
+
out.push(field);
|
|
118
|
+
return out.map((cell) => cell.trim());
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function checkWeightSum(holdings, { tolerance = WEIGHT_SUM_TOLERANCE } = {}) {
|
|
122
|
+
const sum = (holdings || []).reduce((total, row) => total + (Number(row?.weight) || 0), 0);
|
|
123
|
+
const ok = Number.isFinite(sum) && Math.abs(sum - 1) <= tolerance;
|
|
124
|
+
return {
|
|
125
|
+
ok,
|
|
126
|
+
sum: Number(sum.toFixed(6)),
|
|
127
|
+
tolerance,
|
|
128
|
+
gap: ok ? null : `holdings weights sum to ${sum.toFixed(4)}, not ~1 (tolerance ${tolerance}); treat the file as incomplete`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function parseIsharesHoldingsCsv(csv, { symbol = null } = {}) {
|
|
133
|
+
const text = String(csv || "");
|
|
134
|
+
const head = text.slice(0, 512).trimStart();
|
|
135
|
+
if (!head) throw new Error("iShares holdings response was empty");
|
|
136
|
+
if (head.startsWith("<") || /<!doctype html|<html[\s>]/iu.test(head)) {
|
|
137
|
+
throw new Error("iShares returned an HTML document with a CSV content-type (the retired .ajax holdings path does this at HTTP 200); use the /x/latest-holdings.csv path");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const lines = text.split(/\r?\n/);
|
|
141
|
+
const headerIndex = lines.findIndex((line) => /^"?Ticker"?\s*,\s*"?Name"?/u.test(line.trim()));
|
|
142
|
+
if (headerIndex < 0) throw new Error("iShares CSV has no `Ticker,Name` holdings header row");
|
|
143
|
+
|
|
144
|
+
// The block above the table carries the fund name, the stated date and shares outstanding.
|
|
145
|
+
const meta = new Map();
|
|
146
|
+
for (const line of lines.slice(0, headerIndex)) {
|
|
147
|
+
const cells = csvFields(line);
|
|
148
|
+
if (cells.length >= 2 && cells[0]) meta.set(cells[0].replace(/:$/u, "").toLowerCase(), cells[1]);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const columns = csvFields(lines[headerIndex]);
|
|
152
|
+
const at = (row, label) => {
|
|
153
|
+
const index = columns.findIndex((column) => column.toLowerCase() === label);
|
|
154
|
+
return index >= 0 ? row[index] : null;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const holdings = [];
|
|
158
|
+
for (const line of lines.slice(headerIndex + 1)) {
|
|
159
|
+
if (!line.trim()) break; // a blank line ends the table; disclosure sections follow
|
|
160
|
+
const row = csvFields(line);
|
|
161
|
+
const ticker = at(row, "ticker");
|
|
162
|
+
const weight = numeric(at(row, "weight (%)"));
|
|
163
|
+
if (!ticker || weight === null) continue;
|
|
164
|
+
holdings.push(holding({
|
|
165
|
+
ticker,
|
|
166
|
+
name: at(row, "name"),
|
|
167
|
+
weight: weight / 100,
|
|
168
|
+
units: numeric(at(row, "quantity")),
|
|
169
|
+
asset_class: at(row, "asset class"),
|
|
170
|
+
}));
|
|
171
|
+
}
|
|
172
|
+
if (!holdings.length) throw new Error("iShares CSV holdings table has no rows");
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
symbol,
|
|
176
|
+
issuer: "ishares",
|
|
177
|
+
fund_name: lines[0] ? csvFields(lines[0])[0] || null : null,
|
|
178
|
+
as_of: isoDate(meta.get("fund holdings as of")),
|
|
179
|
+
shares_outstanding: numeric(meta.get("shares outstanding")),
|
|
180
|
+
holdings,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function parseInvescoHoldings(payload, { symbol = null } = {}) {
|
|
185
|
+
const data = typeof payload === "string" ? JSON.parse(payload) : payload;
|
|
186
|
+
if (!data || typeof data !== "object") throw new Error("invesco holdings payload was not an object");
|
|
187
|
+
const rows = data.holdings;
|
|
188
|
+
if (!Array.isArray(rows) || !rows.length) throw new Error("invesco holdings payload carried no holdings array");
|
|
189
|
+
|
|
190
|
+
const declared = Number(data.totalNumberOfHoldings);
|
|
191
|
+
if (Number.isFinite(declared) && declared !== rows.length) {
|
|
192
|
+
throw new Error(`invesco returned ${rows.length} holdings but declares ${declared}; the response is truncated (loadType=initial does this at HTTP 200)`);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const asOf = isoDate(data.effectiveDate || data.effectiveBusinessDate);
|
|
196
|
+
if (!asOf) throw new Error("invesco holdings payload carried no parseable effectiveDate");
|
|
197
|
+
|
|
198
|
+
const holdings = rows.map((row) => holding({
|
|
199
|
+
ticker: row?.ticker,
|
|
200
|
+
name: row?.issuerName,
|
|
201
|
+
weight: (numeric(row?.percentageOfTotalNetAssets) ?? 0) / 100,
|
|
202
|
+
units: numeric(row?.units),
|
|
203
|
+
// Nasdaq-100 files carry index futures, currency collateral and several cash sleeves
|
|
204
|
+
// alongside common stock. Look-through must be able to tell them apart.
|
|
205
|
+
asset_class: row?.securityTypeName || null,
|
|
206
|
+
}));
|
|
207
|
+
|
|
208
|
+
return { symbol, issuer: "invesco", fund_name: null, as_of: asOf, shares_outstanding: null, holdings };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export function parseVanguardHoldings(pages, { symbol = null } = {}) {
|
|
212
|
+
const list = (Array.isArray(pages) ? pages : [pages])
|
|
213
|
+
.map((page) => (typeof page === "string" ? JSON.parse(page) : page))
|
|
214
|
+
.filter(Boolean);
|
|
215
|
+
if (!list.length) throw new Error("vanguard holdings response was empty");
|
|
216
|
+
|
|
217
|
+
const entities = list.flatMap((page) => (Array.isArray(page?.fund?.entity) ? page.fund.entity : []));
|
|
218
|
+
if (!entities.length) throw new Error("vanguard holdings payload carried no entities");
|
|
219
|
+
|
|
220
|
+
const declared = Number(list[0]?.size);
|
|
221
|
+
if (Number.isFinite(declared) && declared !== entities.length) {
|
|
222
|
+
throw new Error(`vanguard returned ${entities.length} holdings but declares ${declared}; pagination is incomplete (the payload's own next link points at the dead api.vanguard.com host)`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const asOf = isoDate(String(list[0]?.asOfDate || "").slice(0, 10));
|
|
226
|
+
if (!asOf) throw new Error("vanguard holdings payload carried no parseable asOfDate");
|
|
227
|
+
|
|
228
|
+
const holdings = entities.map((row) => holding({
|
|
229
|
+
ticker: row?.ticker,
|
|
230
|
+
name: row?.longName || row?.shortName,
|
|
231
|
+
weight: (numeric(row?.percentWeight) ?? 0) / 100,
|
|
232
|
+
units: numeric(row?.sharesHeld),
|
|
233
|
+
asset_class: row?.secMainType || null,
|
|
234
|
+
}));
|
|
235
|
+
|
|
236
|
+
return {
|
|
237
|
+
symbol,
|
|
238
|
+
issuer: "vanguard",
|
|
239
|
+
fund_name: null,
|
|
240
|
+
as_of: asOf,
|
|
241
|
+
shares_outstanding: null,
|
|
242
|
+
holdings,
|
|
243
|
+
// Month-end, not daily. A reader comparing this to a daily iShares file needs to know.
|
|
244
|
+
cadence: "month_end",
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function parseSsgaHoldingsXlsx(buffer, { symbol = null } = {}) {
|
|
249
|
+
const entries = unzip(buffer);
|
|
250
|
+
const sheet = entries.get("xl/worksheets/sheet1.xml");
|
|
251
|
+
if (!sheet) throw new Error("SSGA workbook has no xl/worksheets/sheet1.xml");
|
|
252
|
+
const sharedXml = entries.get("xl/sharedStrings.xml");
|
|
253
|
+
const shared = sharedXml
|
|
254
|
+
? [...sharedXml().matchAll(/<si>([\s\S]*?)<\/si>/gu)].map((match) => xmlText(match[1]))
|
|
255
|
+
: [];
|
|
256
|
+
const rows = xlsxRows(sheet(), shared);
|
|
257
|
+
|
|
258
|
+
const label = (needle) => {
|
|
259
|
+
const row = rows.find((cells) => String(cells?.[0] || "").toLowerCase().startsWith(needle));
|
|
260
|
+
return row ? row.slice(1).find((cell) => cell) || null : null;
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const headerIndex = rows.findIndex((cells) => {
|
|
264
|
+
const lower = (cells || []).map((cell) => String(cell || "").toLowerCase());
|
|
265
|
+
return lower.includes("ticker") && lower.includes("weight");
|
|
266
|
+
});
|
|
267
|
+
if (headerIndex < 0) throw new Error("SSGA workbook has no `Ticker`/`Weight` header row");
|
|
268
|
+
const columns = rows[headerIndex].map((cell) => String(cell || "").toLowerCase());
|
|
269
|
+
const at = (row, name) => {
|
|
270
|
+
const index = columns.indexOf(name);
|
|
271
|
+
return index >= 0 ? row[index] : null;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const holdings = [];
|
|
275
|
+
for (const row of rows.slice(headerIndex + 1)) {
|
|
276
|
+
const ticker = at(row, "ticker");
|
|
277
|
+
const weight = numeric(at(row, "weight"));
|
|
278
|
+
if (!ticker || weight === null) continue;
|
|
279
|
+
holdings.push(holding({
|
|
280
|
+
ticker,
|
|
281
|
+
name: at(row, "name"),
|
|
282
|
+
weight: weight / 100,
|
|
283
|
+
units: numeric(at(row, "shares held")),
|
|
284
|
+
asset_class: at(row, "sector"),
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
if (!holdings.length) throw new Error("SSGA workbook holdings table has no rows");
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
symbol,
|
|
291
|
+
issuer: "ssga",
|
|
292
|
+
fund_name: label("fund name"),
|
|
293
|
+
as_of: isoDate(label("holdings")),
|
|
294
|
+
shares_outstanding: numeric(label("shares outstanding")),
|
|
295
|
+
holdings,
|
|
296
|
+
};
|
|
297
|
+
}
|