- frontend: 대시보드를 TradingView 레이아웃으로 재구성(components/tv/*) — 캔들+MA/BB/거래량,
평단·손절·목표·트레일링 가격선, 체결 마커, RSI 기준선은 실효 설정값, 하단 탭(보유·체결·DT 카드·
비용 후 손익곡선/낙폭·저널), 디자인 토큰·한국식 색·최소 11px, 모바일 가로 스크롤 제거
- backend(GET 전용, require_api_key): /positions/overlay, /risk/equity-history,
/strategy-config/display, /trades 응답 필드(side·strategy_type·commission·net_profit_loss),
/risk/mdd-status thresholds, /market-data/chart 1m|5m(캐시·in-flight 공유)
- mean_reversion_strategy: RSI 청산 임계를 resolve_swing_exit_rsi_v2 로 추출(동작 동일) —
청산과 화면 표시가 같은 값을 쓴다
- §8.5-39: SWING_STOP_IGNORE_CRISIS_OVERLAY(기본 False) — 반사실 재생에서 Crisis 조기 손절이
오히려 손실을 줄여 기본 OFF 유지, 정식 백테스트 전 켜지 말 것
- 유닛 스위트 2816 passed / 0 failed, tsc·build 통과
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
사용자 요청: 스윙 목록 사이에 데이 종목이 끼어 보이지 않게 — 데이트레이딩 섹션·카운트 제거,
합산 행은 스윙 몫만 표시(DT 몫은 하단 DayTradingStatusBar). 매매 로직 변경 없음.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- portfolioGrouping.ts: DT 엔진 포지션 → 데이트레이딩, strategy_type 으로 swing(+NULL)/external·manual/us_swing 분류
- 스윙+DT 합산 행(Portfolio stock_code UNIQUE)은 DT 엔진 수량만큼 분할 표시, 분할 카드·DT 수량 미상 카드는 청산 버튼 비활성
(수동 매도는 DT 몫부터 차감되므로 분할 매도 불가 안내)
- 그룹별 종목 수·평가금액·손익 소계, 상단 카운트 데이/스윙/수동/해외 정정
- 매매 로직·백엔드 변경 없음
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- GET /api/v1/market/indices — 네이버 JSON API(비-KIS), 45초 캐시
- 부분 실패 시 직전값 병합, 전부 실패 시 12초 쿨다운 + 직전 캐시 반환
- 방향 code 해석 불가 시 원 부호 폴백, NaN/inf 거부
- MarketIndexBar: 60초 갱신, 상승 빨강/하락 파랑, 장 마감 배지
- 테스트 12건 (전체 877 passed)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
매매일지는 정상 생성되고 있었다(205건, 커버리지 100%, 16:00 자동 생성도 동작).
"작성이 안 된다"의 실체는 아래 표시 계층 문제였다.
## 표시
- Dashboard journals 쿼리가 staleTime:Infinity + refetchInterval 없음이라
페이지 로드 순간의 목록에서 영구 고정됐다 → 30s/60s 폴링
- WS journal_created 는 205건 중 13건(6%)만 발화하고(16:00 스케줄러와
/analysis/generate-journals 는 브로드캐스트 없음) 그마저 커밋 전에 나간다
→ 이벤트 의존 제거, 수신 시 즉시+3초 재invalidate 로 레이스 보강
- 수동 버튼이 목록을 갱신하지 않고 안내가 "매매 로그"(없는 위치)를 가리켰다
→ invalidateQueries + 실제 위치·비동기 지연 명시
## 시각 +9h
- journals 가 KST naive 값에 UTC 라벨을 붙여 화면이 +9h 밀렸다
(실측 KST 15:48 → 화면 09-30 00:48, 즉 당일 16:00 일지가 "다음날 01:00")
- _utc_iso → _kst_iso, +09:00 명시. 세 응답 지점 통일(기존엔 목록/상세가 달랐다)
- /trades 는 raw naive + 프론트 보정으로 짝이 맞아 있어 건드리지 않았다
(회귀 테스트가 trades.py 에 +09:00 유입을 차단)
- JournalPanel 에 조건부 +09:00 정규화 추가(매매내역 경로와 동일 패턴)
## now_kst 섀도잉 4곳
- from timeutil import now_kst 해놓고 함수 내 now_kst = _dt.now(_KST) 로 대입해
같은 함수의 now_kst() 가 TypeError. post_market 에서 실장애였고 나머지 3곳은
무증상 잠재 → 전부 _now 로 리네임 (AST 전수, backend+mcp-server 잔존 0)
- TypeError 를 은폐하던 logger.debug → warning(exc_info=True), except: pass 1곳도
## trade_id=0 중복
- db_worker 에 _handle_insert_trade_journal 신설 — order_id 로 TradeHistory.id
해소, 해소 실패 시 None(0 아님). 정상경로·종료 drain 공용
- 커버 판정 trade_id > 0 (id 는 PK라 0 은 애초에 아무 행도 커버하지 않음)
- order_id 추출이 raw KIS 응답에 없는 top-level "odno" 였다 → output.ODNO 우선
## 전략 파라미터 자동 적용 차단 (STRATEGY_AUTO_APPLY_ENABLED=False)
섀도잉 수정이 post_market 의 자동 최적화를 부활시킨다 — run_optimization 이
strategy_cfg.upsert() 로 실매매 파라미터(RSI 진입·손절·포지션 크기)를 덮어쓴다.
게이트가 "최근 7일 SELL>=5건"이라 5거래 표본 그리드 서치가 alembic 0012 로
정합시킨 값을 조용히 바꿀 수 있다 — §8.1-5·§8.4·§8.5-1 과 정면 충돌.
- 계산·분석·로그는 유지하고 upsert 만 차단. 가드 2단, 둘 다 try 밖
- 차단 시 키별 현재값→제안값 + IS/OOS Sharpe 를 warning + apply_reason 에 기록
- 켜기 전 §8.4 백테스트 요건 충족 필요(config 주석에 명시)
## 부수 발견
strategy_config_service.upsert 가 __import__("datetime").now_kst() 로 항상
AttributeError → 전략 파라미터 저장이 UI·일괄·optimizer 전 경로에서 500이었다.
역설적으로 이것이 자동적용의 2차 방어선이었다 — 고쳤으므로 플래그가 필수다.
⚠️ 배포 후 UI 파라미터 저장이 처음으로 실제 동작한다(§0 정합 주의).
테스트 677 → 715 passed / 0 failed. 전략 임계값 정적 변경 0건.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## 재기동 내구성
- scheduler: 복원 직후 reset_if_new_day()가 복원분을 전부 폐기하던 버그
(begin_restore()로 날짜 경계를 선확정. 복원 성공 로그는 뜨는데 실제로는 지워졌다)
- 일일 안전장치(daily_pnl/loss_streak_today/closed_today) Redis 영속화
날짜를 키와 페이로드 양쪽에 실어 이중 게이트, 복원은 보수적 병합
(손익 min/연패 max/청산목록 합집합 — 복원이 안전장치를 약화시킬 수 없다)
- db_worker 종료 drain이 insert_trade_history만 커밋하고 포지션 추적 행은
DLQ로 버리던 비대칭 제거 + DLQ 재처리 경로 신설(쓰기 전용이었다)
- 장중 기동 시 ORB 소급 수집(backfill), 전일 캔들 혼입 차단
- swing/exit_service "보유 종목 없음" debug→info, 10회 연속 warning
## DT 진입 복구
- 워밍업 회귀 복구: 1b9257c(2026-09-28)가 조회 계층에 당일 필터를 넣어
5분봉 RSI(14)/BB(20) 워밍업이 죽고 VWAP/RSI_BB가 10:15/10:40 이전
발화 불가가 됐다. 필터를 삭제하지 않고 용도별로 분리
(get_minute_chart_full_day_v2 신설, 기존 메서드·3개 호출부 동작 무변경)
- 거래량 게이트 비교 대상 교정: 형성 중 봉 → 완성봉 (5분봉·ORB 1분봉 양쪽)
임계값(1.3/1.5)은 불변, 고친 것은 비교 대상뿐
- 세션 경계 차단: _last_session_candles()로 거래량 비교가 전일 봉을 잡아
개장 직후 게이트가 자동 통과하는 것을 방지
- 스캔 선조회(동시성 4)·종목 타임아웃·시간예산·라운드로빈 + 잘린 종목 수 로그
- watchlist 30분 갱신 시 ORB 보유 종목 우선 유지
## 유입 잔고 격리
- sync_portfolio()가 시스템 매수 근거 없는 KIS 잔고를 자기 스윙 포지션으로
편입해 자동 손절로 처분하던 문제 → strategy_type='external' 격리
(승격만 허용, 강등 없음. 기존 행은 수동 SQL 필요)
- 격리분 손절선 이탈은 집행 없이 warning + summary 노출
- 수동 청산 경로에 record_trade_result 누락 보강, 전략 간 당일 쿨다운
## 4% 상한
- market_data 표시 경로 클램프 누락 + confidence 배율 후 재클램프
- 회귀 방지 테스트(AST로 가드가 try 밖에 있는지 검증)
## 프론트
- 총자산 보정 가드(3%·종목수·가격결손·국내분 한정), 원인 미규명 명시
- cumulative_realized_pl이 /portfolio/combined에 없어 항상 0이던 문제
테스트 579 → 677 passed / 0 failed (소켓 차단 하 통과, 실호출 없음)
전략 임계값 변경 0건
⚠️ 워밍업 복구의 효과 크기는 미확정 — KIS 분봉 API에 날짜 파라미터가 없어
미래 ref_time에 전일 데이터를 주는지가 미검증 전제다. 배포 후
"[분봉] 워밍업 5분봉 N봉 (당일 a + 전일 b)" 로그의 b로 확정할 것.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
trade_history.stock_name 이 비어 있는 행이 있어 분석 화면의 최대 손실/수익
Top5 가 종목코드만 노출됐다. stock_analysis → portfolio 순으로 종목명을
보강 조회하고, 없으면 코드를 그대로 쓴다(부가 정보이므로 조회 실패는
warning 후 분석 계속).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CLAUDE.md §5.2 기준으로 계산해 매수 추천 금액 아래에 함께 표시.
· 손절 = ATR(2.5×)과 -7% 중 타이트한 쪽(가격 높은 쪽), 적응형 모드면 그 값 사용
· 목표 = 진입가 + 2R (R = 진입가 − 손절가) — +2R 50% 분할 매도 지점
ATR 은 stock_analysis.atr_14 우선, 없으면 DB 일봉으로 계산(KIS API 미사용). 테스트 4건 추가.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BUY 신호일 때 실제 자동매매와 동일한 기준으로 매수 금액·수량을 계산해 패널 상단에 표시.
· 종목당 상한 = 총자산 × MAX_POSITION_SIZE(적응형 모드면 그 값)
· 신뢰도 보정 = 예산 × (confidence/0.7), 0.5~1.2배
· 현금 여력(최소 현금보유 제외)·스윙 합산 상한(SWING_MAX_CAPITAL_RATIO) 잔여로 클램프
BUY 가 아니거나 예산이 1주 미만이면 금액 대신 사유를 표시. 테스트 6건.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 예수금: dnca_tot_amt(D+2 기준)를 먼저 읽어 당일 매수가 많으면 -913,965원처럼 음수가
표시됐다. 주문가능현금(_ord_psbl_cash) → prvs_rcdl_excc_amt → nxdy_excc_amt 순으로
첫 양수를 사용한다(데이트레이딩 엔진과 동일 기준).
- 프론트: /auth/me 가 한 번 실패하면(배포 중 502) useTenantMode.mode 가 undefined 로 남아
포트폴리오·매매 쿼리가 전부 enabled:false 로 멈췄다(오늘 26분간 API 호출 0건 확인).
auth-me 를 실패 시 10초 간격 재시도로 바꾸고, queryClient 기본값에 retry 3회/백오프,
refetchOnReconnect, networkMode:'always' 를 적용해 백엔드 복구 시 자동으로 되살아나게 함.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- portfolio_cache_bridge 신설: 매매 엔진 체결 시 Portfolio(db_worker 큐) + 인메모리 캐시 즉시 갱신.
DT 매수는 strategy_type='daytrading'으로 태깅되어 보유 종목 패널의 '데이트레이딩' 그룹에 표시되고
스윙 청산 로직(strategy_type='swing' 대상)에서 제외됨. (기존엔 KIS 동기화로 'swing'으로 유입돼
DT 포지션이 안 보이고 스윙 엔진이 같이 관리하는 문제)
- DT 매도·스윙 자동 매도도 캐시에서 즉시 제거/차감 + 최근매도 기록(동기화 되살림 방지).
- 동기화 시 DT 엔진 보유 종목은 'daytrading'으로 태깅.
- 프론트: 수동 매도 성공 시 낙관적 갱신으로 서버 재조회 전 즉시 목록에서 제거.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- 프론트: 토스트 알림 시스템(lib/toast + ToastHost) 추가, 매도/매수 성공·실패를 화면에 표시
(기존엔 console.log만, 실패는 블로킹 alert). 성공 토스트에 손익 표시.
- 매도 직후 예수금/평가액 요약 즉시 갱신(apply_sell), 최근 5분 내 수동 매도 종목은
KIS 잔고 반영 지연으로 동기화가 되살리지 않도록 스킵(recent_sells).
- 예수금이 D+2 결제 기준(dnca_tot_amt)이라 당일 매도대금이 화면·데이트레이딩 가용현금에
반영되지 않던 문제: 매수가능조회(inquire-psbl-order) ord_psbl_cash 를 우선 사용.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
/daytrading/{status,watchlist,positions}(v1)는 main.py가 실행하는 엔진
(services/daytrading)과 공유되지 않는 별개 인메모리 dict를 읽어 항상 0을 반환했음.
조회는 entry_service 감시목록·day_trading_state 기준으로 응답하고, POST /watchlist는
엔진에도 반영. 프론트 보유종목 패널 하단에 감시/ORB/포지션/청산/당일손익·현재 단계
(ORB 수집중·신호 대기·쿨다운 등)를 30초 폴링으로 표시.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
세션 로그인 사용자는 프론트가 v2(/portfolio/v2)를 쓰는데, 멀티테넌트가 꺼져 있으면
v2 컨텍스트가 legacy로 떨어져 KIS 동기화 없이 DB 스냅숏만 반환 → 현재가·손익이 갱신되지 않음.
/auth/me 에 multi_tenant_enabled 를 추가하고, 프론트는 세션 로그인 AND 플래그 true 일 때만 v2 사용.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
로그인 사용자명(관리자 배지, API 키면 '운영자') 표시 → /account 링크.
로그아웃은 localStorage api_key 제거 후 로그인 화면으로.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- models.User + alembic 0008 (users: username unique, bcrypt password_hash, is_active, is_admin)
- auth.py: POST /auth/register, /auth/login, GET /auth/me, 관리자용 GET /auth/users,
POST /auth/users/{id}/approve|revoke. bcrypt 는 asyncio.to_thread 로 오프로드,
미존재 계정도 더미 해시 검증(타이밍 균등화), IP당 실패 잠금 유지
- 정책: 첫 가입자 = 관리자·즉시 활성, 이후 가입자는 관리자 승인 필요
(SIGNUP_AUTO_APPROVE=true 로 해제, SIGNUP_ENABLED=false 로 가입 차단). API 키는 관리자 취급
- config: ADMIN_USERNAME/ADMIN_PASSWORD(_HASH) 제거 → SIGNUP_ENABLED / SIGNUP_AUTO_APPROVE
- Login.tsx: 로그인/회원가입 탭, 비밀번호 확인, 승인 안내 배너, 상태코드별 메시지,
첫 가입자는 가입 직후 자동 로그인
- DB 접근: 회원가입/로그인은 sync_portfolio 와 같은 단일 트랜잭션 예외로 엔드포인트 직접 접근
(컨테이너 Postgres 대상 통합 테스트 19건 통과)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- auth.py 신규: POST /api/v1/auth/login → JWT 세션 토큰(HS256, SECRET_KEY 서명, 24h)
GET /api/v1/auth/me 자격 확인. IP당 5회 실패 시 300초 잠금(인메모리)
- config: ADMIN_USERNAME / ADMIN_PASSWORD / ADMIN_PASSWORD_HASH(bcrypt) /
SESSION_TOKEN_EXPIRE_HOURS / LOGIN_MAX_FAILURES / LOGIN_LOCKOUT_SECONDS
- security: create_session_token / verify_session_token / is_valid_credential 추가.
require_api_key·optional_api_key 는 시그니처 유지, X-API-Key 값으로 API 키 또는
세션 토큰 모두 수용 → 프론트 api.ts·useWebSocket·MCP 서버 호출 경로 무변경
- main.py WebSocket 인증도 is_valid_credential 로 통일
- bcrypt 검증은 passlib 대신 bcrypt 직접 사용 (passlib 1.7.4 ↔ bcrypt 5.0 비호환)
- Login.tsx: 아이디/비밀번호 폼, 401/429/503 별 안내 메시지
- .env.example 에 관리자 계정 항목 추가
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Login: 카드형 레이아웃, 키 아이콘·표시/숨김 토글, 인라인 에러(aria), 로딩 스피너,
입력 시 에러 자동 해제, 그라디언트 텍스트 제거
- Layout 헤더: 태그라인 삭제, 브랜드명 단일 표기
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
DS1517+(Atom C2538)에서 빌드가 30분 이상 걸리던 원인 두 가지를 제거.
1. PyTorch CPU 전용 휠 사용 (backend)
PyPI 기본 torch 휠은 nvidia-cublas/cudnn 등 CUDA 패키지를 수 GB
함께 내려받는데 NAS에는 GPU가 없어 전부 불필요했다.
download.pytorch.org/whl/cpu 에서 먼저 설치하면 requirements.txt 의
torch 줄은 충족되어 건너뛴다. ml_ensemble 은 이미 지연 임포트라 동작 동일.
2. pip/npm 캐시를 빌드 간 재사용 (backend, mcp-server, frontend)
--no-cache-dir 제거하고 RUN --mount=type=cache 로 전환.
requirements.txt 가 바뀌어도 받아둔 휠은 재다운로드하지 않는다.
Jenkinsfile 에 DOCKER_BUILDKIT/COMPOSE_DOCKER_CLI_BUILD 추가.
부수: frontend Dockerfile 의 FromAsCasing 경고 정리 (as build → AS build).
세 Dockerfile 모두 docker build --check 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
## CRITICAL/HIGH (S1-S8)
- S1: Aggressive 모드 %B 스케일링 캡 1.3 (BB 중앙선 위 매수 방지)
- S2: ML scaler train-only fit (데이터 누수 제거)
- S3: SIDEWAYS = ADX<20 AND slope≈0 (트렌드 초기 차단 해소)
- S4: EOD 청산 실패 시 재시도 + CRITICAL 로그
- S5: 일일 손실 한도에 미실현 P&L 포함
- S6: trailing stop 고점 매 사이클 갱신
- S7: 섹터 필터 미매핑 종목 "기타" 분류 (max 3 적용)
- S8: 스캐너 RSI 기준 25→46, BB 점수 -3%~+1.5% 구간
## MEDIUM (M1-M7)
- M1: 스캐너 최소 거래량 100만→10만주
- M2: ADX 히스테리시스 18/22 (국면 플리핑 방지)
- M3: 분할매도 최소 수익 1.0%→0.5%
- M4: ORB 갭 필터 4% + 레인지 폭 0.3% 최소
- M5: 쿨다운 스트릭 부분매도 시 미변경
- M6: MDD 강제매도 loss_tracker 기록 제거 (허위 ban 방지)
- M7: RSI Wilder 스무딩으로 통일
## 인프라/보안
- 인증 누락 엔드포인트 수정 (analysis, journals)
- nginx 보안 헤더 location 블록 누락 수정
- Alembic 마이그레이션 IF NOT EXISTS 가드 추가
- SellRequest/UsOrderRequest 입력 검증 강화
- 차트 네이버 폴백 추가 (DB 데이터 없을 때)
- 서버 이전 시 자동 DB 마이그레이션 + KRX 초기 수집
- CLAUDE.md 섹션 5.1 백테스트 값 동기화 (4%→6%, -6%→-7%)
- MAX_SWING_POSITIONS 25→20 (CLAUDE.md 준수)
- mdd_manager failed_count에서 skip 종목 제외
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## CRITICAL 수정 (20건)
- day_trading: global 선언 누락, loss_tracker 연동, ban 체크 추가
- trade_executor: BUY 체결가 order_price로 수정, remaining_pct 누적 계산
- risk_validator: get_current_price dict 파싱, MAX_POSITION_SIZE 동기화, DB 세션 누수
- risk_management/recommendations: date.today() → KST 변환
- mdd_manager: Lock 밖 executed_key 참조 수정
- correlation_filter: output → output2 키 수정
- portfolio: 해외 종목 USD/KRW 환율 적용 분리
- Sharpe Ratio 거래빈도 기반 연간화
- telegram_notifier: send_message() 공개 래퍼 추가
- position_manager: 앱 재시작 시 DB 포지션 복원
- swing exit_service: remaining_pct 조건 범위 수정
- run_backtest: original_qty 기반 remaining_pct 계산
- us_market_schedule: 2027년 미국 공휴일 추가
- Login.tsx: res.ok 검증 추가
- mean_reversion_strategy: RSI 로그 하드코딩 수정
## HIGH 수정 (10건)
- db_worker: DLQ 파일 백업 메커니즘 추가
- korea_investment_api: 만료 토큰 임의 연장 제거
- market_data: chart_cache 최대 100개 + TTL 만료
- main.py: rate_limit_store 1시간 미접근 IP 정리
- recommendations: fire-and-forget try/except 추가
- swing/scheduler: DB 세션 3개 분리
- Dashboard: wsMessages 전체 순회
- Layout: /health 엔드포인트 + 30초 폴링
- ml_ensemble: POST /train require_api_key 추가
- day_trading: record_trade_result_safe() 전환
## 코드 정리
- 프론트엔드: isUsStock, formatTime 공통 유틸 추출
- 백엔드: dead code 제거, 중복 import 통합
- MCP: JSON 파싱 헬퍼 추출 (~60줄 감소)
- 전체 ~100개 파일 한국어 주석 추가
- 테스트 13건 코드 기준 수정 (468 passed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- types/trading.ts: 중앙 타입 정의 (CandleData, Position, Trade 등)
- useMarketData.ts: 실시간 시세 처리 + 500ms 쓰로틀링
- usePortfolioData.ts: React Query 기반 포트폴리오 데이터 훅
- useTradeActions.ts: 매매 실행 액션 훅
- useWebSocket.ts: pong timeout 10초 감지 (좀비 연결 방지)
- TradingChart.tsx: @ts-nocheck 제거, CandleData 타입 적용
- PortfolioPanel/RecommendationPanel: any → 구체적 타입 교체
- Dashboard.tsx: 상태 관리 로직을 커스텀 훅으로 이전
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- trade_analyzer.py: 거래 성과 분석(승률/손익비/전략별 패턴), 템플릿 기반 일지 자동 생성
- strategy_optimizer.py: 그리드 서치 기반 파라미터 최적화, Sharpe 10% 개선 시 자동 적용
- analysis.py: /performance /insights /generate-journals /optimize-strategy /optimization-history 엔드포인트
- journals.py: POST /generate/{trade_id}, GET /stats 엔드포인트 추가
- models.py: StrategyOptimizationLog 테이블 추가
- main.py: post_market_analyzer_scheduler (16:00 KST 자동 실행)
- frontend: Analysis 페이지 추가 (성과 요약/인사이트/일지 생성/최적화 이력)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>