Commit Graph

6 Commits

Author SHA1 Message Date
a264561576 fix: 하드닝 루프 8회차 — 체결 보정·고아 감지·청산 경보·실시간/차트·리스크 가드 일괄 수정
- 스윙 체결가 확인 전 executed_price NULL + fill_sweep, 진입가 resolve(ActiveTrade↔Portfolio), 0체결/부분체결 매수 장부 원복
- DT 고아 감지(근거 한정)·0체결 매도 복원·stale 점검 확대, 시간손절 -0.3% 원복
- 폴백 손절 ATR 캐시, 거래량부족-차단 신호 매수 차단, 현금 5% 유보 재적용, MDD peak/reset 수정
- KIS 서킷브레이커 청산 우회·경보, db_worker 재큐잉 순서, heartbeat·health-watch 사이드카
- 실시간 WS 재구독·41건 우선순위·다건 프레임 분할, 차트 샘플 제거·당일봉 합성, WS 서브프로토콜 인증
- 프론트: 미관리 그룹·확인 모달·차트 실시간 반영·예수금 표시 정정
- 전문가 에이전트 6종 추가(.claude/agents)
- 유닛 스위트 2667 passed (소켓 차단 하), tsc OK

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y83Za98XsNw9zuA4FTUytN
2026-10-10 12:17:49 +09:00
b5e0d6a9bb fix: 매매일지 표시·중복·스케줄러 중단 + 전략 파라미터 자동적용 차단
매매일지는 정상 생성되고 있었다(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>
2026-09-29 17:37:48 +09:00
b4a1fc79ab feat: 멀티테넌트 1단계 — 사용자별 KIS 계좌·포트폴리오·수동매매 (MULTI_TENANT_ENABLED 기본 OFF)
설계: docs/multi_tenant_design.md / 검수: docs/multi_tenant_phase1_review.md (High 0, MT=False 배포 가능)

데이터·인프라
- user_kis_credentials(Fernet 암호화, PBKDF2 키 파생, key_version), stock_bans_v2 신설,
  portfolio/trade_history/active_trades/trade_journals/trading_sessions 등 user_id nullable 추가
- alembic 0009~0011(idempotent, legacy owner 백필). main.py 기동 시 portfolio.user_id 스키마 검사(H1)
- Jenkinsfile: DB Migration 을 Deploy 앞으로, alembic 이력 없으면 stamp 0008 후 upgrade(N1)
- bootstrap: users 비어 있으면 BOOTSTRAP_ADMIN_* 로 관리자 시드 + .env KIS 자격증명 이관 + 백필(SAVEPOINT)

백엔드
- core/crypto.py, core/tenant_auth.py(get_current_user — 비활성 사용자 401, API 키→legacy owner,
  deny_non_owner_session_when_mt), core/dt_utils.py
- services/tenant: context, kis_pool, registry(UserContextRegistry, 락 최소화·복호화 to_thread), risk_factory
- KoreaInvestmentAPI.for_user(사용자별 인스턴스, 토큰캐시 users/{id}/, 시세는 공용 위임)
- trade_executor.safe_place_order_v2(사용자별 락/세마포어, legacy ctx 는 기존 키)
- mdd_manager/loss_tracker _v2 + ban_until tz-aware/naive 경계 정규화(레거시 경로 버그 포함 수정)
- db_worker: payload user_id 옵션 필터, upsert_stock_ban_v2, legacy ActiveTrade 조회 LIMIT 1
- API: /account/credentials(등록·마스킹조회·삭제·연결테스트·자동매매), /auth/admin/tenant/*,
  /portfolio/v2(조회·요약·sync·buy·sell), /trades/v2(+pending). PortfolioResponse Optional 수정

프론트
- /account 내 계좌 설정, useTenantMode(세션=v2 / API키=legacy, 미확정 시 쿼리·버튼 비활성),
  계좌 미등록 인라인 안내, v2 매수/매도/거래이력 분기

테스트: tests/integration(격리 Postgres, KIS 전면 mock) 20 passed / 1 xfailed(0012 이전 제약)
2단계(스케줄러 사용자화·legacy 라우터 격리) 전까지 MULTI_TENANT_ENABLED=True 전환 금지

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 10:26:51 +09:00
028a1c352b feat: 자동매매 신뢰성 개선 — 시세 실서버 라우팅·일일 한도 전역화·수동 매수 API
- korea_investment_api: KIS_QUOTES_VIA_REAL — 모의투자 모드에서 시세/차트/호가 조회를
  실계좌 시세 서버(20/s)로 위임, 주문·잔고는 모의서버 유지 (EGW00201 대응)
- recommendations: execute_auto_trade_background asyncio.Lock 중복 실행 방지 +
  MAX_DAILY_TRADES를 당일 BUY 건수 차감 전역 기준으로 적용 (11종목 동시 매수 재발 방지)
- manual_buy.py 신규: POST /api/v1/portfolio/buy (리스크 가드 + safe_place_order + db_worker)
- mcp-server: claude_code_client(claude -p 헤드리스 모드) 추가, trade_monitor 부분매도 시
  active 유지·remaining_pct 갱신, API 키 헤더·/api/v1 경로 수정, ODNO 주문ID 수정
- config: MCP_REQUEST_TIMEOUT, MCP_RISK_CACHE_TTL, BATCH_ANALYSIS_INTERVAL,
  SWING_INDEX_BREAKER_ENABLED(OFF), API_TRIGGERED_AUTO_TRADE(OFF) 추가
- docker-compose: 포트 충돌 해소 (postgres 15433, frontend 3001)
- frontend: 추천 패널 매수 버튼, 차트/호가/저널 패널 개선
- CLAUDE.md 압축 최적화 (규칙 변경 없음), _sweep_single_axis.py 백테스트 단일축 스윕

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-19 23:37:08 +09:00
de7921d270 fix: CRITICAL/HIGH 버그 30건 수정 + 전체 코드 주석 추가 + 중복 정리
## 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>
2026-03-26 16:05:41 +09:00
1c07a59352 대시보드 분리 2026-02-24 16:39:04 +09:00