미증시 페어 베타·시그널 결과 표시 버그 수정

us-market/main.py:
  1) /signal/latest 라우트 순서 버그 수정
     - 기존: /signal/{kr_code} 가 먼저 선언되어 'latest'를 코드로 매칭 → 항상 []
     - 수정: /signal/latest 를 path-param 라우트보다 위로 이동
  2) pair beta 재계산이 stock_prices(7~10일치)에서 데이터 부족으로 32건 전부 skip
     - stock_ohlcv(81일치) 우선 조회, 폴백으로 stock_prices 유지
     - 결과: updated 0→32, 베타·상관 정상 산출

dashboard-api/index.html:
  - 미증시 시그널 카드 필드명 수정 (signal_score → total_adj/sector_adj/pair_adj)
  - 절대값 큰 순 정렬 + 섹터/페어 기여도 분해 표시

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
kyu
2026-05-20 22:25:44 +09:00
parent a02d23de8d
commit 324c7a4b95
2 changed files with 42 additions and 24 deletions
+27 -19
View File
@@ -593,14 +593,21 @@ async def recalc_pair_betas(window_days: int = 60):
if len(us_rows) < 30:
skipped += 1
continue
# 한국 시계열 (stock_prices.collected_at)
# 한국 시계열 (stock_ohlcv 우선 — 일봉 80일+ / 폴백: stock_prices)
kr_rows = await conn.fetch("""
SELECT collected_at::date AS dt,
AVG(price)::float AS close
FROM stock_prices
WHERE stock_code=$1 AND collected_at::date >= $2
GROUP BY collected_at::date ORDER BY dt
SELECT dt, close_price::float AS close
FROM stock_ohlcv
WHERE stock_code=$1 AND dt >= $2 AND close_price > 0
ORDER BY dt
""", kr_c, since)
if len(kr_rows) < 30:
kr_rows = await conn.fetch("""
SELECT collected_at::date AS dt,
AVG(price)::float AS close
FROM stock_prices
WHERE stock_code=$1 AND collected_at::date >= $2
GROUP BY collected_at::date ORDER BY dt
""", kr_c, since)
if len(kr_rows) < 30:
skipped += 1
continue
@@ -751,6 +758,20 @@ async def manual_signal(target: Optional[str] = None):
return await calc_overnight_signals_all(d)
@app.get("/signal/latest")
async def latest_signals(limit: int = Query(default=50, le=500)):
"""주의: /signal/{kr_code}보다 먼저 선언해야 함 — 안 그러면 'latest'를 kr_code로 매칭."""
async with pg_pool.acquire() as conn:
rows = await conn.fetch("""
SELECT DISTINCT ON (kr_code)
kr_code, signal_date, sector_adj, pair_adj, total_adj
FROM us_overnight_signal
ORDER BY kr_code, signal_date DESC
LIMIT $1
""", limit)
return [dict(r) for r in rows]
@app.get("/signal/{kr_code}")
async def get_signal(kr_code: str, days: int = Query(default=7, ge=1, le=90)):
async with pg_pool.acquire() as conn:
@@ -763,19 +784,6 @@ async def get_signal(kr_code: str, days: int = Query(default=7, ge=1, le=90)):
return [dict(r) for r in rows]
@app.get("/signal/latest")
async def latest_signals(limit: int = Query(default=50, le=500)):
async with pg_pool.acquire() as conn:
rows = await conn.fetch("""
SELECT DISTINCT ON (kr_code)
kr_code, signal_date, sector_adj, pair_adj, total_adj
FROM us_overnight_signal
ORDER BY kr_code, signal_date DESC
LIMIT $1
""", limit)
return [dict(r) for r in rows]
@app.get("/pairs")
async def list_pairs(kr_code: Optional[str] = None, us_ticker: Optional[str] = None):
async with pg_pool.acquire() as conn: