DB Database Design for Trading
If you can't query your own trades, you're flying blind
Learning Objectives
- •Design database schemas for trading data
- •Choose between SQL and time-series databases
- •Implement efficient data storage and retrieval
Explain Like I'm 5
You need to store: market data (potentially millions of bars), trade history (every single trade with entry/exit/PnL), model outputs (predictions, features), and configuration (parameters, thresholds). The database design determines how fast you can answer questions like "what was my win rate on FOREX trades last month?" Get it right and analysis is instant. Get it wrong and simple queries take hours. Most beginners dump everything to CSVs and then wonder why their analysis workflow is painful.
Think of It This Way
Database design is like organizing a library. You COULD throw all books in a massive pile, or organize by genre, author, and date with a search catalog. Same books, wildly different ability to find what you need. Now imagine trying to find one specific book in an unsorted pile of 500,000.
1Database Options for Trading
2Schema Design
3Storage Size Reality Check
Storage Size by Data Type (30 instruments, 5 years)
4Query Patterns That Actually Matter
Hands-On Code
SQLite Trading Database
import sqlite3
import json
from datetime import datetime
class TradingDB:
"""Simple SQLite database for trading system."""
def __init__(self, db_path='trading.db'):
self.conn = sqlite3.connect(db_path)
self.create_tables()
def create_tables(self):
self.conn.executescript("""
CREATE TABLE IF NOT EXISTS trades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
symbol TEXT NOT NULL,
direction TEXT NOT NULL,
entry_time TEXT NOT NULL,
exit_time TEXT,
entry_price REAL NOT NULL,
exit_price REAL,
stop_loss REAL,
take_profit REAL,
pnl_r REAL,
cluster TEXT,
l1_confidence REAL,
l2_decision TEXT,
status TEXT DEFAULT 'OPEN'
);
CREATE TABLE IF NOT EXISTS risk_state (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
balance REAL,
drawdown_pct REAL,
dd_zone TEXT,
risk_level REAL,
open_positions INTEGER
);
CREATE INDEX IF NOT EXISTS idx_trades_symbol ON trades(symbol);
CREATE INDEX IF NOT EXISTS idx_trades_entry ON trades(entry_time);
""")
def log_trade(self, trade: dict):
self.conn.execute(
"INSERT INTO trades (symbol, direction, entry_time, entry_price, "
"stop_loss, cluster, l1_confidence, l2_decision) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
(trade['symbol'], trade['direction'], str(datetime.now()),
trade['price'], trade['sl'], trade.get('cluster'),
trade.get('confidence'), trade.get('l2_decision'))
)
self.conn.commit()
def get_stats(self):
cur = self.conn.execute(
"SELECT COUNT(*), AVG(pnl_r), SUM(CASE WHEN pnl_r > 0 THEN 1 ELSE 0 END) * 100.0 / COUNT(*) "
"FROM trades WHERE status = 'CLOSED'"
)
total, avg_r, win_rate = cur.fetchone()
print(f"Trades: {total}, Avg R: {avg_r:.2f}, WR: {win_rate:.1f}%")A proper database lets you query trade history instantly. Without one, you're parsing files manually. Once you have this set up, you'll wonder how you ever operated without it.
Knowledge Check
Q1.You need to store 5 years of 1-minute OHLCV data for 30 instruments. What's the best database choice?
Assignment
Design and implement a SQLite database for your trading system. Store at least 100 simulated trades with all relevant fields. Write queries to compute: win rate, average R, best/worst trade, performance by cluster.