|
|
@@ -0,0 +1,399 @@
|
|
|
+# Strategy Engine Architecture – Concept Paper
|
|
|
+
|
|
|
+## 1. Overview
|
|
|
+
|
|
|
+This document defines a modular architecture for a strategy execution system consisting of:
|
|
|
+
|
|
|
+* A **host engine**
|
|
|
+* Pluggable **strategy modules**
|
|
|
+* Configurable **strategy instances**
|
|
|
+* A **dashboard UI**
|
|
|
+
|
|
|
+The system separates **definition**, **configuration**, **execution**, and **visualization** into clearly distinct layers.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 2. Core Concepts
|
|
|
+
|
|
|
+### 2.1 Strategy Definition
|
|
|
+
|
|
|
+A strategy is a Python module that defines:
|
|
|
+
|
|
|
+* Logic (`on_tick`)
|
|
|
+* State initialization (`init`)
|
|
|
+* Runtime visualization (`render`)
|
|
|
+* Configuration schema (`CONFIG_SCHEMA`)
|
|
|
+
|
|
|
+Characteristics:
|
|
|
+
|
|
|
+* Stateless at definition level
|
|
|
+* Reusable across multiple instances
|
|
|
+* Stored as a single `.py` file (optionally + config)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2.2 Strategy Instance
|
|
|
+
|
|
|
+A strategy instance represents a **configured and uniquely identifiable deployment** of a strategy.
|
|
|
+
|
|
|
+#### Immutable Identity
|
|
|
+
|
|
|
+Defined at creation and never changed:
|
|
|
+
|
|
|
+* `id` (unique internal identifier)
|
|
|
+* `strategy_type`
|
|
|
+* `account`
|
|
|
+* `market` (e.g. BTC/USDT)
|
|
|
+
|
|
|
+Purpose:
|
|
|
+
|
|
|
+* Stable logging
|
|
|
+* Auditability
|
|
|
+* Reproducibility
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+#### Mutable Configuration
|
|
|
+
|
|
|
+User-editable and persisted:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "risk": 0.01,
|
|
|
+ "window": 20,
|
|
|
+ "note": "test run"
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Characteristics:
|
|
|
+
|
|
|
+* Editable via UI
|
|
|
+* Stored in database
|
|
|
+* Survives restarts
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+#### Runtime State
|
|
|
+
|
|
|
+* Managed internally by the strategy
|
|
|
+* Not user-editable
|
|
|
+* Typically not persisted (initially)
|
|
|
+
|
|
|
+Example:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "prices": [],
|
|
|
+ "position": 0
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 3. System Layers
|
|
|
+
|
|
|
+```text
|
|
|
+Strategy Definition → Strategy Instance → Runtime Execution → UI Rendering
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 4. Modes of Operation
|
|
|
+
|
|
|
+Each instance has exactly one mode:
|
|
|
+
|
|
|
+```text
|
|
|
+mode ∈ { off, observe, active }
|
|
|
+```
|
|
|
+
|
|
|
+### Modes
|
|
|
+
|
|
|
+| Mode | Loaded | Receives Ticks | Can Trade |
|
|
|
+| ------- | ------ | -------------- | --------- |
|
|
|
+| off | ❌ | ❌ | ❌ |
|
|
|
+| observe | ✅ | ✅ | ❌ |
|
|
|
+| active | ✅ | ✅ | ✅ |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Design Principle
|
|
|
+
|
|
|
+* Strategies always execute the same logic
|
|
|
+* Capabilities are restricted externally via context
|
|
|
+* No internal branching based on mode
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 5. Persistence vs Runtime
|
|
|
+
|
|
|
+### Persistent Layer (Database)
|
|
|
+
|
|
|
+Source of truth:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "id": "...",
|
|
|
+ "strategy_type": "...",
|
|
|
+ "account": "...",
|
|
|
+ "market": "...",
|
|
|
+ "mode": "observe",
|
|
|
+ "config": {...}
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Runtime Layer (Engine Memory)
|
|
|
+
|
|
|
+```python
|
|
|
+running_instances = {
|
|
|
+ "id": StrategyInstance(...)
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Derived from persistent state.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 6. Reconciliation Model
|
|
|
+
|
|
|
+The engine continuously aligns runtime with the database.
|
|
|
+
|
|
|
+### Pseudocode
|
|
|
+
|
|
|
+```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)
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Key Insight
|
|
|
+
|
|
|
+> The system is **declarative**:
|
|
|
+> The database defines the desired state, the engine enforces it.
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 7. Strategy SDK Contract
|
|
|
+
|
|
|
+### Base Structure
|
|
|
+
|
|
|
+```python
|
|
|
+class Strategy:
|
|
|
+ CONFIG_SCHEMA = {}
|
|
|
+
|
|
|
+ def __init__(self, context, config):
|
|
|
+ self.context = context
|
|
|
+ self.config = config
|
|
|
+ self.state = self.init()
|
|
|
+
|
|
|
+ def init(self):
|
|
|
+ return {}
|
|
|
+
|
|
|
+ def on_tick(self, tick):
|
|
|
+ pass
|
|
|
+
|
|
|
+ def render(self):
|
|
|
+ return {"widgets": []}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Context Interface
|
|
|
+
|
|
|
+Strategies interact only through context:
|
|
|
+
|
|
|
+```python
|
|
|
+context.get_price()
|
|
|
+context.place_order(...)
|
|
|
+context.get_orders()
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Mode Enforcement
|
|
|
+
|
|
|
+```python
|
|
|
+def place_order(...):
|
|
|
+ if mode != "active":
|
|
|
+ raise Exception("Not allowed")
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 8. UI Architecture
|
|
|
+
|
|
|
+### 8.1 Config UI
|
|
|
+
|
|
|
+Defined via `CONFIG_SCHEMA`
|
|
|
+
|
|
|
+Purpose:
|
|
|
+
|
|
|
+* Generate forms
|
|
|
+* Validate input
|
|
|
+
|
|
|
+Example:
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "risk": {
|
|
|
+ "type": "float",
|
|
|
+ "default": 0.01
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 8.2 Runtime UI
|
|
|
+
|
|
|
+Generated dynamically:
|
|
|
+
|
|
|
+```python
|
|
|
+def render(state):
|
|
|
+ return {
|
|
|
+ "widgets": [
|
|
|
+ {"type": "line_chart", "data": [...]},
|
|
|
+ {"type": "metric", "label": "PnL", "value": 123}
|
|
|
+ ]
|
|
|
+ }
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Principle
|
|
|
+
|
|
|
+```text
|
|
|
+Config UI = user input
|
|
|
+Runtime UI = system output
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 9. Dashboard Responsibilities
|
|
|
+
|
|
|
+### Strategy List View
|
|
|
+
|
|
|
+Displays:
|
|
|
+
|
|
|
+* Instance ID
|
|
|
+* Strategy type
|
|
|
+* Market
|
|
|
+* Account
|
|
|
+* Mode
|
|
|
+* Status
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Detail View
|
|
|
+
|
|
|
+#### Sections:
|
|
|
+
|
|
|
+1. **Identity (immutable)**
|
|
|
+2. **Config (editable)**
|
|
|
+3. **Runtime UI (widgets)**
|
|
|
+4. **Controls (mode switching)**
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 10. Execution Model
|
|
|
+
|
|
|
+### Tick Loop
|
|
|
+
|
|
|
+```python
|
|
|
+for instance in running_instances:
|
|
|
+ instance.on_tick(tick)
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Rendering
|
|
|
+
|
|
|
+```python
|
|
|
+def get_ui(instance_id):
|
|
|
+ return instance.render()
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Optimization
|
|
|
+
|
|
|
+* Rendering is **on-demand only**
|
|
|
+* No UI computation when not requested
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 11. Design Principles
|
|
|
+
|
|
|
+### 1. Separation of Concerns
|
|
|
+
|
|
|
+* Strategy logic vs system control
|
|
|
+* Config vs runtime state
|
|
|
+* UI input vs UI output
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 2. Declarative Control
|
|
|
+
|
|
|
+* No direct lifecycle manipulation
|
|
|
+* DB defines desired state
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 3. Minimal Control Surface
|
|
|
+
|
|
|
+* Single `mode` field
|
|
|
+* Avoid multiple flags
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 4. Capability-Based Execution
|
|
|
+
|
|
|
+* Strategies always run logic
|
|
|
+* Context restricts actions
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### 5. Instance-Centric Design
|
|
|
+
|
|
|
+* Everything revolves around instances
|
|
|
+* Not strategies as singletons
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 12. Future Extensions
|
|
|
+
|
|
|
+* Backtesting (reuse instance config)
|
|
|
+* Simulation mode (observe + virtual trading)
|
|
|
+* Distributed execution
|
|
|
+* Strategy versioning
|
|
|
+* State persistence and replay
|
|
|
+* Advanced UI widgets (logs, trades, signals)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 13. Summary
|
|
|
+
|
|
|
+The system consists of:
|
|
|
+
|
|
|
+* **Strategies**: reusable logic modules
|
|
|
+* **Instances**: configured, persistent deployments
|
|
|
+* **Engine**: reconciles desired vs actual state
|
|
|
+* **UI**: renders config and runtime data separately
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Core Insight
|
|
|
+
|
|
|
+```text
|
|
|
+Let strategies always think — but only sometimes act.
|
|
|
+```
|
|
|
+
|
|
|
+---
|