diff --git a/stock-lab/app/screener/schema.py b/stock-lab/app/screener/schema.py index cde379d..17aae14 100644 --- a/stock-lab/app/screener/schema.py +++ b/stock-lab/app/screener/schema.py @@ -12,6 +12,7 @@ DEFAULT_WEIGHTS = { "rs_rating": 1.2, "ma_alignment": 1.0, "vcp_lite": 0.8, + "ai_news": 0.8, } DEFAULT_NODE_PARAMS = { "foreign_buy": {"window_days": 5}, @@ -21,6 +22,7 @@ DEFAULT_NODE_PARAMS = { "rs_rating": {"weights": {"3m": 2, "6m": 1, "9m": 1, "12m": 1}}, "ma_alignment": {"ma_periods": [50, 150, 200]}, "vcp_lite": {"short_window": 40, "long_window": 252}, + "ai_news": {"min_news_count": 1}, } DEFAULT_GATE_PARAMS = { "min_market_cap_won": 50_000_000_000, @@ -110,12 +112,45 @@ CREATE TABLE IF NOT EXISTS screener_results ( FOREIGN KEY (run_id) REFERENCES screener_runs(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_results_run_rank ON screener_results(run_id, rank); + +CREATE TABLE IF NOT EXISTS news_sentiment ( + ticker TEXT NOT NULL, + date TEXT NOT NULL, + score_raw REAL NOT NULL, + reason TEXT NOT NULL DEFAULT '', + news_count INTEGER NOT NULL DEFAULT 0, + tokens_input INTEGER NOT NULL DEFAULT 0, + tokens_output INTEGER NOT NULL DEFAULT 0, + model TEXT NOT NULL DEFAULT 'claude-haiku-4-5-20251001', + created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')), + PRIMARY KEY (ticker, date) +); +CREATE INDEX IF NOT EXISTS idx_news_sentiment_date ON news_sentiment(date DESC); """ def ensure_screener_schema(conn: sqlite3.Connection) -> None: """Create tables and seed default settings (idempotent).""" conn.executescript(DDL) + # ai_news 키 누락 시 1회 보충 (이미 운영 중인 환경에 대해) + row = conn.execute( + "SELECT weights_json, node_params_json FROM screener_settings WHERE id=1" + ).fetchone() + if row is not None: + w = json.loads(row[0]) + p = json.loads(row[1]) + changed = False + if "ai_news" not in w: + w["ai_news"] = DEFAULT_WEIGHTS["ai_news"] + changed = True + if "ai_news" not in p: + p["ai_news"] = DEFAULT_NODE_PARAMS["ai_news"] + changed = True + if changed: + conn.execute( + "UPDATE screener_settings SET weights_json=?, node_params_json=? WHERE id=1", + (json.dumps(w), json.dumps(p)), + ) existing = conn.execute("SELECT id FROM screener_settings WHERE id=1").fetchone() if existing is None: now = datetime.now(timezone.utc).isoformat() diff --git a/stock-lab/requirements.txt b/stock-lab/requirements.txt index fba6382..3bc3244 100644 --- a/stock-lab/requirements.txt +++ b/stock-lab/requirements.txt @@ -1,4 +1,5 @@ # 주식 서비스용 라이브러리 +anthropic==0.39.0 requests==2.32.3 httpx==0.27.2 beautifulsoup4==4.12.3