feat(stock): holdings intel API (intel/history/run)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 22:12:28 +09:00
parent 789785fe3a
commit 7d7064ae93
2 changed files with 64 additions and 1 deletions

View File

@@ -3,7 +3,7 @@ import json
import logging
from datetime import date as date_type
from typing import Optional
from fastapi import FastAPI, Query, Header, Depends, HTTPException
from fastapi import FastAPI, Query, Header, Depends, HTTPException, BackgroundTasks
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import requests
@@ -27,6 +27,7 @@ from .price_fetcher import get_current_prices, get_current_prices_detail
from .ai_summarizer import summarize_news, OllamaError
from .auth import verify_webai_key
from . import webai_cache
from . import holdings_intel
app = FastAPI()
install_access_log(app)
@@ -652,5 +653,25 @@ def remove_sell_history(record_id: int):
return {"ok": True}
# --- Holdings Intelligence API ---
@app.get("/api/stock/holdings/intel")
def holdings_intel_brief():
"""보유종목 인텔리전스 브리핑 (최신 시그널 + 포트 건강)"""
return holdings_intel.build_holdings_brief()
@app.get("/api/stock/holdings/intel/history")
def holdings_intel_history(ticker: str, days: int = 30):
"""종목별 시그널 이력 조회"""
from . import db
return {"ticker": ticker, "history": db.get_holdings_signal_history(ticker, days)}
@app.post("/api/stock/holdings/intel/run")
def holdings_intel_run(background_tasks: BackgroundTasks, use_llm: bool = True):
"""보유종목 시그널 계산 트리거 (BackgroundTask)"""
background_tasks.add_task(holdings_intel.compute_and_store, None, use_llm)
return {"ok": True, "queued": True}

View File

@@ -0,0 +1,42 @@
import os
import sys
import tempfile
from fastapi.testclient import TestClient
def _client(monkeypatch):
# Add web-backend root to sys.path so _shared can be imported by main.py
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
from app import db
monkeypatch.setattr(db, "DB_PATH", os.path.join(tempfile.mkdtemp(), "stock.db"))
db.init_db()
from app.main import app
return TestClient(app)
def test_holdings_intel_endpoint(monkeypatch):
client = _client(monkeypatch)
r = client.get("/api/stock/holdings/intel")
assert r.status_code == 200
body = r.json()
assert "holdings" in body and "portfolio_health" in body
def test_holdings_intel_history_endpoint(monkeypatch):
client = _client(monkeypatch)
r = client.get("/api/stock/holdings/intel/history?ticker=005930")
assert r.status_code == 200
body = r.json()
assert body["ticker"] == "005930"
assert "history" in body
assert isinstance(body["history"], list)
def test_holdings_intel_run_endpoint(monkeypatch):
client = _client(monkeypatch)
r = client.post("/api/stock/holdings/intel/run")
assert r.status_code == 200
body = r.json()
assert body["ok"] is True
assert body["queued"] is True