Files
trex-core/docs/batches/bat-038_20260612_sell-transaction-tax-fee/planning.md
T
genichinandClaude Opus 4.8 1cf13b060f feat(broker): BAT-038 — 매도 증권거래세 누락 정정 + fee/tax 단일 정책 지점 (dcy-026/REQ-018, issue #24)
dcy-026 confirm-discovery + REQ-018 change-req(CHG-20260612-01)→구현→
confirm-req-implemented(CHG-20260612-02) 전체 delivery.

- broker_port.py: calculate_tax(side, amount) 신규 + fee/tax 율 env 상수화
  (TREX_KIS_FEE_BPS=1.5, TREX_KRX_TAX_SELL_BPS=20.0). 매도 0.2%/매수 0.
- paper.py / kis.py: tax=0.0 하드코딩 3곳 제거 → 정책 함수 호출.
  KIS daily-ccld 응답에 fee/tax 필드 부재 → 정책 폴백(향후 정본 우선 훅).
- runtime-flows.md: 체결→ledger fee/tax 산출 흐름 갱신.
- tests: fee/tax 정책 단위 + issue #24 4건 회귀(fee+tax=1,376.9원).
  429 passed (+6), ruff clean.

REQ-018 Approved→Implemented, BAT-038 release-candidate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 17:57:15 +09:00

3.0 KiB

BAT-038 Planning

  • Status: confirmed
  • Batch: BAT-038
  • Profile: standard

Included REQ

  • REQ-018 (CHG-20260612-01): 매도 증권거래세 정책 계산, tax=0.0 하드코딩 제거, 단일 정책 지점 + env 설정, KIS 응답 정본 우선. AC-3 갱신 + AC-6~9 신규.

Delivery Plan

  1. broker_port.py — 세율 env 상수(TREX_KRX_TAX_SELL_BPS=20.0) + 수수료율 env 상수(TREX_KIS_FEE_BPS=1.5, 기존 하드코딩 _FEE_BPS_* 대체) 도입. calculate_tax(side, amount) 신규(매도 정책 세율, 매수 0). FillStatus.tax 주석 갱신.
  2. paper.py:90 — tax=0.0 → calculate_tax(side, amount) 호출.
  3. kis.py:213·230 — 브로커 체결 응답 fee/tax 필드 파싱(있으면 정본), 없으면 calculate_fee/calculate_tax 폴백 + 로그.
  4. 테스트 — 매수/매도 fee·tax 단위(매도 0.2%, 매수 tax=0), issue #24 4건 회귀(1,376.9원), paper·KIS 동일 정책 일치, KIS 응답 우선·폴백 경로.
  5. docs/runtime-flows.md — 체결→ledger fee/tax 산출 흐름 갱신.

Dependencies

  • Internal:
    • trex_core/application/broker_port.py — calculate_fee 기존 함수, env 로딩 패턴(TREX_* os.environ) 기존 사례 준용
    • trex_core/adapters/broker/{paper,kis}.py — FillStatus 생성 지점(이미 fee 계산 호출 중)
    • trex_core/application/execution.py·ledger_outbox.py — fee/tax 전달 경로(계약 불변 예상, 검증 필요)
  • External:
    • KIS 체결 응답 raw 필드(수수료/세금 포함 여부) — delivery 단계 raw 확인(CONFIRM, dcy-026)

Design Gate

  • Design Required Before Implementation: yes
  • Reason: (1) FillStatus.tax 계약 의미 변경(0 고정 → 매도 정책 계산), (2) KIS 응답 fee/tax 파싱 경로 — 필드 존재 여부·단위 결정이 라이브 정확성에 직결(R-2), (3) env 상수 도입과 기존 _FEE_BPS_* 하드코딩 정리 방식, (4) calculate_tax 신규 vs calculate_fee 통합 결정. design 에서 확정 후 구현.

Milestones

  1. Design confirmed — calculate_tax 시그니처, env 로딩, KIS 파싱·폴백 경로 확정
  2. Implementation — broker_port + paper + kis 수정 + 테스트
  3. Verification — AC-3·6~9 매핑 + issue #24 회귀(1,376.9원) + 전체 회귀 + ruff

Risks

  • R-1 (High): 세율 산식 오류 시 손익 역방향 왜곡 — 완화: §4 공식 기대 1,376.9원 회귀 테스트 고정, 매수/매도 각 케이스 단위.
  • R-2 (Medium): KIS 응답 수수료/세금 필드명·단위(원 vs bp) 오파싱 → 라이브 전용 오류(paper 미검출) — 완화: raw 필드 확인 후 파싱, 미확인 시 정책 폴백 + 로그. design 에서 KIS 응답 스키마 확인.
  • R-3 (Low → 해소): execution.py/ledger_outbox.py fee/tax 전달 경로 계약 변경 가능성 — 점검 완료: 불변 확인. execution.py:_record_ledger (line 396-397)가 이미 fee=float(fs.fee), tax=float(fs.tax) 를 ledger 로 전달 중. 어댑터 소스(fs.tax)만 정확히 채우면 되며 전달 경로 코드 변경 불필요.