- New lib/targets.ts: per-code localStorage (key `targets:<code>`) with
read/write/clear; rejects non-positive/non-finite values.
- New PriceTargets sidebar panel: 목표가/손절가 inputs, live %-from-current
preview (rose=up, sky=down), save/clear actions.
- StockChart accepts optional `targets` prop and draws dashed horizontal
price lines on the candle series (rose=target, sky=stop) with axis labels.
- Page loads saved targets on mount/code-change and re-renders chart on save.
Also fixes view-counter dedupe caveat from reviewer: split into
wasRecordedToday() + markRecorded(); the page now marks localStorage only
after POST /api/views succeeds, so a failed POST stays retryable on the
next visit instead of being silently swallowed for the day.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
토스 차트 인상 — 메인 캔들에 hover 하면 RSI/MACD 보조 패널도 같은 시점을
가리키며 가격 라벨이 뜬다. lightweight-charts setCrosshairPosition /
clearCrosshairPosition API 활용.
- rsiByTsRef / macdSignalByTsRef: 보조 시계열의 ts→value O(1) lookup.
RSI/MACD 데이터 push 할 때 동시에 채움.
- crosshair handler: hover 시 보조 차트도 setCrosshairPosition,
마우스가 차트 밖이면 clearCrosshairPosition 으로 양쪽 다 해제.
- MACD 는 signal 라인 기준 — 가격 라벨이 안정적으로 보이도록.
- 보조 차트 toggle off / 데이터 부족 시점은 ref guard 와 lookup miss 로 자연스럽게 noop.
차트 위에 hover 위치 봉의 날짜(+요일)/OHLC/등락률/거래량을 띄우는 좌상단
정보 박스 추가. lightweight-charts subscribeCrosshairMove 로 hover 좌표를
잡고, ohlcv 를 timestamp 기준 Map 으로 O(1) 조회. hover 가 차트 밖일 때는
마지막 봉을 기본 표시해 페이지 진입 직후에도 정보가 보임.
- 거래량 fmt: 억/만 (사이드바와 동일)
- 등락률: (close-open)/open, 한국 컬러 (상승=#ef4444 / 하락=#3b82f6)
- intraday(10분봉) 면 시:분 까지 포함
- 캔들 priceScale 을 위 78%(top=0.05, bottom=0.22)로 좁힘
- 거래량 Histogram 시리즈를 overlay priceScale("volume")로 같은 차트에 부착,
scaleMargins top=0.82 → 차트 영역 아래 18% 만 사용
- 상승봉=빨강(0x40 알파), 하락봉=파랑 — 한국 거래소 관행
- 가격축 라벨/마지막값/priceLine 숨김 → 캔들 시야 방해 최소화
- 시계열은 메인 timeScale 그대로 따라가서 별도 sync 불필요
cleanup 에서 volumeRef.current=null 도 같이 정리. intraday 포함 항상 ON
(거래량은 일/분봉 공통으로 의미 있음).
- EMA + MACD(line/signal/hist) 계산 함수 추가
- MACD 라인(파랑) + Signal 라인(주황) + Histogram (양수=빨강 / 음수=파랑 옅게)
- 별도 lightweight-charts 인스턴스 (RSI 와 동일 패턴, handleScroll/Scale off)
- MA chip 줄에 MACD 토글 chip 추가, 기본 OFF, intraday 에선 숨김
- timeScale 동기화 effect 를 단일 follower 리스트로 일반화 (RSI + MACD 동시 가능)
EMA 헬퍼는 null-tolerant — 결측 시점은 직전 ema 유지. Wilder 가 아닌
표준 EMA (alpha=2/(n+1)) 채택, 트레이딩뷰/Toss 와 동일.
- Wilder's smoothing 기반 RSI 14일 계산 (워밍업 구간 null)
- 메인 차트 아래 110px 별도 lightweight-charts 인스턴스로 sub-pane
- 30/70 가이드 라인 (axisLabel 표시)
- 메인 ↔ RSI timeScale 단방향 동기화 (RSI scroll/scale off)
- MA chip 옆 RSI 토글 chip — 기본 OFF, intraday 에선 숨김
별도 인스턴스 방식 채택 이유: 같은 chart 에 priceScaleId/scaleMargins 로 영역 분할 시
캔들 priceScale 까지 영향받아 메인 줌이 망가짐. sub-chart 패턴이 lightweight-charts
공식 권장 + react cleanup 도 깔끔.
- 예측 오버레이: 라인 시리즈 3개 (median/q10/q90) 를 단일 캔들 시리즈
하나로 합쳤다. 합성 OHLC: open=직전 close, close=point_close,
high=ci_high, low=ci_low. 옅은 색 (up #fda4af / down #93c5fd) 으로
실 캔들과 시각 톤은 같고 명도만 낮춰 "어우러지되 미래"임이 보이게.
- 예측 프리셋 단순화: 단기/중기/장기 + 직접입력 다 떼고 15일/30일/1년
3개로. 백엔드 horizon cap 30 → 252 로 확장 (1년 = 240 거래일).
- PriceHero: 종목명/현재가/등락 큰 글씨 헤더. KR 관례대로 상승=빨강,
하락=파랑.
- PeriodTabs: 1일/1주/1달/3달/1년/5년/최대 7탭. 기존 interval+days
이중 컨트롤 제거. 5년·최대 는 자동으로 주봉/월봉으로 폴백.
- 차트 본체 캔들 색조도 KR 관례 (적/청) 로 통일.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
lightweight-charts 의 timeScale tick 라벨에 직접 텍스트를 끼우는 공식 API 가
없어서, 차트 컨테이너 바로 아래에 작은 캡션 (• 오늘 · YYYY-MM-DD (요일)) 으로
표시. 사용자 요청 ("차트에 표시 말고 아래 날짜 표시하는 곳에").
- backend/app/api/chart.py: interval=10m|1d|1w|1mo. 10m 은 ohlcv_1m 을
time_bucket(10min) 으로 집계, stale(>10분) 이면 KIS 분봉 fetch 후 재조회.
1w/1mo 는 ohlcv_daily 를 date_trunc 로 집계. today 필드 추가.
- backend/app/fetch/kis.py: fetch_minute_price() 추가 (tr_id FHKST03010200).
KIS 응답 KST 시각을 tz-aware datetime 으로 변환, 오름차순 정렬.
- web/lib/api.ts: ChartInterval 타입, getChart(interval), predict(horizons[]).
- web/components/StockChart.tsx: 10m 이면 timeVisible. 일·주·월에서 오늘
화살표 마커 표시. ISO datetime 도 파싱.
- web/components/PredictionPanel.tsx: 단기/중기/장기 프리셋 + 사용자 직접
지정 (예: 1,2,3,7). API 에 horizons 배열 전달.
- web/app/[code]/page.tsx: interval 칩 (10분/일/주/월). 10m 일 때 60초마다
폴링. interval 별 기본 lookback (10m=1, 1d=180, 1w=730, 1mo=1825).