fix: positions 구버전 UNIQUE(symbol) 재구축 — 유령 -41% 낙폭의 뿌리#452
Merged
Conversation
…1% 낙폭의 뿌리 트랙 재시작 직후 첫 매수에서 매매 기록은 남고 포지션만 사라졌다. 스냅샷이 현금만 집계돼 -41% 낙폭으로 찍혔고, 이 유령 MDD가 리스크 가드를 발동시켜 이후 사이클의 매수를 전부 차단했다. 원인은 스냅샷 UNIQUE(date) 때와 같은 계열: account_key 도입 전 시절의 UNIQUE(symbol) 단독 제약이 물리 테이블에 잔존(모델은 이미 복합 제약 — create_all은 기존 테이블을 못 바꾼다). 아카이브 키에 069500이 남은 상태에서 본 키가 재매수하자 IntegrityError로 포지션 저장이 실패했다. 재시작만이 아니라 바스켓과 전략 트랙이 같은 종목을 겹쳐 드는 순간 언제든 터질 지뢰. - 표준 재구축(rename -> 생성 -> INSERT OR IGNORE 복사 -> 행수 검증 -> 삭제), 멱등·중단 재개 가능, 행수 감소 시 RuntimeError로 legacy 보존 - init_database에서 조용히 삼키지 않음. partial_tp_done 컬럼 마이그레이션 뒤에 실행해 복사 컬럼 보장 - 테스트 7종: 행 보존, 재구축 후 두 계좌 동일 종목 공존, 같은 계좌 중복 차단 유지, no-op 멱등, 중단 재개, 실측 사고 시나리오 재연 운영 DB에는 이미 적용됨(다음날 첫 사이클의 init이 자동 수행, 10행 보존 로그 확인). 잔해(고아 매매·깨진 스냅샷) 정리는 별도 운영 조치로 진행.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
배경 — 유령 -41% 낙폭의 뿌리
7/7 소액 트랙 v2 전환(트랙레코드 재시작) 직후 첫 매수에서: 매매 기록은 남았는데 포지션만 사라지고, 스냅샷이 현금만 집계돼 -41.28% 낙폭으로 찍혔다. 이 유령 MDD가 리스크 가드(신규 매수 차단)를 발동시켜 7/8~7/10 사이클이 3일 연속 아무것도 못 샀다.
원인은 #439(스냅샷 UNIQUE(date))와 같은 계열의 레거시 스키마다: account_key 도입 전 시절의
UNIQUE (symbol)단독 제약이 물리 테이블에 잔존 — 모델은 이미(account_key, symbol)복합 제약인데 create_all은 기존 테이블을 바꾸지 못한다. 재시작으로 아카이브 키(...@archived-20260707)에 069500이 남은 상태에서 본 키가 069500을 재매수하자 IntegrityError로 포지션 저장이 실패했다(에러는 로그에만 남고 사이클은 계속 진행).트랙 재시작만의 문제가 아니다 — 서로 다른 계좌(바스켓·전략 트랙·아카이브)가 같은 종목을 드는 순간 언제든 터질 지뢰였다. 분산 바스켓(005930 보유)과 전략 트랙이 삼성전자를 겹쳐 사는 평범한 시나리오도 동일하게 유실된다.
수정
_migrate_position_unique_constraint— 스냅샷 재구축과 동일 절차(rename → 신 스키마 생성 → INSERT OR IGNORE 복사 → 행수 검증 → 구 테이블 삭제). 멱등, 중단 시 재개 가능, 행수 감소 시 RuntimeError로 legacy 보존검증
positions 재구축 완료: 10행, 복합 유니크(account_key, symbol)로그 확인, legacy 테이블 제거·행수 보존 검증 완료후속 운영 조치 (이 PR 머지 후)
스키마는 고쳤지만 7/7 사고의 잔해(고아 매매 1건 + 깨진 스냅샷 4개, 유령 MDD)는 데이터에 남아 있다 — DB 백업 후 해당 잔해를 제거하고 v2 첫 사이클을 재실행해 트랙레코드를 깨끗한 0/60에서 시작한다.