Skip to content

feat: 적립 입금 + 시간가중수익률(TWR) — 소액 적립 트랙 선행 구현 - #437

Merged
easygap merged 1 commit into
mainfrom
feat/deposit-twr
Jul 6, 2026
Merged

feat: 적립 입금 + 시간가중수익률(TWR) — 소액 적립 트랙 선행 구현#437
easygap merged 1 commit into
mainfrom
feat/deposit-twr

Conversation

@easygap

@easygap easygap commented Jul 6, 2026

Copy link
Copy Markdown
Owner

무엇

소액 적립 트랙(docs/POCKET_TRACK_PLAN.md §4)의 선행 구현 — 외부 입금 지원 + 시간가중수익률(TWR). 월 10만원 적립이 운영의 중심인데, 현 수익률 산식(총평가/초기자본)은 입금을 수익으로 오표기합니다(30만에 10만 입금 = +33%).

핵심 계약

  1. 입금은 수익이 아니다 — 입금 직후 수익률·실현손익 점프 0.
  2. MDD는 TWR 지수 기준 — 입금이 낙폭을 가짜 회복시키지 않는다.
  3. 흐름 0건 계정은 기존 산식 그대로 — 기존 트랙 결과 불변(회귀 테스트 고정, 전체 스위트 무회귀).

구현

  • database: cash_flows 테이블(+입금/-출금, 발생 시각) + record/조회/구간합/최신 스냅샷 요약 repo 함수.
  • core/portfolio_manager.py: 순수 twr_period_return + summary의 TWR 분기(직전 스냅샷 누적수익률에 구간 수익률 연결, 유입 경계는 측정 시각 created_at), 현금엔 입금 포함·손익에선 제외, deposits_total/principal 노출.
  • main.py: 일간 수익률 입금 중화 + 카드에 💳 누적 원금(입금 계정만), 주간 리포트 주간 변화도 입금 중화.
  • core/basket_evaluation.py: 입금 계정의 NAV는 스냅샷 TWR 누적치, 비용 드래그 분모는 시간가중 평균 자본(Modified Dietz).
  • tools/record_deposit.py: 입금 기록 CLI(양수만, 마지막 스냅샷 이전 소급 거부 — TWR 체인 보호).
  • tools/restart_basket_track_record.py: 아카이브 이전 목록에 CashFlow 추가(재시작 후 옛 입금 잔류 방지).

적대적 리뷰 반영 (6건 확정 → 전부 수정)

  • [HIGH] 스냅샷 upsert가 created_at 미갱신 → 당일 재실행(재시도 크론!)+입금 조합에서 다음 날 유입이 이중 산입돼 수익률 영구 왜곡 → upsert 시 측정 시각 갱신 + 회귀 테스트.
  • [med] 일간 수익률 유입 경계가 자정(date) → 측정 시각(created_at)으로.
  • [med] 주간 변화가 원화 기준이라 입금 주에 가짜 +10% → TWR 중화.
  • [med] 비용 분모에 전액 입금 합산 → 말기 입금이 승격 게이트를 느슨하게 → Modified Dietz.
  • [low] 순합 0(+100/-100) 에지에서 분기 오판 → '흐름 존재 여부'로 분기 통일.
  • [low] 재시작 도구가 CashFlow 미이전 → 이전 목록에 추가 + 적용 테스트.

검증

  • tests/test_cash_flows.py 23케이스(계약 3종 + 리뷰 회귀 6종 + CLI/재시작 이전).
  • 격리 임시 DB(QUANT_DB_PATH)에서 실CLI 스모크: 입금 → 수익률 0/실현손익 0/원금 분리 표기, 스냅샷 체인 후에도 유지.
  • 전체 스위트 통과.

월 10만원 적립이 운영의 중심(docs/POCKET_TRACK_PLAN.md)인데, 기존 수익률
산식(총평가/초기자본)은 입금을 수익으로 오표기한다(30만에 10만 입금=+33%).

핵심 계약:
1) 입금은 수익이 아니다 — 입금 직후 수익률·실현손익 점프 0
2) MDD는 TWR 지수 기준 — 입금이 낙폭을 가짜 회복시키지 않는다
3) 흐름 0건 계정은 기존 산식 그대로 — 기존 트랙 결과 불변(회귀 고정)

구현:
- database: cash_flows 테이블 + record/조회/구간합/최신 스냅샷 요약
- portfolio_manager: twr_period_return(순수) + summary TWR 분기(직전 스냅샷
  누적수익률에 구간 수익률 연결, 유입 경계는 측정 시각 created_at),
  현금엔 입금 포함·손익 제외, deposits_total/principal 노출
- main: 일간 수익률 입금 중화 + 카드 누적 원금, 주간 변화도 입금 중화
- basket_evaluation: 입금 계정 NAV는 스냅샷 TWR, 비용 분모는 시간가중
  평균 자본(Modified Dietz — 말기 입금이 게이트를 느슨하게 못 하게)
- tools/record_deposit.py: 입금 CLI(양수만, 마지막 스냅샷 이전 소급 거부)
- restart_basket_track_record: CashFlow도 아카이브 이전(재시작 후 잔류 방지)

적대적 리뷰 6건 반영 — 특히 HIGH: 스냅샷 upsert가 created_at(측정 시각)을
갱신하지 않아 당일 재실행(재시도 크론)+입금 조합에서 다음 날 유입이 이중
산입돼 수익률이 영구 왜곡되던 문제 → upsert 시 갱신 + 회귀 테스트.

격리 임시 DB 실CLI 스모크 확인. 전체 스위트 1627 통과.
@easygap
easygap merged commit 9e168b3 into main Jul 6, 2026
1 check passed
@easygap
easygap deleted the feat/deposit-twr branch July 6, 2026 03:18
easygap added a commit that referenced this pull request Jul 6, 2026
feat: 적립 입금 + 시간가중수익률(TWR) — 소액 적립 트랙 선행 구현
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