Spaces:
Sleeping
Sleeping
| """ | |
| Shared DuckDB connection and schema initialization for CommodiSense. | |
| All collectors import get_conn() from here. | |
| """ | |
| import duckdb | |
| from pathlib import Path | |
| DB_PATH = Path(__file__).parent / "commodisense.duckdb" | |
| def get_conn() -> duckdb.DuckDBPyConnection: | |
| """Return a persistent DuckDB connection. Creates the DB file if missing.""" | |
| return duckdb.connect(str(DB_PATH)) | |
| def init_schema() -> None: | |
| """Create all tables if they don't already exist. Safe to call repeatedly.""" | |
| conn = get_conn() | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS prices ( | |
| date DATE NOT NULL, | |
| symbol TEXT NOT NULL, | |
| open DOUBLE, | |
| high DOUBLE, | |
| low DOUBLE, | |
| close DOUBLE, | |
| volume DOUBLE, | |
| adj_close DOUBLE, | |
| PRIMARY KEY (date, symbol) | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS news_raw ( | |
| id TEXT PRIMARY KEY, | |
| source TEXT, | |
| published_date TIMESTAMP, | |
| title TEXT, | |
| summary TEXT, | |
| url TEXT, | |
| commodity_tags TEXT, | |
| sentiment_score DOUBLE, | |
| processed BOOLEAN DEFAULT FALSE | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS weather_features ( | |
| date DATE NOT NULL, | |
| region TEXT NOT NULL, | |
| commodity TEXT NOT NULL, | |
| temp_max DOUBLE, | |
| temp_min DOUBLE, | |
| precipitation DOUBLE, | |
| soil_moisture DOUBLE, | |
| drought_index DOUBLE, | |
| heat_stress_days INTEGER, | |
| precip_anomaly_pct DOUBLE, | |
| PRIMARY KEY (date, region, commodity) | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS geopolitical_events ( | |
| date DATE NOT NULL, | |
| event_type TEXT, | |
| region TEXT, | |
| commodity TEXT, | |
| risk_score DOUBLE, | |
| headline TEXT, | |
| source TEXT | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS sentiment_daily ( | |
| date DATE NOT NULL, | |
| commodity TEXT NOT NULL, | |
| sentiment_score DOUBLE, | |
| article_count INTEGER, | |
| positive_count INTEGER, | |
| negative_count INTEGER, | |
| PRIMARY KEY (date, commodity) | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS extracted_events ( | |
| date DATE, | |
| headline TEXT, | |
| event_type TEXT, | |
| commodity TEXT, | |
| location TEXT, | |
| severity INTEGER, | |
| direction TEXT, | |
| source TEXT | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS accuracy_log ( | |
| date DATE, | |
| symbol TEXT, | |
| forecast_direction TEXT, | |
| actual_direction TEXT, | |
| was_correct BOOLEAN, | |
| confidence TEXT | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS cot_data ( | |
| date DATE NOT NULL, | |
| symbol TEXT NOT NULL, | |
| commercial_net_long DOUBLE, | |
| commercial_net_pct DOUBLE, | |
| mm_net_long DOUBLE, | |
| mm_net_pct DOUBLE, | |
| commercial_chg_1w DOUBLE, | |
| mm_chg_1w DOUBLE, | |
| open_interest DOUBLE, | |
| PRIMARY KEY (date, symbol) | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS fred_data ( | |
| date DATE NOT NULL PRIMARY KEY, | |
| dxy DOUBLE, | |
| inflation_exp DOUBLE, | |
| vix DOUBLE, | |
| treasury_10y DOUBLE, | |
| financial_stress DOUBLE, | |
| indpro DOUBLE, | |
| fedfunds DOUBLE | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS eia_inventory ( | |
| date DATE NOT NULL, | |
| series TEXT NOT NULL, | |
| value DOUBLE, | |
| chg_1w DOUBLE, | |
| vs_5yr_avg DOUBLE, | |
| PRIMARY KEY (date, series) | |
| ) | |
| """) | |
| conn.execute(""" | |
| CREATE TABLE IF NOT EXISTS usda_crop ( | |
| date DATE NOT NULL, | |
| commodity TEXT NOT NULL, | |
| metric TEXT NOT NULL, | |
| value DOUBLE, | |
| yoy_chg_pct DOUBLE, | |
| PRIMARY KEY (date, commodity, metric) | |
| ) | |
| """) | |
| conn.close() | |
| if __name__ == "__main__": | |
| init_schema() | |
| print(f"Schema initialized at {DB_PATH}") | |