Commit Graph

4 Commits

Author SHA1 Message Date
9fab4018d4 fix: 프로그램 검증 루프 7회차 — 리스크·주문·청산·인프라 결함 일괄 수정 + 거래 확대 결정 반영
하네스 규칙 검사 전역 위반 117→0, 회차별 검증(code-verifier opus 4도메인)으로 Critical/High 해소.

주문·리스크
- MDD 강제축소 반복 매도(종목별 완료 집합·재시도 상한·날짜 롤오버·잔고 오류 보류·epoch·장외 미주문)
- KIS 거부 FAILED 기록, 결과 불명(전송 후) 재전송 금지·PENDING, 미전송 실패만 재시도(msg_cd 분류)
- 국내 전량·손실 매도 시장가, 부분 익절 직전 현재가, 지정가만 미체결 취소(cancel_order_v2: TR 0013U·조직번호) + 0체결 롤백
- 누적 4%·현금·레버리지(신규분 포함)·사이클 내 매수 누적, 수동매수 공용 가드(buy_guards), 수동매도 DT 차감·락
- 가드 우회 엔드포인트 차단(/recommendations/auto-trade 위임, US /execute 매수 410·매도 가드)
- 매수 슬롯=성공 매수, 평가 상한·회전, 업무거부/계좌 쿨다운, 프로세스 내 in-flight 주문 중복 차단
데이트레이딩
- 진입·청산 shield, 청산 진행 중 표식(소유 토큰), 2단계 청산 체크, 결과 불명 → 보유 감소 판정·비DT 차감 상한
- 전일 포지션 재시도(일시 실패 미산정), 분할매도 영속, ORB 구간 손절, /cycle 락, 사이클 내 현금 차감, 체결 수량 보정
스윙
- 손절 공백(판정 예외 시 하드 바닥), 단일 손절 소스·범위 검증, 매도 직전 KIS 잔고 상한(min(주문가능,보유)−DT)
- 결과 불명 체결 대조·장부 반영, 대체가(나이·진입 이후·ATR 캐시), 분할 단계 기록, 국면 실패 fail-closed
- 듀얼 플레이북·서킷브레이커 게이트, 평균회귀 우선·듀얼 독립, 시간손절 거래일
- 거래 확대(사용자 결정, 백테스트 미검증): RSI 46/35 정본 경로, 모멘텀 v2 ON, SIDEWAYS ADX AND, 트레일링 1차 익절 후, 20일 시간손절 ON
인프라·보안
- 계좌·손익 GET 인증, 세션 is_active·관리자 경로, 서명키 파생, realip, WS 토큰 마스킹
- KIS 토큰 즉시 실패(sleep 제거)·무효 시 캐시 삭제, 주문 5xx+JSON 본문 반환
- db_worker 종료 drain(멱등 재실행·커밋 불명 격리·예산·밴 커밋), stop_grace 40s, Redis 타임아웃·volatile-lru, /health DLQ·캐시
- KRX 휴장일, py3.11 비호환 f-string 수정 + Jenkins 이미지 내 compileall·헬스 실패 시 빌드 실패
하네스: rules_check 에 PEP 701 f-string 검사, 마커(allow-*), deploy 스모크 401 기준
CLAUDE.md: 실제 동작·플래그·백로그(§8.5-27~38) 갱신

backend 1451 passed / hooks 112 passed / tsc ok / py3.9 compile 0 errors

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 12:01:31 +09:00
45677c8fbb fix: 리스크 결함 일괄 수정 — 누적 4% 상한·스윙 소유권·일일한도 분리·DT 순손익/체결가·시간손절 밴 제외·체결조회 경로
trade_executor
- 종목당 4% 상한을 기존 보유분 포함 누적으로 (sizing_core.remaining_position_room)
- 추천 경로는 스윙 소유 행만 매수·매도 (external/manual/daytrading/us_swing skip, 대칭), 고아 DT 행 warning
- 일일 매수한도는 스윙 소유 매수만 집계, 집계 실패 시 fail-closed
- 부분매도 반복 차단에서만 DT 매도 제외 (재매수 쿨다운은 유지)
- 체결 확인: 부분체결 잔량 자동 재주문 제거(가드 전부 우회·취소/거부 시 발동), PARTIAL→COMPLETED+체결수량, 초과체결 캡

korea_investment_api
- get_order_execution 이 존재하지 않는 /trading/inquire-ccnl 을 호출하던 결함 → inquire-daily-ccld
  (TTTC0081R 우선, 구 TR 폴백, 페이지네이션, ODNO 매칭, EXCG_ID_DVSN_CD=KRX), 실패 로그 warning

daytrading
- 시간손절은 loss_tracker 중립 (42일 밴이 스윙까지 막던 문제)
- 실현손익을 수수료·거래세 차감 순손익으로 (trade_cost_core), 체결가 백그라운드 보정 (fill_reconciler)
- legacy _record_trade strategy_type=daytrading 명시

db_worker
- update_trade_history_by_order_id 를 당일(KST)+최신 1행으로 한정 (일별 재사용 ODNO 로 과거 행 덮어쓰기 방지)

alembic 0013: trade_journals strategy_name='unknown' 을 trade_history.strategy_type 으로 보정 (백업 테이블 포함)
CLAUDE.md: 변경 동작 반영, MT 예약 리비전 0013→0014

998 passed

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 17:37:29 +09:00
7abbb3411c fix: 재기동 내구성 + DT 진입 복구 + 유입 잔고 격리 + 대시보드 표시 오류
## 재기동 내구성
- 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>
2026-09-29 15:49:25 +09:00
1b9257c4d2 fix: 매매 파라미터 3중 소스 정합 + 리스크 가드 복원 + 죽은 코드 2,695줄 제거
## 배경
"전략이 혼란스럽고 현재와 맞지 않는다"를 조사한 결과, 전략 설계가 아니라
전략을 검증했다는 도구와 파라미터 소스가 어긋나 있었다.

## 파라미터 소스 단일화
- 우선순위가 adaptive > strategy_cfg(DB) > config.py 인데 문서는 맨 마지막인
  config.py 를 기술하고 있었다. 11곳이 불일치(BULL RSI 46 vs DB 30, SL -7% vs -6%).
- DEFAULT_PARAMS 를 config.py 에 정합 + alembic 0012 로 기존 DB 행 갱신
  (운영자가 UI 로 바꾼 값은 보존, 옛 기본값과 같은 행만 갱신, 테이블 가드·멱등)

## 백테스트를 실전 로직에 정합
- calculate_adx_simple 이 정확히 period 배(14.0×) 발산 → Aggressive 게이트
  `ADX>25` 가 전 레짐 100% 통과. 전환 빈도 5.6%→2.0%(-65%), 성과 상방 편향
- 백테스트 RSI 는 SMA, 실전은 Wilder → 진입 판정 10~11% 불일치
- us_backtest_engine RSI 1봉 지연 제거 (룩어헤드 없음을 절단 테스트로 증명)
- backend/backtest_results/ 25건은 폐기 대상 (§8.4)

## 리스크 가드 복원
- 4% 절대 상한이 try 블록 안에 있어 예외 시 적응형 6~7% 가 통과 → try 밖으로
- 청산을 매수보다 먼저 평가 (보유 종목이 추천에 들면 손절 대신 물타기가 나갔다)
- 리스크 가드 4개를 매수 전용화 → MDD -10%·보유한도 도달 시에도 손절 작동
- MDD 갱신 5회 연속 실패 시 신규 진입 차단 fail-safe (청산은 계속 허용)
- 스윙 청산이 DT 보유분까지 매도하던 문제, sell_pct 기준 혼재 정정

## 죽은 코드 제거 (2,695줄)
- short_term_strategy, kosdaq_scanner, app/strategy/ 패키지
- app/trading/ + korea_investment_api_adapter (real_market_api 정본은
  korea_investment_api.py:1482, adapter 는 import 0건)

## 지표·사이징 단일화 (수치 무변경 증명)
- indicators_core.py: 3,274건 비교 최대 오차 0.000e+00
- sizing_core.py: 42,105건 비교 불일치 0
- 미국 전략 상수 13개 config 편입 (hex 까지 동일, 3,168 케이스 전수 비교)

## 테스트 안전 (실 KIS 호출 차단)
- 유닛 테스트가 실제 KIS 에 매도 주문을 2회 전송하고 있었다. 리팩터링이
  close_stale_positions 의 대상을 _execute_exit → _execute_exit_stale 로
  바꿨는데 목이 전자에 걸려 빗나갔다. test_api_endpoints 도 캡처된 싱글톤
  참조 누수로 실제 잔고 조회를 타 141초를 소비했다.
- backend/tests/conftest.py 신설: 주문·토큰·시세·잔고를 호출 즉시 예외로 차단.
  예외는 BaseException 파생(프로덕션 except Exception 폴백에 삼켜지지 않게),
  클래스 메서드에 적용(캡처된 참조까지 덮음), DATABASE_URL `_test` 가드 강제
- 전체 유닛 스위트: 365초/6 failed → 11.8초/0 failed (소켓 차단 하 559 passed)

## 신규 (둘 다 플래그 OFF, 백테스트 미검증)
- range_trading_strategy.py — SIDEWAYS 담당 전략이 없던 빈 칸. 미배선
- check_bear_buy_signal_v2 — BEAR 4중 AND(발화율 2.3%) → 점수제(12.4%)

## 문서
- CLAUDE.md 를 실제 코드 기준으로 재작성. §0 파라미터 우선순위, §4.1 테스트 규약,
  §6.4 문서화되지 않았던 진입 차단 게이트 9종, §8.4 백테스트 폐기 근거,
  §8.5 미해결 19항목
- 루트 md 6개 → 2개(docs/ 이동), 중복 배치 문서 병합, 스테일 worktree 제거

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-28 08:58:18 +09:00