fix: use broker balance API as source of truth for SELL qty and holdings (#164 #165) #169

Merged
jihoson merged 1 commits from feature/issue-164-165-broker-api-holdings into main 2026-02-20 07:52:26 +09:00
Collaborator

배경

PR #167, #168에서 DB 기반으로 SELL 수량과 보유 종목을 조회했으나, 유저 피드백에 따라 재검토.

문제: DB의 quantity 필드는 주문 수량이지 체결 수량이 아님.

  • 부분 체결: 10주 주문 → 5주만 체결 → DB는 10 기록
  • 외부 수동 거래: 봇 밖에서 매도 → DB에 반영 안 됨
  • 결제 시점 차이: 주문 성공과 체결 확정 사이 시차 존재

해결책

브로커 잔고 API (get_balance() output1)를 source of truth로 사용.
trading_cycle은 이미 각 종목마다 get_balance()를 호출하고 있으므로 추가 API 호출 없음.

변경 내용

_extract_held_qty_from_balance() 신규

# 국내: pdno → ord_psbl_qty (주문가능수량, 미결제 제외)
# 해외: ovrs_pdno → ovrs_cblc_qty
# 각각 hldg_qty fallback 지원

_determine_order_quantity() 수정

# Before
if action != "BUY":
    return 1  # 항상 1주

# After
if action == "SELL":
    return broker_held_qty  # 브로커 확인 수량 (0이면 스킵)

_extract_held_codes_from_balance() 신규

# ord_psbl_qty > 0인 종목 코드 목록 반환
# 보유 종목 루프 병합에 사용

실시간 루프 보유 종목 병합

# 스캔 시점에 get_balance() 호출 (1회)
held_balance = await broker.get_balance()
held_codes = _extract_held_codes_from_balance(held_balance, is_domestic=True)
stock_codes = list(dict.fromkeys(scanner_codes + held_codes))
# API 실패 시 경고 후 스캐너 후보만으로 계속

테스트

  • TestExtractHeldQtyFromBalance — 7개 (국내/해외/fallback/미보유/케이스 무관)
  • TestExtractHeldCodesFromBalance — 4개 (qty>0 포함, qty=0 제외 등)
  • TestDetermineOrderQuantity — 5개 (SELL qty, BUY sizing)
  • test_sell_order_uses_broker_balance_qty_not_db — DB 10주 vs 브로커 5주 → 5주 사용 검증
  • 기존 stop_loss/take_profit 테스트에 output1 mock 추가해 일관성 유지
  • 689 tests passed

Closes #164
Closes #165
Supersedes #167, #168 (closed)

🤖 Generated with Claude Code

## 배경 PR #167, #168에서 DB 기반으로 SELL 수량과 보유 종목을 조회했으나, 유저 피드백에 따라 재검토. **문제**: DB의 `quantity` 필드는 **주문 수량**이지 **체결 수량**이 아님. - 부분 체결: 10주 주문 → 5주만 체결 → DB는 10 기록 - 외부 수동 거래: 봇 밖에서 매도 → DB에 반영 안 됨 - 결제 시점 차이: 주문 성공과 체결 확정 사이 시차 존재 ## 해결책 브로커 잔고 API (`get_balance()` output1)를 source of truth로 사용. `trading_cycle`은 이미 각 종목마다 `get_balance()`를 호출하고 있으므로 **추가 API 호출 없음**. ## 변경 내용 ### `_extract_held_qty_from_balance()` 신규 ```python # 국내: pdno → ord_psbl_qty (주문가능수량, 미결제 제외) # 해외: ovrs_pdno → ovrs_cblc_qty # 각각 hldg_qty fallback 지원 ``` ### `_determine_order_quantity()` 수정 ```python # Before if action != "BUY": return 1 # 항상 1주 # After if action == "SELL": return broker_held_qty # 브로커 확인 수량 (0이면 스킵) ``` ### `_extract_held_codes_from_balance()` 신규 ```python # ord_psbl_qty > 0인 종목 코드 목록 반환 # 보유 종목 루프 병합에 사용 ``` ### 실시간 루프 보유 종목 병합 ```python # 스캔 시점에 get_balance() 호출 (1회) held_balance = await broker.get_balance() held_codes = _extract_held_codes_from_balance(held_balance, is_domestic=True) stock_codes = list(dict.fromkeys(scanner_codes + held_codes)) # API 실패 시 경고 후 스캐너 후보만으로 계속 ``` ## 테스트 - [x] `TestExtractHeldQtyFromBalance` — 7개 (국내/해외/fallback/미보유/케이스 무관) - [x] `TestExtractHeldCodesFromBalance` — 4개 (qty>0 포함, qty=0 제외 등) - [x] `TestDetermineOrderQuantity` — 5개 (SELL qty, BUY sizing) - [x] `test_sell_order_uses_broker_balance_qty_not_db` — DB 10주 vs 브로커 5주 → 5주 사용 검증 - [x] 기존 stop_loss/take_profit 테스트에 output1 mock 추가해 일관성 유지 - [x] 689 tests passed Closes #164 Closes #165 Supersedes #167, #168 (closed) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
agentson added 1 commit 2026-02-20 07:41:18 +09:00
fix: use broker balance API as source of truth for SELL qty and holdings (#164 #165)
Some checks failed
CI / test (pull_request) Has been cancelled
305120f599
DB의 주문 수량 기록은 실제 체결 수량과 다를 수 있음(부분 체결, 외부 수동 거래).
브로커 잔고 API(output1)를 source of truth로 사용하도록 수정.

## 변경 사항

### SELL 수량 (#164)
- _extract_held_qty_from_balance() 추가
  - 국내: output1의 ord_psbl_qty (→ hldg_qty fallback)
  - 해외: output1의 ovrs_cblc_qty (→ hldg_qty fallback)
- _determine_order_quantity()에 broker_held_qty 파라미터 추가
  - SELL 시 broker_held_qty 반환 (0이면 주문 스킵)
- trading_cycle / run_daily_session 양쪽 호출 지점 수정
  - 이미 fetch된 balance_data에서 수량 추출 (추가 API 호출 없음)

### 보유 종목 루프 (#165)
- _extract_held_codes_from_balance() 추가
  - ord_psbl_qty > 0인 종목 코드 목록 반환
- 실시간 루프에서 스캔 시점에 get_balance() 호출해 보유 종목 병합
  - 스캐너 후보 + 실제 보유 종목 union으로 trading_cycle 순회
  - 실패 시 경고 로그 후 스캐너 후보만으로 계속 진행

### 테스트
- TestExtractHeldQtyFromBalance: 7개 (국내/해외/fallback/미보유)
- TestExtractHeldCodesFromBalance: 4개 (qty>0 포함, qty=0 제외 등)
- TestDetermineOrderQuantity: 5개 (SELL qty, BUY sizing)
- test_sell_order_uses_broker_balance_qty_not_db:
  DB 10주 기록 vs 브로커 5주 확인 → 브로커 값(5) 사용 검증
- 기존 SELL/stop-loss/take-profit 테스트에 output1 mock 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jihoson merged commit 03f8d220a4 into main 2026-02-20 07:52:26 +09:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jihoson/The-Ouroboros#169