A modular, layered trading agent system for real financial markets. Each capability is an independent module that can be developed, tested, and replaced individually, collaborating through clear interface contracts.
Screening → Data Layer → Decision → Execution Engine → Execution Results
↑ ↓
Playbook Trading Evolution (Learning)
↑ │
└──────────────────────┘
Auto-evolution loop
┌──────── Dashboard (Web UI) ────────┐
│ FastAPI + SSE → Real-time Control │
└────────────────────────────────────┘
The Data Layer pre-prepares all factual data (K-line/technical indicators, news, macro). The Decision Agent executes trades through a deterministic backtest engine (pure in-memory, zero I/O, fully reproducible) — no runtime information fetching, ensuring reasoning stability. After trading completes, the evolution system automatically reflects on trading experience, discovers errors and missed opportunities, generates improvement hypotheses, and validates them through Walk Forward testing before promoting new strategies.
| Module | Path | Responsibility |
|---|---|---|
| Stock Screening | modules/screening/ |
Broad-index constituent hard filtering → candidate pool |
| Data Layer | data_layer/ |
Factual data layer (K-line/technical indicators, news, macro, LLM news summaries) |
| Decision v2 | modules/decision_v2/ |
Chain of Insight (COI) 4-step structured reasoning + deterministic execution engine |
| Trade Execution Engine | modules/execution/ |
Deterministic executor: in-memory state management, weighted average cost, P&L calculation |
| Strategy Playbook | modules/playbook/ |
Narrative trading strategy content (text only); version management lives in learning/ |
| Trading Evolution | learning/ |
Automatic strategy evolution: reflect → knowledge → hypothesize → validate → promote |
| Dashboard | dashboard/ |
FastAPI Web UI: real-time SSE updates, Start/Stop/Resume control, portfolio charts |
Cross-module shared: shared/tools/ (LLM configuration, price tools, general utilities)
# Install environment (using uv)
uv sync
# Configure API keys
cp .env.example .env # Edit .env and fill in your keys
# Run directly (uses deterministic execution engine)
python main.py
# Generate trading context using Data Layer CLI
python -m data_layer AAPL 2025-10-01 --news-analysis
# Run execution engine tests
pytest tests/test_backtest_engine.py -vThe dashboard provides a web-based control panel for the trading agent:
# Start the dashboard (browser opens at http://127.0.0.1:8080)
python -m dashboard- Web UI Control Panel — Configure trading parameters (symbols, date range, cash, market) and start trading from the browser
- Real-time Updates — SSE (Server-Sent Events) pushes trade progress, portfolio value, and P&L live to the browser
- Portfolio Chart — Portfolio value over time, daily returns, and trade markers
- Stop Control — Graceful stop (finishes current day) or immediate cancel
- Resume / New Run — Auto-detects interrupted runs; choose to continue from where it left off or start fresh
- Deduplication Safety Net — Chart data automatically deduplicated by date to prevent duplicate entries
The system caches context snapshots and news data automatically to avoid redundant API calls:
| Cache | Location | Behavior |
|---|---|---|
| Context Snapshots | context_store/{SYMBOL}/{DATE}/ |
Second run of same date returns in ~0.003s (zero API calls) |
| News Incremental | context_store/_news_cache/ |
After first full fetch, only pulls new records (~95% API savings) |
| News Analysis | context_store/_news_analysis/ |
SHA256 hash-based LLM cache (disabled by default) |
Already-fetched dates will not trigger API calls on re-run. See CLAUDE.md for details.
configs/config.json — Main configuration file:
| Key Field | Description |
|---|---|
decision_version |
"v2" — COI structured reasoning (default) |
market |
Market identifier, default "us" |
stock_symbols |
List of trading symbols |
date_range |
Simulation start/end dates (init_date, end_date) |
price_data_dir |
Local CSV data directory, default "data/US_Stock_Data" |
layered_config |
Screening parameters (stock universe, initial filter conditions) |
data_layer_config |
Data layer settings (max_analysis_symbols) |
agent_config |
Initial cash (initial_cash) |
policy_dir |
Playbook directory, default modules/playbook |
evolution_enabled |
Whether to enable automatic strategy evolution (requires v2, auto-triggers when trading days >= 7). See Evolution System Guide |
daily_journal_enabled |
Whether to record daily reflection journals (observation/error/opportunity per trading day) |
dashboard_enabled |
Whether to start the Web dashboard after trading completes |
dashboard_port |
Dashboard HTTP port, default 8080 |
evolution_config |
Evolution parameters: reflection_trigger_mode (both/on_demand/scheduled), reflection_window_days, reflection_interval_days, validation_rules (min_sharpe / max_drawdown / min_trades / min_sharpe_improvement), warning_triggers, Walk Forward window configuration, backtest_frequency (token-saving sampling interval, default 3), evolution_dir, llm_model |
.env — Model & API keys:
LLM_MODEL=deepseek-v4-flash
OPENAI_API_BASE=https://api.deepseek.com/v1
OPENAI_API_KEY=your_keySee configs/README.md and .env.example for details.
V2's 5-step reasoning: Market Analysis → Portfolio Analysis → Policy Check → Decision Synthesis → Execution (execution engine)
# Test stock screening module (no LLM needed)
python -c "
from modules.screening import run_stock_screening, get_default_universe
u = get_default_universe()
print(run_stock_screening(u[:5], '2024-06-01', {'enabled': True}))
"
# Test execution engine (39 deterministic tests)
pytest tests/test_backtest_engine.py -v
# Generate trading context with Data Layer
python -m data_layer AAPL 2025-10-01
# Test Decision V2 (Mock mode, using deterministic engine)
python tests/test_decision_v2_mock.py
# Sync K-line data to local CSV
python scripts/sync_kline_data.py AAPLmain.py # Online trading entry point
configs/config.json # Main configuration
.env # API keys
pyproject.toml # Project dependencies
modules/
├── screening/ # Stock screening
├── execution/ # Deterministic trade execution engine
│ ├── engine.py # BacktestEngine (in-memory state management)
│ └── schemas.py # PortfolioSnapshot, ExecutionResult
├── decision_v2/ # Decision (COI)
│ ├── core/agent_coi.py # TradingAgentCOI (calls BacktestEngine)
│ ├── prompts/ # 4-step COI prompts (narrative strategy evaluation)
│ ├── inputs/ # Input builders
│ ├── schemas.py # Data models
│ └── outputs/logger.py # Trajectory logger
└── playbook/ # Strategy content (trading_policy.json + thin loader)
data_layer/ # Data layer
├── context_builder/ # TradingContextBuilder
├── services/ # KlineService, NewsService, MacroService, NewsAnalysisService
├── storage/ # ContextStore snapshot persistence
├── io/ # Authoritative CSV I/O (csv_reader, calendar)
├── schemas/ # Data models (metadata, trading_context)
└── cli.py # CLI entry point
shared/ # Cross-module shared
└── tools/ # Utility functions (LLM config, price tools, general utilities)
learning/ # Trading evolution system
├── schemas/ # Data models (reflection, memory, evolution, strategy_schema)
├── reflection/ # Reflection engine (error identification + opportunity discovery)
├── memory/ # Memory layer (short-term 30-day window + long-term knowledge base)
└── evolution/ # Evolution layer (hypothesis, experiment, policy_store, curator, controller)
dashboard/ # Live trading dashboard (web UI)
│ ├── app.py # FastAPI application + SSE endpoint
│ ├── session.py # TradingSession (state machine + background loop)
│ ├── evolution_monitor.py # Evolution progress tracking + SSE broadcast
│ ├── server.py # Uvicorn server launcher
│ └── status_writer.py # Status.json persistence for resume
data/US_Stock_Data/ # Local market data CSV files
evolution_data/ # Evolution system data (memory, history)
tests/ # All tests (6 files)
│ ├── test_backtest_engine.py # Deterministic execution engine (39 tests)
│ ├── test_decision_v2_mock.py # Decision V2 COI smoke test
│ ├── test_evolution_e2e.py # Evolution system E2E tests
│ ├── test_episode_memory.py # Short-term memory unit tests
│ ├── test_news_analysis_llm.py # News analysis with LLM
│ └── test_semantic_memory.py # Semantic memory unit tests
scripts/ # Utility scripts (2 files)
├── sync_kline_data.py # Download K-line data from Yahoo Finance
└── evolution_dashboard.py # Evolution system monitoring panel
See modules/*/README.md for detailed module documentation.
When evolution_enabled: true and trading days >= 7, main.py automatically triggers an evolution cycle after trading completes:
Trading Trajectories → Reflection Engine (ReflectionEngine)
├── Error Identification: audit decision consistency with strategy principles (non-parametric)
├── Opportunity Discovery: identify missed trading opportunities based on strategy philosophy
└── Output ReflectionResult (0+ errors + 0+ missed opportunities)
↓
Episode Memory (EpisodeMemory) ← 30-day JSONL window
Semantic Memory (SemanticMemory) ← Long-term knowledge base
↓
Hypothesis Generation (HypothesisEngine) → LLM-driven strategy improvement hypotheses
↓
Experiment Validation (ExperimentEngine) → Walk Forward rolling backtest (Mock + Live dual mode)
↓
Policy Validation (PolicyValidator) → Multi-level gating (Sharpe, drawdown, win rate)
↓
Strategy Curation (CuratorAgent) → Intelligently merge validated hypotheses into narrative strategy
↓
Policy Promotion (PolicyVersionManager) → Version tree tracking + auto-promote after passing
Reflection principle: Based on strategy philosophy, not parameter thresholds. Evaluates "did the trade follow the principles described in the strategy" rather than "is RSI > 50". See Evolution System Guide.
Zero trades may occur when the strategy is too conservative. Common causes:
- Conservative strategy philosophy: Principles like "don't chase rallies", "wait for perfect setup", "cash is a strategic asset" may cause the agent to stay on the sidelines
- Single symbol + choppy market: With only 1 stock and no clear market direction, trend-following strategies struggle to find entry points
- Limited technical signals: Without auxiliary data like volume or sector comparison, LLMs tend to be conservative
Suggestions: Increase candidate symbol count (stock_symbols), adjust strategy narratives to encourage more active entry, or increase trading days for more opportunities.
The most common cause of validation failure is candidate and baseline strategies producing identical performance (e.g., both with 0 trades), resulting in no Sharpe improvement. Ensure sufficient trade records exist in the trading cycle for the evolution system to learn from.
The free Finnhub API Key does not have access to the economic calendar endpoint. The system will automatically skip macro data without affecting trading decisions. Upgrade your Finnhub subscription if macro data is needed.
Set FINNHUB_API_KEY in .env. Without an API Key, news and macro data will return empty, which does not affect basic trading functionality (K-line data is provided via local CSV).
Working memory filters out all HOLD decisions (no actual trades). This is normal behavior — entries are only recorded when there are BUY/SELL actions.