87 lines
2.6 KiB
Python
87 lines
2.6 KiB
Python
"""주문 실행 디스패처 — 국내/해외 공통 인터페이스.
|
|
|
|
trade_executor.py 의 is_domestic 분기를 여기서 캡슐화.
|
|
신규 시장(예: 일본, 홍콩) 추가 시 이 모듈만 수정.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Protocol
|
|
|
|
from app.services.korea_investment_api import korea_investment_api
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class OrderDispatcher(Protocol):
|
|
"""주문 실행 인터페이스."""
|
|
|
|
async def place(
|
|
self,
|
|
stock_code: str,
|
|
order_type: str,
|
|
quantity: int,
|
|
price: float,
|
|
) -> dict: ...
|
|
|
|
async def get_execution(self, order_id: str) -> dict: ...
|
|
|
|
def adjust_price(self, price: float, order_type: str) -> float: ...
|
|
|
|
|
|
class DomesticOrderDispatcher:
|
|
"""국내 주식 주문 실행."""
|
|
|
|
async def place(
|
|
self,
|
|
stock_code: str,
|
|
order_type: str,
|
|
quantity: int,
|
|
price: float,
|
|
**_,
|
|
) -> dict:
|
|
return await korea_investment_api.place_order(stock_code, order_type, quantity, price)
|
|
|
|
async def get_execution(self, order_id: str) -> dict:
|
|
return await korea_investment_api.get_order_execution(order_id, is_domestic=True)
|
|
|
|
def adjust_price(self, price: float, order_type: str) -> float:
|
|
"""BUY +0.5% / SELL -0.5%, 원화 정수 반환."""
|
|
adjusted = price * 1.005 if order_type == "BUY" else price * 0.995
|
|
return float(int(adjusted))
|
|
|
|
|
|
class OverseasOrderDispatcher:
|
|
"""해외 주식 주문 실행."""
|
|
|
|
def __init__(self, exchange_code: str = "NASD"):
|
|
self.exchange_code = exchange_code
|
|
|
|
async def place(
|
|
self,
|
|
stock_code: str,
|
|
order_type: str,
|
|
quantity: int,
|
|
price: float,
|
|
**_,
|
|
) -> dict:
|
|
return await korea_investment_api.place_overseas_order(
|
|
stock_code, order_type, quantity, float(price), self.exchange_code
|
|
)
|
|
|
|
async def get_execution(self, order_id: str) -> dict:
|
|
# 해외 체결 조회 미지원 — 포트폴리오 동기화로 대체
|
|
return {"filled_qty": 0, "filled_price": 0.0}
|
|
|
|
def adjust_price(self, price: float, order_type: str) -> float:
|
|
"""BUY +0.5% / SELL -0.5%, USD 소수점 2자리 반환."""
|
|
adjusted = price * 1.005 if order_type == "BUY" else price * 0.995
|
|
return round(adjusted, 2)
|
|
|
|
|
|
def get_dispatcher(is_domestic: bool, exchange_code: str = "NASD") -> DomesticOrderDispatcher | OverseasOrderDispatcher:
|
|
"""is_domestic 에 따라 적절한 디스패처 반환."""
|
|
if is_domestic:
|
|
return DomesticOrderDispatcher()
|
|
return OverseasOrderDispatcher(exchange_code=exchange_code)
|