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.
193 lines
5.4 KiB
Python
193 lines
5.4 KiB
Python
"""SQLite schema and dataclasses for ORB paper trading state."""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
|
|
# ── SQL DDL ───────────────────────────────────────────────────────────────────
|
|
|
|
CREATE_TABLES_SQL = """
|
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
session_id TEXT PRIMARY KEY,
|
|
session_name TEXT NOT NULL UNIQUE,
|
|
config_path TEXT NOT NULL,
|
|
initial_equity REAL NOT NULL,
|
|
created_at TEXT NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'active'
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS orb_positions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id TEXT NOT NULL REFERENCES sessions(session_id),
|
|
date TEXT NOT NULL,
|
|
ticker TEXT NOT NULL,
|
|
direction TEXT NOT NULL,
|
|
entry_price REAL NOT NULL,
|
|
entry_time TEXT NOT NULL,
|
|
shares INTEGER NOT NULL,
|
|
orb_high REAL NOT NULL,
|
|
orb_low REAL NOT NULL,
|
|
atr_at_entry REAL NOT NULL,
|
|
stop_distance REAL NOT NULL,
|
|
current_stop REAL NOT NULL,
|
|
peak_price REAL NOT NULL,
|
|
trailing_active INTEGER NOT NULL DEFAULT 0,
|
|
rvol REAL,
|
|
composite_score REAL,
|
|
order_id TEXT,
|
|
status TEXT NOT NULL DEFAULT 'open',
|
|
UNIQUE(session_id, date, ticker)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS trades (
|
|
trade_id TEXT PRIMARY KEY,
|
|
session_id TEXT NOT NULL,
|
|
date TEXT NOT NULL,
|
|
ticker TEXT NOT NULL,
|
|
direction TEXT NOT NULL,
|
|
entry_price REAL NOT NULL,
|
|
exit_price REAL NOT NULL,
|
|
entry_time TEXT NOT NULL,
|
|
exit_time TEXT NOT NULL,
|
|
shares INTEGER NOT NULL,
|
|
pnl REAL NOT NULL,
|
|
r_multiple REAL NOT NULL,
|
|
exit_reason TEXT NOT NULL,
|
|
atr_at_entry REAL,
|
|
rvol REAL,
|
|
composite_score REAL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS daily_snapshots (
|
|
session_id TEXT NOT NULL,
|
|
date TEXT NOT NULL,
|
|
equity REAL NOT NULL,
|
|
daily_pnl REAL,
|
|
total_pnl REAL,
|
|
trades_taken INTEGER,
|
|
stops_hit INTEGER,
|
|
drawdown_pct REAL,
|
|
PRIMARY KEY (session_id, date)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS daily_state (
|
|
session_id TEXT NOT NULL,
|
|
date TEXT NOT NULL,
|
|
cumulative_loss REAL NOT NULL DEFAULT 0.0,
|
|
stops_hit INTEGER NOT NULL DEFAULT 0,
|
|
kill_switch INTEGER NOT NULL DEFAULT 0,
|
|
phase TEXT NOT NULL DEFAULT 'idle',
|
|
PRIMARY KEY (session_id, date)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS orb_candidates (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id TEXT NOT NULL,
|
|
date TEXT NOT NULL,
|
|
ticker TEXT NOT NULL,
|
|
direction TEXT NOT NULL,
|
|
orb_high REAL NOT NULL,
|
|
orb_low REAL NOT NULL,
|
|
breakout_level REAL NOT NULL,
|
|
atr REAL NOT NULL,
|
|
rvol REAL NOT NULL,
|
|
gap_pct REAL NOT NULL,
|
|
composite_score REAL NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'pending',
|
|
UNIQUE(session_id, date, ticker)
|
|
);
|
|
"""
|
|
|
|
|
|
# ── Dataclasses ───────────────────────────────────────────────────────────────
|
|
|
|
@dataclass
|
|
class ORBSessionRow:
|
|
session_id: str
|
|
session_name: str
|
|
config_path: str
|
|
initial_equity: float
|
|
created_at: str
|
|
status: str = "active"
|
|
|
|
|
|
@dataclass
|
|
class ORBPositionRow:
|
|
session_id: str
|
|
date: str
|
|
ticker: str
|
|
direction: str # 'long' or 'short'
|
|
entry_price: float
|
|
entry_time: str
|
|
shares: int
|
|
orb_high: float
|
|
orb_low: float
|
|
atr_at_entry: float
|
|
stop_distance: float
|
|
current_stop: float
|
|
peak_price: float
|
|
trailing_active: bool = False
|
|
rvol: float | None = None
|
|
composite_score: float | None = None
|
|
order_id: str | None = None
|
|
status: str = "open"
|
|
id: int | None = None # autoincrement, set after insert
|
|
|
|
|
|
@dataclass
|
|
class ORBTradeRow:
|
|
trade_id: str
|
|
session_id: str
|
|
date: str
|
|
ticker: str
|
|
direction: str
|
|
entry_price: float
|
|
exit_price: float
|
|
entry_time: str
|
|
exit_time: str
|
|
shares: int
|
|
pnl: float
|
|
r_multiple: float
|
|
exit_reason: str # 'stop_loss', 'trailing_stop', 'close', 'kill_switch'
|
|
atr_at_entry: float | None = None
|
|
rvol: float | None = None
|
|
composite_score: float | None = None
|
|
|
|
|
|
@dataclass
|
|
class ORBDailySnapshotRow:
|
|
session_id: str
|
|
date: str
|
|
equity: float
|
|
daily_pnl: float = 0.0
|
|
total_pnl: float = 0.0
|
|
trades_taken: int = 0
|
|
stops_hit: int = 0
|
|
drawdown_pct: float = 0.0
|
|
|
|
|
|
@dataclass
|
|
class ORBDailyStateRow:
|
|
session_id: str
|
|
date: str
|
|
cumulative_loss: float = 0.0
|
|
stops_hit: int = 0
|
|
kill_switch: bool = False
|
|
phase: str = "idle" # idle, pre_market, orb_detection, breakout, management, eod, done
|
|
|
|
|
|
@dataclass
|
|
class ORBCandidateRow:
|
|
session_id: str
|
|
date: str
|
|
ticker: str
|
|
direction: str
|
|
orb_high: float
|
|
orb_low: float
|
|
breakout_level: float
|
|
atr: float
|
|
rvol: float
|
|
gap_pct: float
|
|
composite_score: float
|
|
status: str = "pending" # pending, filled, timeout, cancelled
|
|
id: int | None = None
|