diff --git a/docs/commands.md b/docs/commands.md index 6f00b17..b72df71 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -192,6 +192,27 @@ When `TELEGRAM_COMMANDS_ENABLED=true` (default), the bot accepts these interacti Commands are only processed from the authorized `TELEGRAM_CHAT_ID`. +## KIS API TR_ID 참조 문서 + +**TR_ID를 추가하거나 수정할 때 반드시 공식 문서를 먼저 확인할 것.** + +공식 문서: `docs/한국투자증권_오픈API_전체문서_20260221_030000.xlsx` + +> ⚠️ 커뮤니티 블로그, GitHub 예제 등 비공식 자료의 TR_ID는 오래되거나 틀릴 수 있음. +> 실제로 `VTTT1006U`(미국 매도 — 잘못됨)가 오랫동안 코드에 남아있던 사례가 있음 (Issue #189). + +### 주요 TR_ID 목록 + +| 구분 | 모의투자 TR_ID | 실전투자 TR_ID | 시트명 | +|------|---------------|---------------|--------| +| 해외주식 매수 (미국) | `VTTT1002U` | `TTTT1002U` | 해외주식 주문 | +| 해외주식 매도 (미국) | `VTTT1001U` | `TTTT1006U` | 해외주식 주문 | + +새로운 TR_ID가 필요할 때: +1. 위 xlsx 파일에서 해당 거래 유형의 시트를 찾는다. +2. 모의투자(`VTTT`) / 실전투자(`TTTT`) 컬럼을 구분하여 정확한 값을 사용한다. +3. 코드에 출처 주석을 남긴다: `# Source: 한국투자증권_오픈API_전체문서 — '<시트명>' 시트` + ## Environment Setup ```bash diff --git a/docs/requirements-log.md b/docs/requirements-log.md index c2c2b72..7a654c7 100644 --- a/docs/requirements-log.md +++ b/docs/requirements-log.md @@ -7,6 +7,32 @@ --- +## 2026-02-21 + +### 거래 상태 확인 중 발견된 버그 (#187) + +- 거래 상태 점검 요청 → SELL 주문(손절/익절)이 Fat Finger에 막혀 전혀 실행 안 됨 발견 +- **#187 (Critical)**: SELL 주문에서 Fat Finger 오탐 — `order_amount/total_cash > 30%`가 SELL에도 적용되어 대형 포지션 매도 불가 + - JELD stop-loss -6.20% → 차단, RXT take-profit +46.13% → 차단 + - 수정: SELL은 `check_circuit_breaker`만 호출, `validate_order`(Fat Finger 포함) 미호출 + +--- + +## 2026-02-20 + +### 지속적 모니터링 및 개선점 도출 (이슈 #178~#182) + +- Dashboard 포함해서 실행하며 간헐적 문제 모니터링 및 개선점 자동 도출 요청 +- 모니터링 결과 발견된 이슈 목록: + - **#178**: uvicorn 미설치 → dashboard 미작동 + 오해의 소지 있는 시작 로그 → uvicorn 설치 완료 + - **#179 (Critical)**: 잔액 부족 주문 실패 후 매 사이클마다 무한 재시도 (MLECW 20분 이상 반복) + - **#180**: 다중 인스턴스 실행 시 Telegram 409 충돌 + - **#181**: implied_rsi 공식 포화 문제 (change_rate≥12.5% → RSI=100) + - **#182 (Critical)**: 보유 종목이 SmartScanner 변동성 필터에 걸려 SELL 신호 미생성 → SELL 체결 0건, 잔고 소진 +- 요구사항: 모니터링 자동화 및 주기적 개선점 리포트 도출 + +--- + ## 2026-02-05 ### API 효율화 diff --git a/src/broker/overseas.py b/src/broker/overseas.py index 3d37acb..fe9d448 100644 --- a/src/broker/overseas.py +++ b/src/broker/overseas.py @@ -230,7 +230,9 @@ class OverseasBroker: session = self._broker._get_session() # Virtual trading TR_IDs for overseas orders - tr_id = "VTTT1002U" if order_type == "BUY" else "VTTT1006U" + # Source: 한국투자증권 오픈API 전체문서 (20260221) — '해외주식 주문' 시트 + # VTTT1002U: 모의투자 미국 매수, VTTT1001U: 모의투자 미국 매도 + tr_id = "VTTT1002U" if order_type == "BUY" else "VTTT1001U" body = { "CANO": self._broker._account_no, diff --git a/tests/test_overseas_broker.py b/tests/test_overseas_broker.py index 620b98d..08f7fb5 100644 --- a/tests/test_overseas_broker.py +++ b/tests/test_overseas_broker.py @@ -414,7 +414,7 @@ class TestSendOverseasOrder: @pytest.mark.asyncio async def test_sell_limit_order(self, overseas_broker: OverseasBroker) -> None: - """Limit sell order should use VTTT1006U and ORD_DVSN=00.""" + """Limit sell order should use VTTT1001U and ORD_DVSN=00.""" mock_resp = AsyncMock() mock_resp.status = 200 mock_resp.json = AsyncMock(return_value={"rt_cd": "0"}) @@ -428,7 +428,7 @@ class TestSendOverseasOrder: result = await overseas_broker.send_overseas_order("NYSE", "MSFT", "SELL", 5, price=350.0) assert result["rt_cd"] == "0" - overseas_broker._broker._auth_headers.assert_called_with("VTTT1006U") + overseas_broker._broker._auth_headers.assert_called_with("VTTT1001U") call_args = mock_session.post.call_args body = call_args[1]["json"]