Strategy_concepts_1.md 3.6 KB

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

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:

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. Tick cadence

Strategies declare cadence with TICK_MINUTES. The runtime heartbeats every 6 seconds and schedules strategies from that value.

  • TICK_MINUTES = 1.0 means about 10 heartbeat steps
  • decimals are allowed, so 2.1 is valid

5. Reconciliation

The engine reconciles persisted records against runtime instances when records change and at startup.

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.

unload_instance(id)
load_instance(updated_record)

This is the clean default because it is deterministic and easy to debug.

Selective state carryover is not part of the current model, 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 shows:

  • identity
  • config
  • current mode
  • runtime status
  • rendered widgets

It does 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