Files
auto-stock/backend/app/services/order_dispatcher.py
2026-03-06 19:10:39 +09:00

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)