AUTHOR: Tony Mudau
Closed-loop remediation (Phases 1–4)
This document describes the concrete implementation of the remediation plan: wiring closed trades into technical memory, execution guards, performance adaptation, decision snapshots, and where to observe metrics.
Phase 1 — Closed trades → technical memory + idempotent sync
Modules
agents/memory_learning.py— SQLite rollups (symbol_trade_stats,setup_outcome_stats),apply_learning_from_closed_trade_id,reprocess_unprocessed_closed_trades, public aliassync_closed_trades_to_technical_memory.agents/common.py—trade_historyinserts/updates;close_trade_history_by_tickettriggers learning after a close.
Schema (trade_history)
memory_synced INTEGER DEFAULT 0— primary idempotency flag once a closed row has been rolled into stats andrecord_trade_outcome(technical file memory) has run.learning_processed— legacy mirror; both are set to1on success. Existing rows withlearning_processed=1are backfilled tomemory_synced=1on migration.entry_context_json,entry_mtf_json— optional persisted decision context at entry (not close): core indicators vs H1/D1/HTF fields split fromentry_learningso learning reflects the decision environment even ifextra_contextis trimmed later.
Resolution order when a trade closes
apply_learning_from_closed_trade_id builds the fingerprint using resolve_entry_learning_from_row: prefer entry_context_json + entry_mtf_json, else extra_context.entry_learning.
Who writes entry columns
insert_trade_history_row/update_trade_history_for_execution(statusopen) derive JSON columns fromextra_context["entry_learning"]via_serialize_entry_learning_for_columnsincommon.py.
Orchestration
_build_entry_learning_snapshotinorchestration_agent/main.pystoressession_labelwith other fields insideextra_context["entry_learning"]for schedule and execute-now paths.
Phase 2 — Freshness and stale-thesis guards
Module: agents/execution_guards.py
evaluate_execution_guards(mt5_tools, proposal, timeframe=..., extra_context=...)- Stale bars: last closed bar time vs now; max age =
EXEC_GUARD_BAR_AGE_MULT× bar duration (timeframe_seconds). - Slippage vs proposal entry: compares live bid/ask to
proposal["entry"]againstEXEC_GUARD_MAX_SLIPPAGE_PCT. - Optional technical agreement: if
EXEC_GUARD_REQUIRE_TECH_AGREEMENTis true, a short-window close trend must align withproposal["direction"](micro trend from recent closes).
- Stale bars: last closed bar time vs now; max age =
- When MT5 is unavailable, bar/tick checks are skipped (documented in the guard result
detail); unit tests injectlast_bar_time_utc/execution_bid/execution_ask. record_guard_rejectionappends toexecution_guard_eventsfor dashboards.guard_rejection_count_sincesupports rolling counts.
Wiring: agents/execution_agent/main.py — execute_market_order runs guards before execute_market. On failure it returns {"skipped": True, "reason": ...}, updates trade_history with status skipped_guard, and records a decision snapshot when one was provided.
Scheduler: scheduled_trades.proposal_context_json (JSON) stores proposal_entry, timeframe, extra_context snapshot at schedule time. _scheduler_loop merges this into proposal and extra_context so guards see the original entry and timeframe.
Settings: app/config.py — EXEC_GUARD_*, EXEC_GUARD_REQUIRE_TECH_AGREEMENT.
Phase 3 — Performance-aware adaptation
Module: agents/performance_adaptation.py
symbol_adaptation_flags— recent win rate overADAPT_SYMBOL_LOOKBACK; may setsymbol_pausedor reducelot_multipliervsADAPT_SYMBOL_WINRATE_THRESHOLD/ADAPT_SYMBOL_LOT_SCALE.on_closed_trade_for_adaptation— called fromapply_learning_from_closed_trade_idafter rollups: maintainspattern_loss_streaks(persetup_fingerprint) andsession_trade_stats. AfterADAPT_PATTERN_LOSS_STREAKconsecutive losses on the same fingerprint,blocked_untilis set forADAPT_PATTERN_COOLDOWN_HOURS.is_pattern_in_cooldown/effective_min_proposal_confidence— gates used in orchestration before duplicate/execute logic.session_confidence_delta— if a session bucket is weak (enough trades, low win rate, losses ≥ wins), the minimum proposal confidence is raised byADAPT_SESSION_CONFIDENCE_BUMP.
Orchestration: after portfolio + risk, adaptation may clear proposal (paused symbol, pattern cooldown, or session confidence floor).
Risk: risk_agent/main.py applies symbol_adaptation_flags["lot_multiplier"] again as a final lot scale (orchestration pause already removed bad symbols).
Settings: ADAPT_* keys in app/config.py.
Phase 4 — Decision snapshots (auditable intent)
Module: agents/decision_snapshots.py
build_decision_snapshot(...)— portfolio precheck subset, technical confidence/direction/strategy, MTF summary fields, optional reversal guard keys, final proposal confidence, risk block,entry_learning, timestamps.insert_trade_decision_snapshot(trade_history_id, payload)— tabletrade_decision_snapshots(trade_history_id, optionalscheduled_trade_id,symbol,snapshot_json).
Wiring: Orchestration builds a snapshot after adaptation passes and attaches it as extra_context["decision_snapshot"]. ExecutionAgent.execute_market_order persists it after update_trade_history_for_execution returns an id (including guard-skipped paths when a snapshot exists).
Suggested operational metrics
Daily or rolling SQL / exports:
| Metric | Source |
|---|---|
| Win rate, expectancy, net PnL by symbol | trade_history (status='closed'), symbol_trade_stats |
| Win rate by strategy mode | setup_outcome_stats / fingerprint includes strategy_mode |
| Win rate by session | session_trade_stats |
| Average adverse excursion | Not yet computed in SQL (would need tick/high-water marks per ticket) |
| Signal → execution latency | decision_snapshot.signal_generated_at vs execution_started_at; scheduled path: proposal_context_json.signal_scheduled_at |
| Stale-thesis / guard rejections | execution_guard_events; guard_rejection_count_since |
Tests
backend/tests/test_remediation_phases.py — isolated DB via monkeypatch on DB_PATH (use pathlib.Path). Covers memory sync + entry columns, guard staleness/slippage, pattern cooldown, snapshot insert, and sync_closed_trades_to_technical_memory.
Run:
python -m pytest tests/test_remediation_phases.py -v
Related files (quick index)
| Area | Files |
|---|---|
| DB path / history CRUD | agents/common.py |
| Learning + sync API | agents/memory_learning.py |
| Guards + metrics table | agents/execution_guards.py |
| Adaptation + pattern/session tables | agents/performance_adaptation.py |
| Snapshots | agents/decision_snapshots.py |
| Cycle + scheduler | agents/orchestration_agent/main.py |
| Execution | agents/execution_agent/main.py |
| Lot scaling | agents/risk_agent/main.py |
| Tunables | app/config.py |