From 6ff887c047ec8354386e8bc4b016455bd1666e9c Mon Sep 17 00:00:00 2001 From: agentson Date: Thu, 26 Feb 2026 02:01:13 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=ED=95=B4=EC=99=B8=20=EB=A7=A4=EC=88=98?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=EA=B8=88=EC=95=A1=20ord=5Fpsbl=5Ffrcr=5Famt?= =?UTF-8?q?=20=E2=86=92=20ovrs=5Ford=5Fpsbl=5Famt=20=EA=B5=90=EC=B2=B4=20(?= =?UTF-8?q?#269)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 외화 예수금만 반영하는 ord_psbl_frcr_amt 대신 미결제 매도 대금(sll_ruse_psbl_amt)을 포함하는 ovrs_ord_psbl_amt (앱 '외화' 기준 통합 주문가능금액)를 사용하도록 수정. 실제 API 응답 확인: ord_psbl_frcr_amt = $139.25 (외화 예수금만) sll_ruse_psbl_amt = $7292.70 (미결제 매도 대금) ovrs_ord_psbl_amt = $7391.30 (합산, 원화 미포함) 원화 환산(frcr_ord_psbl_amt1)은 요구사항에 따라 사용하지 않음. 출처: KIS 공식문서(20260221) '해외주식 매수가능금액조회' 시트. Co-Authored-By: Claude Sonnet 4.6 --- src/main.py | 4 ++-- tests/test_main.py | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main.py b/src/main.py index 68122d1..3f16c75 100644 --- a/src/main.py +++ b/src/main.py @@ -537,7 +537,7 @@ async def trading_cycle( market.exchange_code, stock_code, current_price ) total_cash = safe_float( - ps_data.get("output", {}).get("ord_psbl_frcr_amt", "0") or "0" + ps_data.get("output", {}).get("ovrs_ord_psbl_amt", "0") or "0" ) except ConnectionError as exc: logger.warning( @@ -1710,7 +1710,7 @@ async def run_daily_session( ref_stock["current_price"], ) total_cash = safe_float( - ps_data.get("output", {}).get("ord_psbl_frcr_amt", "0") or "0" + ps_data.get("output", {}).get("ovrs_ord_psbl_amt", "0") or "0" ) except ConnectionError as exc: logger.warning( diff --git a/tests/test_main.py b/tests/test_main.py index 0662127..7a5e74c 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -909,7 +909,7 @@ class TestOverseasBalanceParsing: } ) broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "5000.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "5000.00"}} ) return broker @@ -929,7 +929,7 @@ class TestOverseasBalanceParsing: } ) broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "5000.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "5000.00"}} ) return broker @@ -942,7 +942,7 @@ class TestOverseasBalanceParsing: ) broker.get_overseas_balance = AsyncMock(return_value={"output2": []}) broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "0.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "0.00"}} ) return broker @@ -965,7 +965,7 @@ class TestOverseasBalanceParsing: ) # get_overseas_buying_power not called when price=0, but mock for safety broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "5000.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "5000.00"}} ) return broker @@ -1202,7 +1202,7 @@ class TestOverseasBalanceParsing: } ) broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "50000.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "50000.00"}} ) broker.send_overseas_order = AsyncMock(return_value={"msg1": "주문접수"}) return broker @@ -1309,7 +1309,7 @@ class TestOverseasBalanceParsing: } ) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "50000.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "50000.00"}} ) overseas_broker.send_overseas_order = AsyncMock( return_value={"rt_cd": "0", "msg1": "OK"} @@ -1373,7 +1373,7 @@ class TestOverseasBalanceParsing: } ) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "10000"}} + return_value={"output": {"ovrs_ord_psbl_amt": "10000"}} ) overseas_broker.get_overseas_price = AsyncMock( return_value={"output": {"last": "50.1234", "rate": "0"}} @@ -1434,7 +1434,7 @@ class TestOverseasBalanceParsing: } ) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "10000"}} + return_value={"output": {"ovrs_ord_psbl_amt": "10000"}} ) overseas_broker.get_overseas_price = AsyncMock( return_value={"output": {"last": "0.5678", "rate": "0"}} @@ -1735,7 +1735,7 @@ class TestScenarioEngineIntegration: "output2": [{"frcr_evlu_tota": "10000", "frcr_buy_amt_smtl": "9000"}] }) os_broker.get_overseas_buying_power = AsyncMock(return_value={ - "output": {"ord_psbl_frcr_amt": "500"} + "output": {"ovrs_ord_psbl_amt": "500"} }) with patch("src.main.log_trade"): @@ -2861,7 +2861,7 @@ class TestBuyCooldown: "output2": [{"frcr_evlu_tota": "50000", "frcr_buy_amt_smtl": "0"}], }) broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "50000"}} + return_value={"output": {"ovrs_ord_psbl_amt": "50000"}} ) broker.send_overseas_order = AsyncMock( return_value={"rt_cd": "1", "msg1": "모의투자 주문가능금액이 부족합니다."} @@ -2978,7 +2978,7 @@ class TestBuyCooldown: "output2": [{"frcr_evlu_tota": "50000", "frcr_buy_amt_smtl": "0"}], }) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "50000"}} + return_value={"output": {"ovrs_ord_psbl_amt": "50000"}} ) overseas_broker.send_overseas_order = AsyncMock( return_value={"rt_cd": "1", "msg1": "기타 오류 메시지"} @@ -3378,7 +3378,7 @@ async def test_buy_suppressed_when_open_position_exists() -> None: } ) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "10000"}} + return_value={"output": {"ovrs_ord_psbl_amt": "10000"}} ) overseas_broker.send_overseas_order = AsyncMock(return_value={"msg1": "OK"}) @@ -3445,7 +3445,7 @@ async def test_buy_proceeds_when_no_open_position() -> None: } ) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "50000"}} + return_value={"output": {"ovrs_ord_psbl_amt": "50000"}} ) overseas_broker.send_overseas_order = AsyncMock(return_value={"msg1": "OK"}) @@ -3554,7 +3554,7 @@ class TestOverseasBrokerIntegration: } ) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "50000.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "50000.00"}} ) overseas_broker.send_overseas_order = AsyncMock(return_value={"msg1": "주문접수"}) @@ -3630,7 +3630,7 @@ class TestOverseasBrokerIntegration: } ) overseas_broker.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "50000.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "50000.00"}} ) overseas_broker.send_overseas_order = AsyncMock(return_value={"msg1": "주문접수"}) @@ -4880,7 +4880,7 @@ class TestOverseasGhostPositionClose: ) ob.get_overseas_balance = AsyncMock(return_value=balance_data) ob.get_overseas_buying_power = AsyncMock( - return_value={"output": {"ord_psbl_frcr_amt": "0.00"}} + return_value={"output": {"ovrs_ord_psbl_amt": "0.00"}} ) ob.send_overseas_order = AsyncMock(return_value=sell_result) return ob