Revert DB-first feature fix — Oracle real-time enrichment must be primary

The DB-first approach (prefer feature_json over Oracle recalculation) caused:
- LMND (+$782) and M (+$1,052) trades to disappear
- TEM loss to increase from -$321 to -$535
- Overall PnL drop from +$5,948 to +$3,078

Root cause: DB features were computed at a different time with different
Oracle data. When paper trader used DB values, the feature values didn't
match what the backtester's Parquet snapshot had, causing different
engine gate outcomes.

Paper trader must use Oracle real-time enrichment as primary source
(same as the original design). The volume_ratio_20d field name fix
is retained as that was a genuine bug.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
main
I Luk Kim 5 months ago
parent f0baa48e7b
commit 0797535047

@ -135,15 +135,11 @@ class EventDetector:
if not enriched.get("reaction_day_high"):
enriched["reaction_day_high"] = sym_bars[rd].get("high")
# Compute market features from Oracle bars ONLY if missing in DB
# feature_json. DB values are authoritative because they were computed
# by the feature_builder at event time with the correct reaction_date
# and base price. Oracle bars can produce different values due to
# non-deterministic data or different date alignment.
_db_has_reaction = enriched.get("reaction_day_return") is not None
# Compute market features from Oracle bars if missing in DB feature_json.
# These can be None when the feature builder ran before reaction-day bars settled.
sym_bars = bars_by_symbol.get(sym, {})
rd = _parse_date(enriched.get("reaction_date"))
if rd and rd in sym_bars and not _db_has_reaction:
if rd and rd in sym_bars:
sorted_dates = sorted(sym_bars.keys())
try:
rd_idx = sorted_dates.index(rd)

Loading…
Cancel
Save