TradeCraft
Algorithmic trading simulation platform
What TradeCraft Does
TradeCraft is a trading simulation platform where you backtest algorithmic strategies against years of real market data, then deploy autonomous agents that mirror those trades using your own Alpaca API keys.
The core idea: Every other trading platform either wants your money (manage it for you) or your strategy (sell you theirs). TradeCraft is BYOK — Bring Your Own Keys. Your capital stays in your Alpaca account, you own the strategy logic, and the platform just shows you what works.
The Architecture
Three-Pillar Breakdown
🗄️ DATABASE: TimescaleDB (PostgreSQL with time-series extensions)
│
├─ market_candles 100M+ rows of OHLCV data (stocks + crypto)
├─ simulation_results Every backtest run (strategy × symbol × timeframe)
├─ character_agents 39 personified strategies ("Characters")
├─ user_agents Live trading agents that mirror simulations
└─ trades Actual executions via Alpaca API
🖥️ INTERFACE: PHP + Bootstrap 5 (dark theme)
│
├─ Server-rendered HTML Fast, no build step, SEO-friendly
├─ Character Dashboard See how each strategy performs across all symbols
├─ Agent Dashboard Monitor your live trading agents
└─ Account Settings Link Alpaca keys, manage subscriptions
⚡ API LOGIC: PHP business layer + External APIs
│
├─ Simulation Engine Runs backtests using historical candles
├─ Trade Mirror System Copies simulation trades to Alpaca when agent active
├─ Data Pipeline Fetches new candles from Alpaca/Tiingo (cron jobs)
└─ Stripe Integration Subscription billing (3 tiers)
Why TimescaleDB?
We started with regular PostgreSQL. Queries on 100M candle rows were... painful. TimescaleDB gives us hypertables — it automatically partitions time-series data by time ranges. A query like "show me all SPY 1-minute candles from March 2024" becomes sub-second instead of minutes.
The Shared Database Pattern
Here's something unusual: development and production share the same database.
/opt/bened-tradecraft (dev) ──┐
├──▶ TimescaleDB (ONE database)
/srv/bened-tradecraft (prod) ──┘
Why? The simulation engine and data collectors run as cron jobs from dev. They write candles, simulation results, and agent trades. Production just reads the same data. No replication lag, no sync issues, one data pipeline.
The consequence: Schema changes are ADDITIVE ONLY. You can't drop a column dev uses if prod is still SELECT-ing it. This forces disciplined database evolution.
The 39 Characters
Instead of "Strategy A" and "Strategy B", TradeCraft has personified algorithms — Characters. Each one has a name, personality, and trading style:
- Momentum Riders: Trend-following strategies that buy strength
- Mean Reversion: Contrarian plays betting on reversals
- Volatility Traders: Profit from price swings regardless of direction
- Hybrid Strategies: Multi-factor combinations
Each Character runs simulations across 114 symbols (102 stocks + 12 crypto). You study their results, see which ones align with your risk tolerance, then activate agents that mirror their trades.
Auth & Identity
Single sign-on via Keycloak at auth.bened.works. When you log into TradeCraft, you're actually getting a JWT from Keycloak. That same token works on the rental platform, the platform API — everything. One login, all apps.
We tried separate user databases first. It was a nightmare.
The Tech Stack
| Layer | Technology | Why This Choice |
|---|---|---|
| Backend | PHP 8.2 | Fast, mature, no build step. Direct database access. |
| Database | TimescaleDB | PostgreSQL + time-series superpowers. Sub-second queries on 100M rows. |
| Frontend | Bootstrap 5 (dark) | Responsive, accessible, looks good without custom CSS. |
| Server | Nginx + PHP-FPM | Nginx proxies, PHP-FPM handles scripts. Standard, battle-tested. |
| Auth | Keycloak (OIDC) | Industry-standard SSO. JWT tokens, refresh flow, cross-app identity. |
| Trading API | Alpaca | Commission-free, good API, supports stocks + crypto. |
| Market Data | Alpaca + Tiingo | Historical candles, real-time quotes. Free tier sufficient for dev. |
| Payments | Stripe Subscriptions | 3 tiers: Free (demo), Basic, Pro. Stripe handles recurring billing. |
Data Flow: How a Trade Happens
1. Simulation Engine (cron) └─ Runs backtests for all Characters × Symbols └─ Writes results to simulation_results table 2. User activates an Agent └─ Links Agent to a Character strategy └─ Agent starts monitoring simulation_results 3. Character generates a trade signal (via simulation) └─ Agent sees the signal in simulation_results └─ Agent calls Alpaca API to execute the trade └─ Trade recorded in trades table 4. User sees trade in their dashboard └─ PHP reads from trades table └─ Displays in Agent Dashboard
What's Proprietary (Not Shown Here)
- The actual strategy algorithms (how Characters decide to trade)
- The simulation engine's execution logic
- Fee structures and profit calculations
- Risk management rules and position sizing
This is appropriate disclosure — you see how the system works, not the secret sauce that makes strategies profitable.
Development vs Production
| Development | Production | |
|---|---|---|
| URL | devtradecraft.bened.works | tradecraft.bened.works |
| Code | /opt/bened-tradecraft | /srv/bened-tradecraft |
| Database | Shared TimescaleDB | |
| Cron Jobs | ✅ All run here | ❌ None |
| Purpose | Sandbox, new features, data engine | Stable public-facing site |
The Deployment Story
Code changes go like this:
1. Edit files in /opt/bened-tradecraft (dev) 2. Test at devtradecraft.bened.works 3. When stable, run deploy script: └─ Pulls code from /opt/ to /srv/ └─ Runs composer install --no-dev └─ PHP-FPM serves new code instantly (no restart) 4. Production site at tradecraft.bened.works gets updates
PHP has a beautiful property: file changes are live immediately. No build step, no container restarts, no downtime.