Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions pykis/adapter/account_product/order_modify.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
from typing import TYPE_CHECKING, Protocol, runtime_checkable

from pykis.utils.params import EMPTY, EMPTY_TYPE

if TYPE_CHECKING:
from pykis.api.account.order import (
IN_ORDER_QUANTITY,
ORDER_CONDITION,
ORDER_EXECUTION,
ORDER_PRICE,
KisOrder,
KisOrderNumber,
)


@runtime_checkable
class KisCancelableOrder(Protocol):
"""취소 가능 주문 프로토콜"""

def cancel(self) -> "KisOrder":
"""
한국투자증권 통합 주식 주문취소 (해외 주간거래 모의투자 미지원)

국내주식주문 -> 주식주문(정정취소)[v1_국내주식-003]
국내주식주문 -> 해외주식 정정취소주문[v1_해외주식-003]
"""
raise NotImplementedError


class KisModifyableOrder(Protocol):
"""정정 가능 주문 프로토콜"""

def modify(
self,
price: "ORDER_PRICE | None | EMPTY_TYPE" = EMPTY,
qty: "IN_ORDER_QUANTITY | None" = None,
condition: "ORDER_CONDITION | None | EMPTY_TYPE" = EMPTY,
execution: "ORDER_EXECUTION | None | EMPTY_TYPE" = EMPTY,
) -> "KisOrder":
"""
한국투자증권 통합 주식 주문정정 (국내 모의투자 미지원, 해외 주간거래 모의투자 미지원)

국내주식주문 -> 주식주문(정정취소)[v1_국내주식-003]
국내주식주문 -> 해외주식 정정취소주문[v1_해외주식-003]

Args:
price (ORDER_PRICE, optional): 주문가격
qty (IN_ORDER_QUANTITY, optional): 주문수량
condition (ORDER_CONDITION, optional): 주문조건
execution (ORDER_EXECUTION_CONDITION, optional): 체결조건
"""
raise NotImplementedError


@runtime_checkable
class KisOrderableOrder(KisCancelableOrder, KisModifyableOrder, Protocol):
"""주문 가능 주문 프로토콜"""


class KisCancelableOrderImpl:
"""취소 가능 주문"""

def cancel(
self: "KisOrderNumber",
) -> "KisOrder":
"""
한국투자증권 통합 주식 주문취소 (해외 주간거래 모의투자 미지원)

국내주식주문 -> 주식주문(정정취소)[v1_국내주식-003]
국내주식주문 -> 해외주식 정정취소주문[v1_해외주식-003]
"""
from pykis.api.account.order_modify import cancel_order

return cancel_order(self.kis, order=self)


class KisModifyableOrderImpl:
"""정정 가능 주문"""

def modify(
self: "KisOrderNumber",
price: "ORDER_PRICE | None | EMPTY_TYPE" = EMPTY,
qty: "IN_ORDER_QUANTITY | None" = None,
condition: "ORDER_CONDITION | None | EMPTY_TYPE" = EMPTY,
execution: "ORDER_EXECUTION | None | EMPTY_TYPE" = EMPTY,
) -> "KisOrder":
"""
한국투자증권 통합 주식 주문정정 (국내 모의투자 미지원, 해외 주간거래 모의투자 미지원)

국내주식주문 -> 주식주문(정정취소)[v1_국내주식-003]
국내주식주문 -> 해외주식 정정취소주문[v1_해외주식-003]

Args:
price (ORDER_PRICE, optional): 주문가격
qty (IN_ORDER_QUANTITY, optional): 주문수량
condition (ORDER_CONDITION, optional): 주문조건
execution (ORDER_EXECUTION_CONDITION, optional): 체결조건
"""
from pykis.api.account.order_modify import modify_order

return modify_order(
self.kis,
order=self,
price=price,
qty=qty,
condition=condition,
execution=execution,
)


class KisOrderableOrderImpl(KisCancelableOrderImpl, KisModifyableOrderImpl):
"""주문 가능 주문"""
81 changes: 68 additions & 13 deletions pykis/adapter/websocket/execution.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import TYPE_CHECKING, Callable, Literal, Protocol, runtime_checkable

from pykis.api.base.account import KisAccountProtocol
from pykis.event.handler import KisEventFilter, KisEventTicket
from pykis.event.handler import KisEventFilter, KisEventTicket, KisMultiEventFilter
from pykis.event.subscription import KisSubscriptionEventArgs

if TYPE_CHECKING:
from pykis.api.account.order import KisOrder
from pykis.api.websocket.order_execution import KisRealtimeExecution
from pykis.client.websocket import KisWebsocketClient

Expand All @@ -22,9 +23,7 @@ def on(
self,
event: Literal["execution"],
callback: "Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]",
where: (
"KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None"
) = None,
where: "KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None" = None,
once: bool = False,
) -> "KisEventTicket[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]]":
"""
Expand All @@ -44,9 +43,7 @@ def once(
self,
event: Literal["execution"],
callback: "Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]",
where: (
"KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None"
) = None,
where: "KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None" = None,
) -> "KisEventTicket[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]]":
"""
웹소켓 이벤트 핸들러 등록
Expand All @@ -68,9 +65,7 @@ def on(
self: "KisAccountProtocol",
event: Literal["execution"],
callback: "Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]",
where: (
"KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None"
) = None,
where: "KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None" = None,
once: bool = False,
) -> "KisEventTicket[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]]":
"""
Expand Down Expand Up @@ -100,9 +95,7 @@ def once(
self: "KisAccountProtocol",
event: Literal["execution"],
callback: "Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]",
where: (
"KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None"
) = None,
where: "KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None" = None,
) -> "KisEventTicket[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]]":
"""
웹소켓 이벤트 핸들러 등록
Expand All @@ -125,3 +118,65 @@ def once(
)

raise ValueError(f"Unknown event: {event}")


class KisRealtimeOrderableOrderImpl:
"""한국투자증권 실시간 주문 가능 주문"""

def on(
self: "KisOrder",
event: Literal["execution"],
callback: "Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]",
where: "KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None" = None,
once: bool = False,
) -> "KisEventTicket[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]]":
"""
웹소켓 이벤트 핸들러 등록

[국내주식] 실시간시세 -> 국내주식 실시간체결통보[실시간-005]
[해외주식] 실시간시세 -> 해외주식 실시간체결통보[실시간-009]

Args:
callback (Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]): 콜백 함수
where (KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None, optional): 이벤트 필터. Defaults to None.
once (bool, optional): 한번만 실행 여부. Defaults to False.
"""
from pykis.api.websocket.order_execution import on_account_execution

if event == "execution":
return on_account_execution(
self,
callback=callback,
where=KisMultiEventFilter(self, where) if where else self,
once=once,
)

raise ValueError(f"Unknown event: {event}")

def once(
self: "KisOrder",
event: Literal["execution"],
callback: "Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]",
where: "KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None" = None,
) -> "KisEventTicket[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]]":
"""
웹소켓 이벤트 핸들러 등록

[국내주식] 실시간시세 -> 국내주식 실시간체결통보[실시간-005]
[해외주식] 실시간시세 -> 해외주식 실시간체결통보[실시간-009]

Args:
callback (Callable[[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]], None]): 콜백 함수
where (KisEventFilter[KisWebsocketClient, KisSubscriptionEventArgs[KisRealtimeExecution]] | None, optional): 이벤트 필터. Defaults to None.
"""
from pykis.api.websocket.order_execution import on_account_execution

if event == "execution":
return on_account_execution(
self,
callback=callback,
where=KisMultiEventFilter(self, where) if where else self,
once=True,
)

raise ValueError(f"Unknown event: {event}")
5 changes: 3 additions & 2 deletions pykis/api/account/daily_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ORDER_QUANTITY,
ORDER_TYPE,
KisOrder,
KisSimpleOrder,
)
from pykis.api.base.account import KisAccountBase, KisAccountProtocol
from pykis.api.base.account_product import (
Expand Down Expand Up @@ -372,7 +373,7 @@ class KisDomesticDailyOrder(KisDynamic, KisDailyOrderBase):
@property
def order_number(self) -> KisOrder:
"""주문번호"""
return KisOrder.from_order(
return KisSimpleOrder.from_order(
account_number=self.account_number,
symbol=self.symbol,
market=self.market,
Expand Down Expand Up @@ -495,7 +496,7 @@ class KisForeignDailyOrder(KisDynamic, KisDailyOrderBase):
@cached
def order_number(self) -> KisOrder:
"""주문번호"""
return KisOrder.from_order(
return KisSimpleOrder.from_order(
account_number=self.account_number,
symbol=self.symbol,
market=self.market,
Expand Down
Loading