Fix live option guards, grounding operand evidence, source-bound benchmarks, trade artifacts, attribution, drawdowns, valuation tolerances, and SEC point-in-time factor inputs.
Add Brazil research data and market support, 13 fundamental and valuation factors, channel progress forwarding, and opt-in ZimaOS templates. Update seven README News sections with three visible dates.
Validation: 17,635 backend tests passed; 1,084 final targeted tests and 103 frontend tests passed. Frontend build, package build, documentation checks, and CI gates passed.
#1368 relaxed the benchmark availability check from the whole run to the
regime's own bars, but `_bar_returns` reads `series[index - 1]` — the
anchor bar is outside `bar_indices` by construction, so verifying the
regime's own bars verifies nothing about it. A single unparseable
benchmark cell before a regime's first bar then reached `previous <= 0`
as None; `rebuild_evidence`'s except swallowed the TypeError and the
WHOLE run produced no evidence rows. A missing endpoint now yields no
return for that bar, exactly as a non-finite one already did.
#1369 fixed the bare `M2K` form but not its dated contracts: `M2KZ4`
still extracted `M` and silently took the `_MULTIPLIER.get(product, 50)`
default. Resolve a symbol against the multiplier table first, longest
match wins — which subsumes the PR's own month-code-collision special
case (MYM2503, FESX2503), covers the embedded-digit forms it missed, and
keeps SILZ4 as micro silver rather than SI. A product absent from the
table still falls through to the shape regexes.
Mutation-checked both ways: reverting the None guard fails the two new
strategy-discovery tests with the original TypeError; dropping the
listed-product lookup fails six global-futures cases.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
compute_evidence_for_run resolved exposure-derived position sizing a
single time before the per-regime loop, so every regime's breakeven
fee calculation used the same whole-run average exposure. A strategy
that runs small in a bear regime and large in a bull regime got one
blended size applied to both, understating breakeven costs for the
regime that actually ran smaller and overstating them for the one
that ran larger.
Move the position-size resolution inside the loop so each regime uses
only its own bars' exposure. This also fixes read_equity_series, whose
exposure column was returned as a compacted list with entries dropped
for non-positive or missing values, so it no longer lined up
positionally with bar index. Exposure is now aligned to bar position
like the existing benchmark column, with None marking bars that lack a
usable value, so per-regime slicing by bar index is correct.
Also scopes the benchmark-completeness check for excess return to the
regime's own bar_indices instead of the whole run's benchmark list.
Signed-off-by: Lanre Shittu <136805224+Shizoqua@users.noreply.github.com>
Implements #969 Phase 2 over the Phase 1 facade (#978). The evidence cache
is no longer empty-by-construction and no longer silent about age:
- refresh_strategy_evidence: agent tool (primary, scheduler-reachable) +
MCP wrapper + 'vibe-trading strategy-evidence refresh --manifest' CLI.
Manifest-driven only — runs carry no attribution, so explicit
{strategy_id, run_dir, position_size} specs are the honest path; entries
outside the runtime runs root / allowed run roots are skipped with a
stable path-outside-allowed-roots reason. Writes only the disposable
facade-owned cache.
- backtest-diagnose hookup: the skill's Hard-Gate Checklist becomes the
evidence ingestion gate — state.json success, metrics.csv present,
trade_count > 0, equity present and NaN-free, each with a stable
hard-gate:* skip token. NaN-equity runs are refused entirely instead of
yielding partial-curve evidence (fixes the Phase-1 silent-skip latent).
- atomic rebuild: compute all rows first, then one transaction swaps the
store — a failed rebuild can no longer leave the cache empty.
- decay status surfaced in query_strategies / get_strategy_evidence:
freshness computed at read time from the evidence-window age
(fresh/aging/stale, 90/180-day thresholds tied to the quarterly
re-backtest cadence; last_verified reported but never gating). Stale rows
fail closed out of default recommendations (include_stale opt-out);
sdm:* rows mirror the SDM lifecycle (decayed/disabled never recommended,
sdm-lifecycle: prefix); unparseable windows fail closed to stale.
Decay is never persisted — a stored decay field would go stale by
definition.
- docs + count sync: strategy-discovery SKILL.md gains the Decay &
Freshness Contract and Populating & Refreshing Evidence sections;
backtest-diagnose SKILL.md documents the gate hookup; phantom-guard test
now asserts every tool named in the SKILL.md recipe is registered;
MCP tools 73 -> 74 across five READMEs + agent/SKILL.md (65 -> 66
decorators).