Files
auto-trade/common-docs/improvement/plans/dev-plan-2026-03-06-autotrade-real-execution-budget-tax.md

127 lines
11 KiB
Markdown
Raw Permalink Normal View History

2026-03-12 09:26:27 +09:00
[계획 문서 경로]
- common-docs/improvement/plans/dev-plan-2026-03-06-autotrade-real-execution-budget-tax.md
[요구사항 요약]
- 내 예산 기준으로 실제 몇 주를 살 수 있는지 계산하고, 자동매매 설정창에서 정한 비율대로 매수 수량이 정해지게 만든다.
- 매도는 현재 보유/매도가능 수량과 비교해서 가능한 수량만 나가게 한다.
- 수수료/세금/실현손익까지 고려해 진짜 자동매매처럼 동작하게 만든다.
[가정]
- 자동매매 설정창의 `allocationPercent`는 "이번 종목/이번 주문에 실제로 쓸 비율"로 사용한다.
- `allocationAmount`는 절대 상한(최대 투자금)으로 사용한다.
- 수수료/세금은 계좌/환경/정책에 따라 달라질 수 있으므로, 구현 시 하드코딩보다 `설정값 + KIS 실제 체결/매매일지 값`을 함께 쓴다.
- 국내주식 단주가 아닌 1주 단위 주문 기준으로 계획한다.
[영향 범위]
- 수정: features/autotrade/hooks/useAutotradeEngine.ts
- 수정: lib/autotrade/risk.ts
- 수정: features/autotrade/types/autotrade.types.ts
- 수정: features/autotrade/components/AutotradeControlPanel.tsx
- 수정: app/api/autotrade/signals/generate/route.ts
- 수정: lib/autotrade/openai.ts
- 수정: lib/autotrade/cli-provider.ts
- 수정: package.json
- 추가: lib/autotrade/execution-cost.ts
- 추가: lib/autotrade/executable-order-quantity.ts
- 추가: tests/autotrade/risk-budget.test.ts
- 추가: tests/autotrade/order-guard-cost.test.ts
- 추가: common-docs/improvement/plans/dev-plan-2026-03-06-autotrade-real-execution-budget-tax.md
- 삭제: 없음
[현재 코드 기준 핵심 문제]
- `allocationPercent`가 실주문 계산 기준이 아니라 참고 경고 수준으로만 쓰이고 있다.
- 쉬운 말: 설정창에서 10%, 25%를 바꿔도 실제 자동매매 수량 계산에는 약하게만 반영된다.
- 매수 수량은 `effectiveAllocationAmount``maxOrderAmountRatio` 중심이라, 내 예산/비율/호가/예상 비용을 함께 계산하는 구조가 아니다.
- 매도는 `보유수량/매도가능수량` 차단은 있지만, 포지션 기준 목표 청산 비율, 부분 청산, 순손익 기준 청산 조건이 없다.
- 세금/수수료는 대시보드 조회/표시에는 일부 있지만, 자동매매의 진입/청산/손실 한도 계산에는 거의 반영되지 않는다.
- 일일 손실 한도는 입력 금액 기준이고, 실제 체결 후 순손익(수수료/세금 포함)과 연결되지 않는다.
[구현 단계]
- [x] 1. 주문 가능 예산 모델 재정의
- 입력: 가용 예수금, 매수가능금액, allocationPercent, allocationAmount, 전략별 maxOrderAmountRatio
- 처리: `실주문가능예산 = min(매수가능금액, allocationAmount 상한, 예수금 * allocationPercent)` 구조로 통일
- 결과: "현재 이 종목에 실제로 쓸 수 있는 예산" 1개 값으로 고정
- [x] 2. 매수 수량 계산 로직 교체
- 입력: 실주문가능예산, 현재가/주문가, 예상 수수료, 최소 안전여유금
- 처리: 비용 포함 기준으로 최대 주문 가능 수량 계산
- 결과: "내 예산 기준으로 지금 몇 주 살 수 있는지"를 로그와 UI에 함께 표시
- [x] 3. 매도 수량 계산 로직을 포지션 기준으로 확장
- 입력: 보유수량, 매도가능수량, 평균단가, 평가손익, AI 제안 수량/비율
- 처리: 없는 주식은 절대 매도 금지, 보유보다 큰 수량 금지, 부분 매도 허용
- 결과: "실제 보유 중인 수량 안에서만 매도" 보장
- [x] 4. 수수료/세금 추정 모듈 추가
- 입력: 주문금액, 매수/매도 구분, 계좌/환경 정책
- 처리: 주문 전 예상 비용 계산, 주문 후 실제 체결/매매일지로 정산값 보정
- 결과: 순손익 기준 판단 가능
- [x] 5. 자동매매 위험 관리 기준을 순손익 기준으로 보강
- 입력: 실현손익, 평가손익, 누적 수수료, 누적 세금
- 처리: 일일 손실선/청산 조건을 총손익이 아니라 순손익 기준으로 갱신
- 결과: 세금/수수료 때문에 실제 손실이 커지는 상황 반영
- [x] 6. AI 입력값도 포지션/비용 기준으로 보강
- 입력: holdingQuantity, sellableQuantity, averagePrice, estimatedFee, estimatedTax, netProfitEstimate
- 처리: AI가 매도 시 "팔 수 있는지/팔면 순손익이 어떤지"를 함께 보게 함
- 결과: 보유 없는 SELL, 손익 무시 SELL/BUY 감소
- [x] 7. UI/로그 보강
- 자동매매 설정창/로그에 아래 항목 노출
- 현재 주문 가능 예산
- 현재 매수 가능 수량
- 현재 보유 수량 / 매도 가능 수량
- 예상 수수료 / 예상 세금 / 예상 순손익
- [x] 8. 체결 후 실제값 동기화
- 주문 후 잔고/활동 API 재조회
- 체결 후 보유수량, sellableQuantity, realized fee/tax, realized profit을 스토어에 반영
- 다음 주문은 이 최신값을 기준으로 계산
[사용할 MCP/Skills]
- MCP: next-devtools, sequential-thinking, mcp:kis-code-assistant-mcp
- Skills: dev-plan-writer, dev-mcp-implementation, dev-refactor-polish, dev-test-gate, dev-plan-completion-checker, vercel-react-best-practices
[참조 문서(common-docs)]
- common-docs/api-reference/kis_api_reference.md
- common-docs/api-reference/kis-error-code-reference.md
- common-docs/features/trade-stock-sync.md
- common-docs/ui/GLOBAL_ALERT_SYSTEM.md
[주석/문서 반영 계획]
- 함수 주석: [목적]/[사용처]/[데이터 흐름] 유지
- 수량 계산/비용 계산 함수에는 입력 -> 처리 -> 결과 주석 추가
- 자동매매 로그에는 "왜 주문됐는지/왜 차단됐는지" 숫자 기준 노출
[리스크/회귀 포인트]
- 계좌별 수수료 정책이 다르면 세금/수수료 추정이 실제와 다를 수 있다.
- 매수가능금액/잔고/매매일지 API 응답 타이밍이 어긋나면 체결 직후 수량이 잠깐 다르게 보일 수 있다.
- 모의투자는 실전과 세금/수수료/매매일지 지원 방식이 다를 수 있다.
- 주문 전 추정 비용과 주문 후 실제 비용이 다를 수 있으므로, 최종 손익 기준은 실제 체결/매매일지 값으로 재정산해야 한다.
[검증 계획]
- [x] 1. `allocationPercent`, `allocationAmount`, `매수가능금액` 조합별로 매수 수량이 기대값대로 계산되는지 단위 테스트 추가
- [x] 2. 보유 없음 / 보유 1주 / 매도가능수량 부족 상황에서 SELL이 차단되는지 테스트
- [x] 3. 수수료/세금 추정 로직과 실제 activity API 정산값 연결 테스트
- [x] 4. `npm run lint`
- [x] 5. `npm run build`
- [x] 6. 자동매매 스모크 시나리오
- 예산 30만원, 비율 10%, 주가 16,000원일 때 매수 가능 수량 계산 확인
- 보유 5주, 매도가능 3주일 때 SELL 수량 제한 확인
- 체결 후 잔고/활동 재조회로 보유/손익이 갱신되는지 확인
- Playwright 인증 필요 구간에서는 사용자(본인)가 로그인/앱키/계좌 인증을 완료할 때까지 테스트를 대기하고, 완료 신호를 받은 뒤 다음 단계를 진행
[진행 로그]
- 2026-03-06: 현재 자동매매 코드를 점검한 결과, 매도가능수량 비교는 일부 구현되어 있으나 `allocationPercent` 실주문 반영, 세금/수수료 반영, 순손익 기준 손실 관리, 체결 후 정산 반영은 미흡한 상태로 판단함.
- 2026-03-06: 구현 방향을 `예산 계산 -> 주문 수량 계산 -> 보유/매도가능 수량 검증 -> 비용 추정 -> 체결 후 실제 정산` 순서로 재설계하기로 함.
- 2026-03-06: `lib/autotrade/risk.ts`에서 `allocationPercent`를 실주문 예산 계산에 강제 반영하도록 변경하고, BUY/SELL 수량 계산 경로를 분리함.
- 2026-03-06: `useAutotradeEngine.ts`에 비용 추정(수수료/세금), 체결 전후 활동/잔고 재조회, 누적 손실 한도 자동중지 로직을 반영함.
- 2026-03-06: AI 신호 스냅샷에 `budgetContext`, `portfolioContext`, `executionCostProfile`을 추가하고 OpenAI/CLI 프롬프트 규칙에 예산/보유/비용 제약을 반영함.
- 2026-03-06: 검증 결과 `npm run lint`, `npm run build` 통과. `npm run test:autotrade:smoke`는 로그인 필요(개발 우회 토큰 미적용 환경)로 실패함.
- 2026-03-06: Playwright 스모크로 `/`, `/trade`(로그인 리다이렉트 확인), `/settings`(로그인 리다이렉트 확인) 화면 로드 및 콘솔 error 없음 확인.
- 2026-03-06: Playwright 테스트 협업 규칙 추가 - 로그인/앱키/계좌 인증은 사용자가 직접 완료하고, 완료 전에는 테스트를 대기하도록 문서에 명시함.
- 2026-03-06: `lib/autotrade/executable-order-quantity.ts` 순수 clamp 유틸을 추가하고, `useAutotradeEngine.ts`의 실제 주문수량 검증에 연결함.
- 2026-03-06: 단위 테스트 추가(`tests/autotrade/risk-budget.test.ts`, `tests/autotrade/order-guard-cost.test.ts`) 후 `npm run test:autotrade:unit` 통과.
- 2026-03-06: `.env.local`의 실제 `AUTOTRADE_DEV_BYPASS_TOKEN`, `AUTOTRADE_WORKER_TOKEN`으로 스모크 재실행하여 `npm run test:autotrade:smoke` 통과.
- 2026-03-06: Playwriter 실브라우저 디버깅으로 `/trade` 화면에서 `내 설정 점검 -> 자동매매 시작 -> 수동 중지` 흐름 확인(세션 시작/중지 로그 정상, 브라우저 콘솔 error 없음). 장중 실시간 틱 부재로 신호요청/주문실행 로그는 미발생.
- 2026-03-06: AI 스냅샷의 `estimatedBuyableQuantity` 계산을 실제 주문 함수(`resolveOrderQuantity`)와 동일하게 통일해, 비율 예산으로 0주가 나와도 전체 예산 1주 가능 시 `1주`가 전달되도록 핫픽스함.
- 2026-03-06: Playwriter 네트워크 검증으로 `/api/autotrade/signals/generate` 요청 본문에 `estimatedBuyableQuantity=1`, `effectiveAllocationAmount=21631`, `effectiveOrderBudgetAmount=7570`, `currentPrice=16790`이 전달되는 것을 확인함(수량 0 전달 이슈 해소).
- 2026-03-06: 검증 자금 산정 로직을 `예수금 + 매수가능금액` 동시 조회 기반으로 변경하고, 두 값이 모두 있을 때는 더 보수적인 값(min)을 사용하도록 반영함.
- 2026-03-06: 자동매매 설정창의 투자비율 입력 UX를 퍼센트 프리셋 버튼 + 슬라이더 + 금액 자동입력 버튼으로 개선하고, 안전 점검 라벨을 `가용 예수금`에서 `주문 기준 자금`으로 변경함.
- 2026-03-06: `setNumberField`를 필드별 범위(clamp) 보정 방식으로 바꿔 퍼센트/신뢰도 입력이 비정상 값(음수, 100% 초과, 임계값 범위 이탈)으로 저장되지 않도록 정리함.
- 2026-03-06: 회귀 검증으로 `npm run test:autotrade:unit`, `npm run lint`, `npm run build` 재실행 모두 통과함.