Skip to content

feat: live 전환 타임라인 레버 — 모의서버 리허설 병행 + 승격 기간 운영자 설정 - #411

Merged
easygap merged 7 commits into
mainfrom
feat/live-timeline-levers
Jun 10, 2026
Merged

feat: live 전환 타임라인 레버 — 모의서버 리허설 병행 + 승격 기간 운영자 설정#411
easygap merged 7 commits into
mainfrom
feat/live-timeline-levers

Conversation

@easygap

@easygap easygap commented Jun 10, 2026

Copy link
Copy Markdown
Owner

#410에 스택#410 머지 후 diff가 깨끗해집니다.

배경 — 60일 구간을 안전하게 압축하는 운영자 레버

실자금 보호는 그대로 두고, 대기 시간의 낭비만 제거한다.

1) KIS 모의서버 리허설을 평가와 병행 허용
런북 Phase 1(use_mock: true 모의서버로 live 코드 경로 전체 리허설)은 실돈 리스크 0인데, 게이트가 모의서버/실계좌를 구분하지 않아 리허설까지 60일을 기다리게 막는 모순이 있었다. 게이트의 목적은 실자금 보호 — 모의서버에서는 평가 미통과를 경고로만 처리한다.

  • 실계좌(use_mock: false): 평가 통과 전 차단 불변 (테스트 고정)
  • 설정 결함(비중합·미존재·비활성): 모의서버에서도 여전히 차단 (완화는 평가 기간에만)
  • 효과: 사장님이 오늘부터 모의서버에서 live 경로(KIS 인증·주문·체결조회·sync)를 리허설하며 증거 축적과 병행 가능

2) 승격 기간을 바스켓 설정으로 노출 (promotion: { min_trading_days: N }, 기본 60 유지)
베타 바스켓의 전략 통계는 4.5년 과거 실현 기록이 담당 — paper 기간이 증명하는 것은 운영 신뢰성이다. 단축이 합리적일 수 있으나 반드시 기준 문서를 읽고 내리는 운영자의 명시적 결정이어야 한다(자동 단축 없음, 코드 기본 60).

검증

테스트 4건(모의서버 WAIT 통과 / 실계좌 차단 불변 / 설정 결함 비완화 / 기간 설정 전달) — 전체 1488 passed

easygap added 7 commits June 10, 2026 14:15
오늘 작성한 코드 전체를 독립 에이전트로 적대적 재검토시켜 발견된 결함 5건을
트랙레코드 1일차인 지금(마이그레이션 비용 최소) 일괄 해소한다.

1) [HIGH] live gate가 "어느 바스켓의" 기록인지 검증하지 않던 구멍.
   거래가 이름 없는 strategy('basket_rebalance')로 기록돼 귀속이 불가능했고,
   수집기는 합산 평가라 A 바스켓의 60일 기록으로 신규 B 바스켓이 승격될 수
   있었다. 계정·귀속 키를 paper/live 공통 basket_rebalance:<name>으로 통일
   (BasketRebalancer 기본값 + 호출부 명시 전달), 수집기는 바스켓별 필터
   (basket_name 미지정 시 enabled 1개만 허용 — 모호하면 ValueError fail-closed),
   게이트는 자기 바스켓 이름을 명시 전달(회귀 테스트로 고정).

2) [HIGH] account_key=''가 격리 계정이 아니라 전 계정 합산 뷰였던 문제.
   --strategy 없는 paper 실행 한 번이면 scoring 거래가 섞여 NAV·드리프트·평가가
   오염됐다. 바스켓 전용 키 계정으로 NAV 스냅샷·평가·health 감시를 전부 이전.
   기존 기록(거래 9·포지션 9·스냅샷 1)은 tools/migrate_basket_paper_account.py로
   이전 완료(단일 바스켓 상황 전용 도구, dry-run 기본).

3) [MED] 스케줄러 단독 운영 시 바스켓 NAV 스냅샷이 0건이던 문제.
   장마감 스냅샷은 전략 계정만 저장했다 — 사이클마다 바스켓 계정 스냅샷을
   저장한다(save_daily_nav_snapshot, 거래 여부 무관, 멱등 upsert). 승격 후
   live 바스켓 NAV 기록도 같은 경로로 해결.

4) [MED] 가격 조회 실패일에 avg_price 폴백 NAV가 '커버된 영업일'로 둔갑하던
   문제. save_daily_nav_snapshot이 보유 종목 가격 완전성을 확인하고, 미확보 시
   스킵+경고(다음 날 health 끊김 감지로 노출 — 가짜 NAV보다 정직).

5) [LOW] 평가 분모에 스냅샷 저장 전의 '오늘'이 포함돼 경계(95%)에서 오판되던
   문제(오늘은 스냅샷 존재 시만 포함) + dead-letter 집계가 전 전략 무차별이던
   것을 바스켓 계정으로 한정(타 전략 잔여 실패가 바스켓 승격을 막는 오판 방지).

부수: 계좌 격리 가드는 paper에서 키 격리로 자연 통과(live 실계좌 공유만 차단),
평가 CLI --basket 옵션 + enabled 복수 각각 평가.

검증: 실 CLI 종단(리밸런싱→새 키 스냅샷·백업→평가 WAIT 1/60 커버리지 100%→
health 새 키 감시) 정상. 테스트 갱신·추가 다수, 전체 1480 passed.
운영상 가장 가능성 높은 실수 시나리오를 보호한다: 거래일에 PC가 꺼져 있다가
주말에 앱을 열면 스케줄 작업이 보충 실행되는데, 기존엔 스냅샷이 주말 날짜로
저장돼 커버리지(영업일 기준)에 영원히 안 잡혔다 — 운영자가 다음날 바로
보충했는데도 커버리지가 깎이는 낭비.

보충 실행에서 조회되는 가격은 직전 거래일 종가이므로, NAV의 정직한 귀속일은
그 거래일이다. save_daily_nav_snapshot이 '오늘이 거래일이면 오늘, 아니면
직전 거래일(KST)'로 귀속한다(_nav_attribution_date, 판정 실패 시 오늘 폴백).

- repositories.save_portfolio_snapshot: snapshot_date 옵션(자정 정규화, upsert 동일)
- PortfolioManager.save_daily_snapshot: snapshot_date 전달

수집기 귀속 테스트 추가: 바스켓별 필터(타 바스켓 비용 미혼입), 이름 미지정
모호 시 ValueError fail-closed, snapshot_date 귀속·upsert. 전체 1483 passed.
60일 대기 구간을 운영자가 합리적으로 압축할 수 있는 두 레버를 연다.
둘 다 실자금 보호는 그대로 유지한다.

1) KIS 모의투자 서버 리허설을 평가 기간과 병행 허용.
   런북 Phase 1(use_mock=true 모의서버로 live 코드 경로 전체 리허설)은 실돈
   리스크가 0인데, 게이트가 모의서버와 실계좌를 구분하지 않아 리허설까지
   60일을 기다리게 막고 있었다 — 게이트의 목적은 실자금 보호이므로 모순.
   use_mock=true면 평가 미통과를 경고로만 처리해 리허설을 허용한다.
   실계좌(use_mock=false)는 평가 통과 전 차단 그대로. 설정 결함(비중합·미존재·
   비활성)은 모의서버에서도 여전히 차단(완화는 '평가 기간'에만 적용).

2) 승격 기간을 바스켓 설정으로 노출(promotion.min_trading_days, 기본 60 유지).
   베타 바스켓의 전략 통계는 4.5년 과거 실현 기록이 담당하고 paper 기간이
   증명하는 것은 운영 신뢰성이다 — 단축이 합리적일 수 있으나, 반드시
   docs/BASKET_PAPER_EVALUATION.md를 읽고 내리는 운영자의 명시적 결정이어야
   한다(코드 기본값은 60 유지, 자동 단축 없음).

문서: 평가 기준 문서에 '운영자 레버' 절 추가, 런북 Phase 1에 '지금 바로 가능' 명시.
테스트 4건(모의서버 WAIT 통과/실계좌 차단 불변/설정 결함 비완화/기간 설정 전달).
전체 1488 passed.
promotion.min_trading_days를 게이트만 읽고 CLI는 기본 60을 쓰면, 운영자가
기간을 설정했을 때 CLI가 보여주는 판정과 게이트 판정이 달라진다 — #410에서
세운 "CLI 판정 = 게이트 판정" 원칙 위반.

기간 해석을 collect_basket_paper_evaluation으로 이동(min_days=None이면 바스켓
설정 promotion.min_trading_days, 기본 60). 게이트는 중복 조회 제거, CLI는
--min-days 미지정 시 같은 단일 소스를 따른다(명시 시 우선).

테스트: 수집기의 설정 해석·명시 우선 검증으로 교체. 전체 1488 passed.
@easygap
easygap merged commit 0892042 into main Jun 10, 2026
1 check passed
easygap added a commit that referenced this pull request Jun 10, 2026
fix: 모의서버 완화에 실효 도메인 검증 — #411 머지 레이스로 누락된 하드닝 회수
easygap added a commit that referenced this pull request Jul 6, 2026
feat: live 전환 타임라인 레버 — 모의서버 리허설 병행 + 승격 기간 운영자 설정
easygap added a commit that referenced this pull request Jul 6, 2026
fix: 모의서버 완화에 실효 도메인 검증 — #411 머지 레이스로 누락된 하드닝 회수
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant