""" database.py — SQLite schema initialization and connection management. """ import sqlite3 import os from pathlib import Path SCHEMA = """ -- ═══════════════════════════════════════════════ -- L0: Raw data tables -- ═══════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS ohlcv_daily ( date TEXT NOT NULL, symbol TEXT NOT NULL DEFAULT 'BTC/USDT:USDT', open REAL, high REAL, low REAL, close REAL, volume REAL, ema20 REAL, ema60 REAL, ema120 REAL, atr_14 REAL, bb_width REAL, adx_14 REAL, PRIMARY KEY (date, symbol) ); CREATE TABLE IF NOT EXISTS breadth_daily ( date TEXT PRIMARY KEY, total_tracked INTEGER DEFAULT 50, advance_top50 INTEGER DEFAULT 0, decline_top50 INTEGER DEFAULT 0, above_ema20_top50 INTEGER DEFAULT 0, new_highs_20d_top50 INTEGER DEFAULT 0, btc_dominance REAL, advance_top20 INTEGER DEFAULT 0, advance_top30 INTEGER DEFAULT 0, above_ema20_top20 INTEGER DEFAULT 0, above_ema20_top30 INTEGER DEFAULT 0, new_highs_20d_top20 INTEGER DEFAULT 0, new_highs_20d_top30 INTEGER DEFAULT 0, fetched_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS derivatives ( date TEXT NOT NULL, symbol TEXT NOT NULL DEFAULT 'BTC/USDT:USDT', funding_rate REAL, open_interest REAL, oi_24h_change_pct REAL, long_liquidations REAL, short_liquidations REAL, basis_annualised_pct REAL, source TEXT DEFAULT 'binance', fetched_at TEXT DEFAULT (datetime('now')), PRIMARY KEY (date, symbol) ); CREATE TABLE IF NOT EXISTS etf_flow ( date TEXT NOT NULL, product TEXT NOT NULL, net_flow_million REAL NOT NULL, price REAL, source TEXT DEFAULT 'farside', fetched_at TEXT DEFAULT (datetime('now')), PRIMARY KEY (date, product) ); CREATE TABLE IF NOT EXISTS stablecoin_supply ( date TEXT NOT NULL, token TEXT NOT NULL, chain TEXT NOT NULL DEFAULT 'all', supply REAL NOT NULL, source TEXT DEFAULT 'defillama', fetched_at TEXT DEFAULT (datetime('now')), PRIMARY KEY (date, token, chain) ); -- ═══════════════════════════════════════════════ -- L3: Regime history -- ═══════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS regime_history ( date TEXT PRIMARY KEY, regime TEXT NOT NULL, confidence REAL, regime_version TEXT NOT NULL DEFAULT 'v1_price_breadth_vol', maturity_score REAL DEFAULT 50.0, all_scores_json TEXT DEFAULT '{}', prior_regime TEXT, confirmation_days INTEGER DEFAULT 1, created_at TEXT DEFAULT (datetime('now')) ); -- ═══════════════════════════════════════════════ -- ★ signal_features — THE moat -- ═══════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS signal_features ( id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT NOT NULL, signal_type TEXT NOT NULL, signal_version TEXT NOT NULL DEFAULT 'b3_v1', symbol TEXT DEFAULT 'BTC/USDT:USDT', -- ★★ Version control (most important fields) regime_version TEXT NOT NULL DEFAULT 'v1_price_breadth_vol', signal_grade TEXT, signal_strength REAL, -- Market State Vector snapshot regime TEXT NOT NULL, regime_confidence REAL, regime_maturity_score REAL DEFAULT 50.0, market_state_hash TEXT, state_embedding TEXT DEFAULT '[]', breadth_top20 REAL, breadth_top30 REAL, breadth_top50 REAL, breadth_bucket TEXT, breadth_divergence REAL, oi_state TEXT, volatility_regime TEXT, price_structure_score REAL, -- Chan context (V5+) chan_trend_direction TEXT, chan_pivot_count INTEGER, chan_divergence_type TEXT, -- Outcomes entry_price REAL, result_1d REAL, result_3d REAL, result_5d REAL, result_7d REAL, result_14d REAL, max_favorable_excursion REAL, max_adverse_excursion REAL, is_win_7d INTEGER, created_at TEXT DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_sf_regime ON signal_features(regime); CREATE INDEX IF NOT EXISTS idx_sf_signal ON signal_features(signal_type); CREATE INDEX IF NOT EXISTS idx_sf_oi_state ON signal_features(oi_state); CREATE INDEX IF NOT EXISTS idx_sf_date ON signal_features(date); CREATE INDEX IF NOT EXISTS idx_sf_state_hash ON signal_features(market_state_hash); CREATE INDEX IF NOT EXISTS idx_sf_regime_version ON signal_features(regime_version); CREATE INDEX IF NOT EXISTS idx_sf_signal_version ON signal_features(signal_version); -- ═══════════════════════════════════════════════ -- Expectancy cache (raw counts, NOT posteriors) -- ═══════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS expectancy_cache ( state_hash TEXT NOT NULL, signal_type TEXT NOT NULL, wins_weighted REAL DEFAULT 0, losses_weighted REAL DEFAULT 0, sum_return_7d REAL DEFAULT 0, sum_return_sq_7d REAL DEFAULT 0, effective_samples REAL DEFAULT 0, sufficiency TEXT DEFAULT 'INSUFFICIENT', updated_at TEXT DEFAULT (datetime('now')), PRIMARY KEY (state_hash, signal_type) ); -- ═══════════════════════════════════════════════ -- Similarity outcome (KNN weight learning, Phase D) -- ═══════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS similarity_outcome ( id INTEGER PRIMARY KEY AUTOINCREMENT, state_a_hash TEXT, state_b_hash TEXT, distance REAL, actual_return_gap REAL, dimension_weights_json TEXT DEFAULT '{}', created_at TEXT DEFAULT (datetime('now')) ); -- ═══════════════════════════════════════════════ -- chan_context — Chan theory integration (V1 empty) -- ═══════════════════════════════════════════════ CREATE TABLE IF NOT EXISTS chan_context ( date TEXT NOT NULL, timeframe TEXT NOT NULL DEFAULT '1d', trend_direction TEXT, trend_strength REAL, pivot_count INTEGER, pivot_level TEXT, signal_type TEXT, signal_strength REAL, divergence_type TEXT, chan_structure_score REAL, alignment_score REAL, raw_context_json TEXT DEFAULT '{}', PRIMARY KEY (date, timeframe) ); """ def init_db(db_path: str = "data/macro.db") -> sqlite3.Connection: """Initialize database: create directory and all tables.""" Path(db_path).parent.mkdir(parents=True, exist_ok=True) conn = sqlite3.connect(db_path) conn.executescript(SCHEMA) conn.commit() return conn def get_connection(db_path: str = "data/macro.db") -> sqlite3.Connection: """Get a database connection. Creates tables if first run.""" if not os.path.exists(db_path): return init_db(db_path) conn = sqlite3.connect(db_path) conn.row_factory = sqlite3.Row return conn