feat: 종목차트 탭 재배열 + 3개월 추가 — 1분봉/5분봉/1개월/3개월/6개월/1년

- CHART_RANGE_DAYS에 '3M': 63 추가 (stock_analysis)
- /api/chart_svg 탭·패널 순서를 분봉 우선으로 재배열, 3M 패널 신설
- 기본 활성 탭은 1개월 유지

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hyowons
2026-06-12 10:28:08 +09:00
parent ff3652c8b1
commit 72b98409f2
2 changed files with 14 additions and 11 deletions
+12 -9
View File
@@ -10300,10 +10300,11 @@ class Handler(BaseHTTPRequestHandler):
'sma20': sa.sma(closes, 20),
'sma60': sa.sma(closes, 60),
}
# 분석 페이지와 동일 패턴 — 1Y/6M/1M 3 개 panel + 탭. 250 봉 캐시 슬라이스만 다름.
# 분석 페이지와 동일 패턴 — 1M/3M/6M/1Y 4 개 panel + 탭. 250 봉 캐시 슬라이스만 다름.
# 분봉 panel 은 빈 placeholder. 탭 클릭 시 클라이언트가 lazy fetch.
svg_1y = sa.render_svg_chart(snap, range_key='1Y')
svg_6m = sa.render_svg_chart(snap, range_key='6M')
svg_3m = sa.render_svg_chart(snap, range_key='3M')
svg_1m = sa.render_svg_chart(snap, range_key='1M')
# 분봉 panel 안에 기간 sub-tabs (30분/1h/3h/5h/하루). default = '1h'.
# subpanel 은 클라이언트가 sub-toggle 이벤트로 lazy fetch.
@@ -10322,17 +10323,19 @@ class Handler(BaseHTTPRequestHandler):
)
html_block = (
'<div class="chart-tabs">'
'<button type="button" data-range="1Y">1년</button>'
'<button type="button" data-range="6M">6개월</button>'
'<button type="button" data-range="1M" class="active">1개월</button>'
'<button type="button" data-range="5m" data-unit="5m">5분봉</button>'
'<button type="button" data-range="1m" data-unit="1m">1분봉</button>'
'<button type="button" data-range="5m" data-unit="5m">5분봉</button>'
'<button type="button" data-range="1M" class="active">1개월</button>'
'<button type="button" data-range="3M">3개월</button>'
'<button type="button" data-range="6M">6개월</button>'
'<button type="button" data-range="1Y">1년</button>'
'</div>'
f'<div class="chart-panel" data-range="1Y">{svg_1y}</div>'
f'<div class="chart-panel" data-range="6M">{svg_6m}</div>'
f'<div class="chart-panel active" data-range="1M">{svg_1m}</div>'
+ _minute_panel('5m')
+ _minute_panel('1m')
+ _minute_panel('5m')
+ f'<div class="chart-panel active" data-range="1M">{svg_1m}</div>'
f'<div class="chart-panel" data-range="3M">{svg_3m}</div>'
f'<div class="chart-panel" data-range="6M">{svg_6m}</div>'
f'<div class="chart-panel" data-range="1Y">{svg_1y}</div>'
)
body = html_block.encode('utf-8')
body, enc = _maybe_gzip(body, self.headers.get('Accept-Encoding'))
@@ -543,13 +543,13 @@ VOL_TOP = PRICE_BOT + PANEL_GAP
VOL_BOT = VOL_TOP + VOL_PANEL_H
CHART_RANGE_DAYS = {'1Y': 250, '6M': 120, '1M': 21}
CHART_RANGE_DAYS = {'1Y': 250, '6M': 120, '3M': 63, '1M': 21}
def render_svg_chart(snap: dict, range_key: str = '1Y', ref_price: float | None = None, intraday: bool = False) -> str:
"""캔들 + SMA 3선 + 거래량 막대 인라인 SVG.
range_key: '1Y' (250일) | '6M' (120일) | '1M' (21일). 같은 snapshot 데이터에서 슬라이스만.
range_key: '1Y' (250일) | '6M' (120일) | '3M' (63일) | '1M' (21일). 같은 snapshot 데이터에서 슬라이스만.
ref_price: 기준가(전일종가 등) — 지정 시 노란 점선 기준선 + 마지막 종가의 대비 등락률 표시 (분봉용).
snap: collect_snapshot 결과. candles_asc·sma5/20/60 사용.
외부 JS 의존성 0. CSS는 inline.