fix: 해외 cash=0.00 및 get_open_position HOLD 필터링 수정 (#264, #265)
Some checks failed
CI / test (pull_request) Has been cancelled

## 변경사항

### #264 — 해외 매수가능금액 조회 API 교체 (frcr_dncl_amt_2 → inquire-psamount)
- TTTS3012R (해외주식 잔고) output2에 frcr_dncl_amt_2 필드가 존재하지 않아
  총 가용 현금이 항상 0.00으로 산출되는 문제 수정
- OverseasBroker에 get_overseas_buying_power() 메서드 추가
  (TR_ID: 실전 TTTS3007R / 모의 VTTS3007R, ord_psbl_frcr_amt 반환)
- main.py trading_cycle() 및 daily cycle 모두 수정
- 출처: 한국투자증권 오픈API 전체문서 (20260221) — 해외주식 매수가능금액조회 시트

### #265 — get_open_position() HOLD 레코드 필터링 추가
- HOLD 결정도 trades 테이블에 저장되어 BUY 이후 HOLD 기록 시
  최신 레코드가 HOLD → get_open_position이 None 반환하는 문제 수정
- 쿼리에 AND action IN ('BUY', 'SELL') 필터 추가
- HOLD 레코드를 제외하고 마지막 BUY/SELL 기록만 확인

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
agentson
2026-02-26 01:29:46 +09:00
parent 6a6d3bd631
commit df12be1305
4 changed files with 170 additions and 49 deletions

View File

@@ -222,6 +222,59 @@ class OverseasBroker:
f"Network error fetching overseas balance: {exc}"
) from exc
async def get_overseas_buying_power(
self,
exchange_code: str,
stock_code: str,
price: float,
) -> dict[str, Any]:
"""
Fetch overseas buying power for a specific stock and price.
Args:
exchange_code: Exchange code (e.g., "NASD", "NYSE")
stock_code: Stock ticker symbol
price: Current stock price (used for quantity calculation)
Returns:
API response; key field: output.ord_psbl_frcr_amt (주문가능외화금액)
Raises:
ConnectionError: On network or API errors
"""
await self._broker._rate_limiter.acquire()
session = self._broker._get_session()
# TR_ID: 실전 TTTS3007R, 모의 VTTS3007R
# Source: 한국투자증권 오픈API 전체문서 (20260221) — '해외주식 매수가능금액조회' 시트
ps_tr_id = (
"TTTS3007R" if self._broker._settings.MODE == "live" else "VTTS3007R"
)
headers = await self._broker._auth_headers(ps_tr_id)
params = {
"CANO": self._broker._account_no,
"ACNT_PRDT_CD": self._broker._product_cd,
"OVRS_EXCG_CD": exchange_code,
"OVRS_ORD_UNPR": f"{price:.2f}",
"ITEM_CD": stock_code,
}
url = (
f"{self._broker._base_url}/uapi/overseas-stock/v1/trading/inquire-psamount"
)
try:
async with session.get(url, headers=headers, params=params) as resp:
if resp.status != 200:
text = await resp.text()
raise ConnectionError(
f"get_overseas_buying_power failed ({resp.status}): {text}"
)
return await resp.json()
except (TimeoutError, aiohttp.ClientError) as exc:
raise ConnectionError(
f"Network error fetching overseas buying power: {exc}"
) from exc
async def send_overseas_order(
self,
exchange_code: str,