diff --git a/pykis/api/account/order.py b/pykis/api/account/order.py index 46457acf..d27237f9 100644 --- a/pykis/api/account/order.py +++ b/pykis/api/account/order.py @@ -525,7 +525,7 @@ def __eq__(self, value: object | KisOrderNumber) -> bool: self.account_number == value.account_number # type: ignore and self.symbol == value.symbol # type: ignore and self.market == value.market # type: ignore - and self.branch == value.branch # type: ignore + and (self.foreign or self.branch == value.branch) # type: ignore and int(self.number) == int(value.number) # type: ignore ) except AttributeError: diff --git a/pykis/api/websocket/__init__.py b/pykis/api/websocket/__init__.py index 709e5d9c..ed26762f 100644 --- a/pykis/api/websocket/__init__.py +++ b/pykis/api/websocket/__init__.py @@ -3,7 +3,10 @@ KisDomesticRealtimeOrderbook, KisUSRealtimeOrderbook, ) -from pykis.api.websocket.order_execution import KisDomesticRealtimeOrderExecution +from pykis.api.websocket.order_execution import ( + KisDomesticRealtimeOrderExecution, + KisForeignRealtimeOrderExecution, +) from pykis.api.websocket.price import KisDomesticRealtimePrice, KisForeignRealtimePrice from pykis.responses.websocket import KisWebsocketResponse @@ -15,4 +18,6 @@ "HDFSASP0": KisUSRealtimeOrderbook, "H0STCNI0": KisDomesticRealtimeOrderExecution, "H0STCNI9": KisDomesticRealtimeOrderExecution, + "H0GSCNI0": KisForeignRealtimeOrderExecution, + "H0GSCNI9": KisForeignRealtimeOrderExecution, } diff --git a/pykis/api/websocket/order_execution.py b/pykis/api/websocket/order_execution.py index e2208e3d..c21eada3 100644 --- a/pykis/api/websocket/order_execution.py +++ b/pykis/api/websocket/order_execution.py @@ -392,7 +392,9 @@ class KisForeignRealtimeOrderExecution(KisRealtimeExecutionBase): None, # 12 CNTG_YN 체결여부 1:주문,정정,취소,거부 2:체결 None, # 13 ACPT_YN 접수여부 1:주문접수 2:확인 3:취소(FOK/IOC) None, # 14 BRNC_NO 지점번호 - KisDecimal["quantity"], # 15 ODER_QTY 주문수량 + KisDecimal[ + "quantity", Decimal(-1) + ], # 15 ODER_QTY 주문수량 ,주문통보인 경우 해당 위치 미출력 (주문통보의 주문수량은 CNTG_QTY 위치에 출력). 체결통보인 경우 해당 위치에 주문수량이 출력 None, # 16 ACNT_NAME 계좌명 None, # 17 CNTG_ISNM 체결종목명 KisAny(FOREIGN_MARKET_CODE_MAP.__getitem__)[ @@ -469,6 +471,9 @@ def __post_init__(self): self.timezone = get_market_timezone(self.market) self.time = self.time_kst.astimezone(self.timezone) + if self.quantity < 0: + self.quantity = self.executed_quantity + if self.receipt: self.quantity = self.executed_quantity self.executed_quantity = ORDER_QUANTITY(0) diff --git a/pykis/event/filters/order.py b/pykis/event/filters/order.py index 8d620883..29d307a8 100644 --- a/pykis/event/filters/order.py +++ b/pykis/event/filters/order.py @@ -149,7 +149,7 @@ def __filter__( return not ( order.symbol == value.symbol and order.market == value.market - and order.branch == value.branch + and (order.foreign or order.branch == value.branch) and int(order.number) == int(value.number) and order.account_number == value.account_number ) diff --git a/pykis/responses/websocket.py b/pykis/responses/websocket.py index 88f75837..4c16fa7f 100644 --- a/pykis/responses/websocket.py +++ b/pykis/responses/websocket.py @@ -2,7 +2,7 @@ from typing import Any, Iterable, Protocol, TypeVar, get_args, runtime_checkable from pykis import logging -from pykis.responses.dynamic import KisNoneValueError, KisType +from pykis.responses.dynamic import KisNoneValueError, KisType, empty from pykis.responses.types import KisAny __all__ = [ @@ -111,9 +111,7 @@ def parse( field = field.default_type() if field.field is None: - logging.logger.warning( - f"{response_type.__name__}[{i}] 필드의 이름이 지정되지 않았습니다." - ) + logging.logger.warning(f"{response_type.__name__}[{i}] 필드의 이름이 지정되지 않았습니다.") continue try: @@ -124,16 +122,17 @@ def parse( setattr(response, field.field, value) except KisNoneValueError: - nullable = ( - NoneType in get_args(anno) if (anno := annotation.get(field.field)) else False - ) + nullable = NoneType in get_args(anno) if (anno := annotation.get(field.field)) else False - if not nullable: - raise ValueError( - f"{response_type.__name__}.{field.field} 필드가 None일 수 없습니다." - ) + default_value = None if field.default is empty else field.default - setattr(response, field.field, None) + if callable(default_value): + default_value = default_value() + + if default_value is None and not nullable: + raise ValueError(f"{response_type.__name__}.{field.field} 필드가 None일 수 없습니다.") + + setattr(response, field.field, default_value) except Exception as e: raise ValueError(