You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
324 lines
11 KiB
Markdown
324 lines
11 KiB
Markdown
# ACE-F v1 — US Stock Event Swing Trading System
|
|
|
|
AI-powered event-driven swing trading system that uses SEC filings and free market data
|
|
to identify 1-5 day continuation trades in US equities.
|
|
|
|
**Core principle:** AI/LLM is a document interpreter, not a price predictor.
|
|
Entry signals come from official filings + price confirmation, never from social data alone.
|
|
|
|
```
|
|
SEC Filings → Document Parser → Feature Builder → Signal Ranker
|
|
↓ ↓
|
|
Price/Volume Confirmation ←──── Backtest Engine ←── Risk Engine
|
|
↓ ↓
|
|
Attention Overlay (optional) ──→ Execution Engine → Post-trade Review
|
|
```
|
|
|
|
## Architecture
|
|
|
|
```
|
|
apps/ # Application entry points
|
|
├── backtester/ # Event-driven backtest simulation & CLI
|
|
├── pipeline/ # Multi-stage data processing
|
|
│ ├── filing_poller/ # Poll SEC EDGAR for new filings
|
|
│ ├── filing_fetcher/ # Download filing documents
|
|
│ ├── event_parser/ # Parse events from filings (rule + LLM)
|
|
│ ├── feature_builder/ # Generate scoring features
|
|
│ ├── label_generator/ # Create forward-return labels
|
|
│ └── dataset_export/ # Export Parquet snapshots for backtesting
|
|
├── sync/ # Data synchronization
|
|
│ ├── issuer_sync/ # Company metadata from Stock Oracle
|
|
│ ├── macro_sync/ # FRED macro indicators
|
|
│ └── short_volume_sync/ # FINRA short sale volume
|
|
├── tracker/ # Strategy improvement tracking CLI
|
|
├── tools/ # Analysis & utility scripts
|
|
├── review/ # Manual review queue
|
|
└── qa/ # Data quality checks
|
|
|
|
libs/ # Core libraries
|
|
├── backtest/ # Backtesting engine
|
|
│ ├── domain.py # Pydantic domain models (30+)
|
|
│ ├── tracker.py # SQS scoring, journal I/O, leaderboard
|
|
│ ├── execution.py # Entry/exit simulation
|
|
│ ├── allocator.py # Position sizing & entry gates
|
|
│ ├── scoring.py # Candidate scoring (PEAD, composite)
|
|
│ ├── selector.py # Candidate filtering & ranking
|
|
│ ├── metrics.py # 21-metric performance bundle + bootstrap CIs
|
|
│ ├── artifacts.py # Run output writer (Parquet, JSON, CSV)
|
|
│ ├── manifests.py # Experiment config resolution
|
|
│ ├── snapshot_store.py # Parquet data loader
|
|
│ ├── splits.py # Walk-forward window generation
|
|
│ └── calendar.py # Trading day utilities
|
|
├── common/ # Logging, config, time utils
|
|
├── db/ # PostgreSQL models (async SQLAlchemy)
|
|
├── oracle_client/ # Stock Oracle API client
|
|
├── parser/ # Filing document parser
|
|
├── features/ # Feature engineering
|
|
├── labeler/ # Label generation
|
|
├── schemas/ # Shared data schemas
|
|
├── export/ # Snapshot export
|
|
├── review/ # Review logic
|
|
└── llm/ # LLM integration layer
|
|
|
|
configs/
|
|
├── backtest/ # Base backtest configs (defaults.json)
|
|
├── experiments/ # 66 experiment manifests
|
|
├── app.yaml # Application settings
|
|
└── symbols_*.yaml # Asset universe definitions
|
|
|
|
data/ # Data storage (parquet snapshots, cache)
|
|
runs/ # Backtest execution outputs
|
|
journal/ # Strategy improvement journal & leaderboard
|
|
tests/
|
|
├── unit/ # Unit tests (270+)
|
|
├── integration/ # Integration tests (requires PostgreSQL)
|
|
└── replay/ # Determinism replay tests
|
|
```
|
|
|
|
## Setup
|
|
|
|
**Requirements:** Python 3.11+, PostgreSQL 16 (via Docker)
|
|
|
|
```bash
|
|
# Install dependencies
|
|
pip install -e ".[dev]"
|
|
|
|
# Start PostgreSQL
|
|
docker compose up -d
|
|
|
|
# Run database migrations
|
|
alembic upgrade head
|
|
|
|
# Copy and configure environment
|
|
cp .env.example .env
|
|
```
|
|
|
|
**Key environment variables:**
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `STOCK_ORACLE_URL` | `http://localhost:18001` | Stock Oracle API endpoint |
|
|
| `POSTGRES_DSN` | `postgresql+asyncpg://acef:acef@localhost:5432/acef` | Database connection |
|
|
| `DATA_ROOT` | `./data` | Data storage root |
|
|
| `LOG_LEVEL` | `INFO` | Logging level |
|
|
| `LLM_ENABLED` | `false` | Enable LLM document parsing |
|
|
|
|
## Usage
|
|
|
|
### Data Pipeline
|
|
|
|
```bash
|
|
# Sync company metadata
|
|
python -m apps.sync.issuer_sync.main
|
|
|
|
# Fetch and parse filings
|
|
python -m apps.pipeline.filing_poller.main
|
|
python -m apps.pipeline.filing_fetcher.main
|
|
python -m apps.pipeline.event_parser.main
|
|
|
|
# Build features and labels
|
|
python -m apps.pipeline.feature_builder.main
|
|
python -m apps.pipeline.label_generator.main
|
|
|
|
# Export Parquet snapshot for backtesting
|
|
python -m apps.pipeline.dataset_export.main
|
|
```
|
|
|
|
### Backtesting
|
|
|
|
```bash
|
|
# Single split backtest
|
|
python -m apps.backtester.run \
|
|
--manifest configs/experiments/pead_midcap_step1_fixedr.json \
|
|
--split test --output-root runs/midcap_steps
|
|
|
|
# 3-split backtest (train/valid/test)
|
|
for split in train valid test; do
|
|
python -m apps.backtester.run \
|
|
--manifest configs/experiments/pead_midcap_step1_fixedr.json \
|
|
--split $split --output-root runs/midcap_steps
|
|
done
|
|
|
|
# Walk-forward cross-validation
|
|
python -m apps.backtester.run \
|
|
--manifest configs/experiments/pead_midcap_step1_fixedr.json \
|
|
--walk-forward --wf-train-days 252 --wf-test-days 63
|
|
|
|
# Output includes SQS score after each run:
|
|
# Run complete: bt_baseline_swing_v1_...
|
|
# Trades: 95
|
|
# Total return: -0.46%
|
|
# SQS: 39.7 (profitability=23.9, risk=52.4, consistency=24.8, robustness=80.7)
|
|
```
|
|
|
|
### Experiment Configuration
|
|
|
|
Experiments are defined as JSON manifests in `configs/experiments/`:
|
|
|
|
```json
|
|
{
|
|
"experiment_name": "pead_midcap_step1_fixedr",
|
|
"dataset_snapshot_id": "midcap-filtered",
|
|
"base_config": "configs/backtest/defaults.json",
|
|
"overrides": {
|
|
"signal": { "scoring_model": "pead", "pead_reaction_threshold": 0.07 },
|
|
"execution": { "target_model": "fixed_r", "target_1_r": 2.0 },
|
|
"risk": { "max_positions": 8 }
|
|
},
|
|
"tags": ["pead", "midcap"]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Strategy Improvement Tracking System
|
|
|
|
A structured system to prevent duplicate experiments, enable data-driven decisions,
|
|
and track the best strategy via a leaderboard.
|
|
|
|
### Strategy Quality Score (SQS)
|
|
|
|
Composite score (0-100) computed from **test split metrics only**. Higher is better.
|
|
|
|
| Category | Weight | Sub-metric | Weight | 0 pts | 100 pts |
|
|
|----------|--------|------------|--------|-------|---------|
|
|
| **Profitability** | 40% | profit_factor | 60% | ≤0.8 | ≥2.0 |
|
|
| | | total_return_pct | 40% | ≤-5% | ≥+5% |
|
|
| **Risk** | 25% | max_drawdown_pct (inv) | 50% | ≥10% | ≤1% |
|
|
| | | sharpe_ratio | 50% | ≤-1.0 | ≥2.0 |
|
|
| **Consistency** | 20% | win_rate | 50% | ≤0.35 | ≥0.65 |
|
|
| | | monthly_win_rate | 50% | ≤0.30 | ≥0.70 |
|
|
| **Robustness** | 15% | equity_curve_r_squared | 50% | ≤0.0 | ≥0.80 |
|
|
| | | trade_count | 50% | ≤10 | ≥100 |
|
|
|
|
**Low-trade penalty:** If test trades < 20, SQS is halved.
|
|
|
|
| SQS Range | Interpretation |
|
|
|-----------|----------------|
|
|
| 0-20 | Losing strategy |
|
|
| 20-40 | Near breakeven |
|
|
| 40-55 | Promising, needs work |
|
|
| 55-70 | Good, has OOS edge |
|
|
| 70-85 | Strong, live candidate |
|
|
| 85-100 | Exceptional (check for data issues) |
|
|
|
|
### Journal & Leaderboard
|
|
|
|
```
|
|
journal/
|
|
├── improvement_journal.jsonl ← Append-only improvement cycle log
|
|
├── experiment_registry.json ← Leaderboard data (regenerated)
|
|
└── LEADERBOARD.md ← Human-readable leaderboard (regenerated)
|
|
```
|
|
|
|
Each journal entry records one improvement cycle:
|
|
|
|
```json
|
|
{
|
|
"entry_id": "IMP-0001",
|
|
"timestamp": "2026-03-16T19:30:00",
|
|
"experiment_name": "pead_midcap_step3_10pct",
|
|
"hypothesis": "Raise reaction threshold to 10% for stronger signals",
|
|
"results": {
|
|
"train": { "run_id": "bt_...", "trade_count": 420, "profit_factor": 0.95, ... },
|
|
"valid": { "run_id": "bt_...", ... },
|
|
"test": { "run_id": "bt_...", ... }
|
|
},
|
|
"sqs_score": 38.5,
|
|
"sqs_breakdown": { "profitability": 35.2, "risk": 45.0, "consistency": 30.0, "robustness": 42.0 },
|
|
"verdict": "better",
|
|
"verdict_reasoning": "Test PF 0.89 -> 1.00, breakeven achieved",
|
|
"next_direction": "Combine 10% threshold + maxcand3"
|
|
}
|
|
```
|
|
|
|
### Tracker CLI
|
|
|
|
```bash
|
|
# Record experiment results to journal
|
|
python -m apps.tracker.cli record \
|
|
--journal-dir journal/ \
|
|
--runs-dir runs/midcap_steps/ \
|
|
--experiment pead_midcap_step3_10pct \
|
|
--hypothesis "Raise reaction threshold to 10%" \
|
|
--baseline pead_7pct_midcap \
|
|
--verdict better \
|
|
--reasoning "Test PF improved from 0.89 to 1.00" \
|
|
--next "Combine 10% threshold + maxcand3"
|
|
|
|
# View leaderboard
|
|
python -m apps.tracker.cli leaderboard --journal-dir journal/
|
|
|
|
# # Experiment SQS PF Ret% Trades
|
|
# ------------------------------------------------------------------
|
|
# 1 pead_7pct_longshort_v2 60.7 1.31 +2.0 55
|
|
# 2 pead_midcap_step3_10pct 38.5 1.00 +0.0 85
|
|
|
|
# Show entry details
|
|
python -m apps.tracker.cli show --journal-dir journal/ IMP-0001
|
|
|
|
# Check for duplicate experiments
|
|
python -m apps.tracker.cli check-duplicate \
|
|
--journal-dir journal/ --experiment pead_midcap_step3_10pct
|
|
```
|
|
|
|
### Improvement Workflow
|
|
|
|
```
|
|
1. Create experiment config configs/experiments/my_experiment.json
|
|
2. Run 3-split backtest for split in train valid test; do ... done
|
|
3. Record to journal python -m apps.tracker.cli record ...
|
|
4. Check leaderboard python -m apps.tracker.cli leaderboard ...
|
|
5. Plan next experiment based on verdict + SQS breakdown
|
|
6. Check for duplicates python -m apps.tracker.cli check-duplicate ...
|
|
7. Repeat from step 1
|
|
```
|
|
|
|
---
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
# Unit tests (fast, no external deps)
|
|
pytest tests/unit/ -v
|
|
|
|
# Backtest module tests only
|
|
pytest tests/unit/backtest/ -v
|
|
|
|
# Integration tests (requires PostgreSQL)
|
|
pytest tests/integration/ -v
|
|
|
|
# Full CI check (lint + typecheck + unit tests)
|
|
make ci
|
|
```
|
|
|
|
## Data Sources
|
|
|
|
| Source | Role | Cost |
|
|
|--------|------|------|
|
|
| **SEC EDGAR** | Primary event source (8-K, 10-Q, 6-K filings) | Free |
|
|
| **Stock Oracle API** | Market data (OHLCV bars, company info) | Internal |
|
|
| **FRED** | Macro regime indicators (rates, spreads) | Free |
|
|
| **FINRA** | Short sale volume (crowding signal) | Free |
|
|
| Wikimedia | Retail attention via pageviews | Free |
|
|
| YouTube | Channel-based attention tracking | Free (quota limited) |
|
|
| Yahoo RSS | Headline burst detection | Free |
|
|
|
|
## Tech Stack
|
|
|
|
| Component | Technology |
|
|
|-----------|-----------|
|
|
| Language | Python 3.11+ |
|
|
| Models | Pydantic v2 |
|
|
| Database | PostgreSQL 16 + async SQLAlchemy |
|
|
| Research data | DuckDB + Parquet |
|
|
| Containers | Docker Compose |
|
|
| Linting | Ruff |
|
|
| Type checking | MyPy (strict) |
|
|
| Testing | Pytest + asyncio |
|
|
| Logging | structlog (JSON) |
|
|
|
|
## License
|
|
|
|
Private project. All rights reserved.
|