# Strategy Engine Architecture ## 1. Overview This document describes how strategy definitions become running instances in `trader-mcp`. The design separates: - strategy definition - persisted instance record - runtime execution - dashboard rendering ## 2. Core Concepts ### 2.1 Strategy definition A strategy definition is reusable code, usually a Python module, that exposes the strategy class and behavior. It typically defines: - `init()` - `on_tick()` - `render()` - `CONFIG_SCHEMA` ### 2.2 Strategy instance A strategy instance is a configured, uniquely identifiable deployment of a strategy definition. It has: - immutable identity - mutable config - runtime state - execution mode #### Immutable identity Examples: - `id` - `strategy_type` - `account` - `market` These fields should be stable and audit-friendly. #### Mutable config Config is user-editable and persistent. It is stored as JSON in the database and supplied to the strategy on load. #### Runtime state State is owned by the strategy instance and is not part of persistent config. ## 3. System Model ```text Strategy Definition -> Persisted Instance Record -> Running Instance -> UI View ``` The database stores desired state. The engine reconciles runtime from that desired state. ## 4. Modes Instances should use a small mode set: ```text off, observe, active ``` ### Meaning - `off`, not instantiated, no ticks, no trading - `observe`, instantiated, ticks enabled, trading disabled - `active`, instantiated, ticks enabled, trading enabled ### Mode transitions - `off` <-> `observe` is the power toggle - `observe` <-> `active` is the activation toggle - activation should be disabled while mode is `off` ### Paused runtime state `paused` is not a persisted mode. It is a runtime freeze state controlled by the engine. - the instance stays loaded - ticks are skipped - trading is skipped - render can be skipped while paused This keeps the stored mode model small while still allowing a temporary freeze. ## 5. Reconciliation The engine should reconcile persisted records against runtime instances when records change or at startup. ```python def reconcile(): for record in db.instances: if record.mode != "off" and record.id not in running: load_instance(record) if record.mode == "off" and record.id in running: unload_instance(record.id) ``` ## 6. Config Reload Semantics Config changes should normally trigger a reload. ```text unload_instance(id) load_instance(updated_record) ``` This is the clean default because it is deterministic and easy to debug. Selective state carryover can exist later, but reload is the default. ## 7. Engine Responsibilities The engine should: - load strategy modules - instantiate strategies with context + config - manage lifecycle - tick loaded strategies - render on demand - enforce execution mode through the context, including binding the instance `account_id` and `client_id` when orders are sent to exec-mcp ## 8. Dashboard Responsibilities The dashboard should show: - identity - config - current mode - runtime status - rendered widgets It should not own trading logic. ## 9. Recommended Direction The architecture is strongest when: - config is declarative - state is instance-local - context is capability-only and may enrich calls with the instance `account_id` and `client_id` - reload is the default config update mechanism - the database is the source of truth