Files

183 lines
5.6 KiB
Python
Raw Permalink Normal View History

2025-11-14 22:56:44 +00:00
from abc import ABC, abstractmethod
from typing import Dict, List, Optional, Any
from datetime import datetime
import asyncio
from loguru import logger
from ..strategy.base import SignalEvent, Position
class OrderEvent:
"""订单事件"""
def __init__(
self,
instrument: str,
order_type: str, # "MARKET", "LIMIT", "STOP"
direction: str, # "BUY", "SELL"
quantity: float,
timestamp: datetime,
price: Optional[float] = None,
stop_loss: Optional[float] = None,
take_profit: Optional[float] = None,
order_id: Optional[str] = None
):
self.event_type = "ORDER"
self.instrument = instrument
self.order_type = order_type
self.direction = direction
self.quantity = quantity
self.timestamp = timestamp
self.price = price
self.stop_loss = stop_loss
self.take_profit = take_profit
self.order_id = order_id
self.status = "CREATED" # CREATED, SUBMITTED, FILLED, CANCELLED, REJECTED
class FillEvent:
"""成交事件"""
def __init__(
self,
instrument: str,
direction: str,
quantity: float,
price: float,
timestamp: datetime,
commission: float = 0.0,
order_id: Optional[str] = None
):
self.event_type = "FILL"
self.instrument = instrument
self.direction = direction
self.quantity = quantity
self.price = price
self.timestamp = timestamp
self.commission = commission
self.order_id = order_id
class ExecutionHandler(ABC):
"""
执行处理器基类
负责订单执行和管理
"""
def __init__(self):
self.orders: Dict[str, OrderEvent] = {} # order_id -> OrderEvent
self.positions: Dict[str, Position] = {} # instrument -> Position
self.fills: List[FillEvent] = []
self._order_callbacks = []
self._fill_callbacks = []
async def process_signal(self, signal: SignalEvent, price: Optional[float] = None) -> OrderEvent:
"""
处理交易信号并创建订单
Args:
signal: 交易信号
Returns:
创建的订单事件
"""
order = OrderEvent(
instrument=signal.instrument,
order_type="MARKET", # 默认为市价单
direction="BUY" if signal.signal_type == "LONG" else "SELL",
quantity=abs(signal.strength),
timestamp=signal.timestamp,
stop_loss=signal.stop_loss,
take_profit=signal.take_profit,
price=price
)
# 生成订单ID
order.order_id = f"{order.instrument}_{order.timestamp.strftime('%Y%m%d_%H%M%S')}"
self.orders[order.order_id] = order
# 执行订单
try:
await self.execute_order(order)
except Exception as e:
logger.error(f"订单执行失败: {str(e)}")
order.status = "REJECTED"
return order
@abstractmethod
async def execute_order(self, order: OrderEvent) -> None:
"""
执行订单
Args:
order: 要执行的订单
"""
pass
@abstractmethod
async def cancel_order(self, order_id: str) -> bool:
"""
取消订单
Args:
order_id: 要取消的订单ID
Returns:
是否成功取消
"""
pass
def add_order_callback(self, callback):
"""添加订单状态更新回调"""
self._order_callbacks.append(callback)
def add_fill_callback(self, callback):
"""添加成交更新回调"""
self._fill_callbacks.append(callback)
async def _notify_order(self, order: OrderEvent):
"""通知订单状态更新"""
for callback in self._order_callbacks:
await callback(order)
async def _notify_fill(self, fill: FillEvent):
"""通知成交更新"""
for callback in self._fill_callbacks:
await callback(fill)
def get_position(self, instrument: str) -> Optional[Position]:
"""获取某个品种的持仓"""
return self.positions.get(instrument)
def get_all_positions(self) -> List[Position]:
"""获取所有持仓"""
return list(self.positions.values())
def update_position(self, fill: FillEvent) -> None:
"""根据成交更新持仓"""
instrument = fill.instrument
position = self.positions.get(instrument)
if position is None:
# 新建仓位
position = Position(
instrument=instrument,
direction=fill.direction,
size=fill.quantity,
entry_price=fill.price,
entry_time=fill.timestamp
)
self.positions[instrument] = position
else:
# 更新现有仓位
if fill.direction == position.direction:
# 同向加仓
new_size = position.size + fill.quantity
position.entry_price = (position.entry_price * position.size +
fill.price * fill.quantity) / new_size
position.size = new_size
else:
# 反向减仓
position.size -= fill.quantity
if position.size <= 0:
# 清仓
del self.positions[instrument]