feat: ADR 추세 차트 20일 미만 누적 구간도 표시(확장 윈도우)

_compute_adr_ma_series를 확장 윈도우로 — window 미만 구간은 가용한 만큼의 평균으로 1일차부터 점 생성.
누적이 20일 도달하면 정식 trailing-20 이평과 동일(steady-state 불변, 검증됨). 누적 중엔 제목에 '누적 N/20일' 표시.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hyowons
2026-06-08 15:55:19 +09:00
parent e01e0b8a62
commit ceb9b8565d
+9 -6
View File
@@ -5116,12 +5116,13 @@ def _compute_adr_ma_latest(symbol: str, today_raw_adr: float | None, today_date:
def _compute_adr_ma_series(rows: list[dict], window: int = ADR_MA_WINDOW) -> list[tuple[str, float, bool]]:
"""rows(오래된 순, {date,adr,is_live}) → 각 시점 trailing window 평균 시리즈.
[(date, ma, is_live), ...]. window 채워지지 않은 앞쪽은 skip.
is_live는 시점 윈도우에 라이브 점이 포함됐는지 (= 마지막 평균 라이브일 가능성)."""
[(date, ma, is_live), ...].
확장 윈도우: window 미만 누적 구간은 '가용한 만큼'(최대 window일) 평균으로 점을 만든다
1일차부터 그려지고 누적이 window에 도달하면 정상 trailing-window 평균과 동일(steady-state 동작 불변)."""
series: list[tuple[str, float, bool]] = []
for i in range(window - 1, len(rows)):
win = rows[i + 1 - window : i + 1]
avg = sum(r['adr'] for r in win) / window
for i in range(len(rows)):
win = rows[max(0, i + 1 - window) : i + 1]
avg = sum(r['adr'] for r in win) / len(win)
is_live = any(r.get('is_live') for r in win)
series.append((rows[i]['date'], avg, is_live))
return series
@@ -5577,10 +5578,12 @@ def _render_adr_trend_card(days: int = ADR_TREND_DAYS) -> str:
f'</div>'
)
# 누적 < window 면 아직 정식 20일 이평이 아니라 '가용한 만큼'의 평균 → 제목에 명시.
accum_note = f' · 누적 {raw_count_max}/{ADR_MA_WINDOW}' if raw_count_max < ADR_MA_WINDOW else ''
return (
'<div class="market-card adr-trend-card">'
f'<div class="market-card-title">ADR 추세 <span class="market-card-sub">{ADR_MA_WINDOW}일 이평 · '
+ html.escape(sel_label) + '</span></div>'
+ html.escape(sel_label) + accum_note + '</span></div>'
+ summary_block
+ f'<div class="market-section-hint">{ADR_MA_WINDOW}일 이동평균 ADR · 회색점선=100(균형) · 파란점선=75(침체) · 빨간점선=125(과열) · *=오늘(라이브 포함)</div>'
+ _render_adr_trend_controls(days)