Files
market_intel/packages/db/schema.py
T
2026-08-01 10:33:19 +08:00

76 lines
2.2 KiB
Python

"""SQLite schema(可迁移设计)。时间戳存 UTC ms。"""
from __future__ import annotations
import sqlite3
from pathlib import Path
SCHEMA_SQL = """
CREATE TABLE IF NOT EXISTS option_quotes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts_ms INTEGER NOT NULL,
exchange TEXT NOT NULL,
underlying TEXT NOT NULL,
inst_id TEXT NOT NULL,
expiry_ymd TEXT NOT NULL,
strike REAL NOT NULL,
side TEXT NOT NULL,
index_px REAL NOT NULL,
ask REAL,
bid REAL,
ask_sz REAL,
bid_sz REAL,
leverage REAL,
created_at_ms INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_oq_ts ON option_quotes(ts_ms);
CREATE INDEX IF NOT EXISTS idx_oq_side_ts ON option_quotes(side, ts_ms);
CREATE INDEX IF NOT EXISTS idx_oq_expiry ON option_quotes(expiry_ymd);
CREATE TABLE IF NOT EXISTS index_ticks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
ts_ms INTEGER NOT NULL,
exchange TEXT NOT NULL,
underlying TEXT NOT NULL,
index_px REAL NOT NULL,
created_at_ms INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_it_ts ON index_ticks(ts_ms);
CREATE INDEX IF NOT EXISTS idx_it_u_ts ON index_ticks(underlying, ts_ms);
CREATE TABLE IF NOT EXISTS expiry_settlements (
expiry_ymd TEXT PRIMARY KEY,
settle_ts_ms INTEGER NOT NULL,
settle_index_px REAL NOT NULL,
exchange TEXT NOT NULL,
underlying TEXT NOT NULL,
created_at_ms INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS collector_heartbeat (
id INTEGER PRIMARY KEY CHECK (id = 1),
last_ok_ts_ms INTEGER,
last_error TEXT,
last_error_ts_ms INTEGER,
consecutive_failures INTEGER NOT NULL DEFAULT 0,
meta_json TEXT
);
"""
def init_db(db_path: str | Path) -> sqlite3.Connection:
path = Path(db_path)
path.parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(str(path), check_same_thread=False)
conn.row_factory = sqlite3.Row
conn.execute("PRAGMA journal_mode=WAL;")
conn.execute("PRAGMA synchronous=NORMAL;")
conn.executescript(SCHEMA_SQL)
conn.execute(
"INSERT OR IGNORE INTO collector_heartbeat (id, consecutive_failures) VALUES (1, 0)"
)
conn.commit()
return conn