增加智能判断反向信号
This commit is contained in:
parent
8f4938f17a
commit
3f8b5fee23
@ -116,6 +116,7 @@ class Settings(BaseSettings):
|
||||
paper_trading_leverage: int = 10 # 杠杆倍数
|
||||
paper_trading_margin_per_order: float = 1000 # 每单保证金 (USDT)
|
||||
paper_trading_max_orders: int = 10 # 最大持仓+挂单总数
|
||||
paper_trading_auto_close_opposite: bool = False # 是否自动平掉反向持仓(智能策略)
|
||||
# 废弃的配置(保留兼容性)
|
||||
paper_trading_position_a: float = 1000 # A级信号仓位 (USDT)
|
||||
paper_trading_position_b: float = 500 # B级信号仓位 (USDT)
|
||||
|
||||
@ -24,6 +24,7 @@ class PaperTradingService:
|
||||
self.leverage = self.settings.paper_trading_leverage # 杠杆倍数
|
||||
self.margin_per_order = self.settings.paper_trading_margin_per_order # 每单保证金
|
||||
self.max_orders = self.settings.paper_trading_max_orders # 最大订单数
|
||||
self.auto_close_opposite = self.settings.paper_trading_auto_close_opposite # 是否自动平掉反向持仓
|
||||
|
||||
# 确保表已创建
|
||||
self._ensure_table_exists()
|
||||
@ -31,7 +32,7 @@ class PaperTradingService:
|
||||
# 加载活跃订单到内存
|
||||
self._load_active_orders()
|
||||
|
||||
logger.info("模拟交易服务初始化完成")
|
||||
logger.info(f"模拟交易服务初始化完成(自动平反向持仓: {'启用' if self.auto_close_opposite else '禁用'})")
|
||||
|
||||
def _ensure_table_exists(self):
|
||||
"""确保数据表已创建"""
|
||||
@ -89,6 +90,15 @@ class PaperTradingService:
|
||||
side = OrderSide.LONG if action == 'buy' else OrderSide.SHORT
|
||||
entry_price = signal.get('entry_price') or signal.get('price', 0)
|
||||
|
||||
# === 反向订单处理 ===
|
||||
# 1. 总是取消同一交易对的反向挂单(混合策略)
|
||||
self._cancel_opposite_pending_orders(symbol, side)
|
||||
|
||||
# 2. 可选:智能平掉反向持仓(需要配置启用)
|
||||
if self.auto_close_opposite and current_price:
|
||||
grade = signal.get('signal_grade') or signal.get('grade', 'D')
|
||||
self._close_opposite_positions(symbol, side, grade, current_price)
|
||||
|
||||
# === 限制检查 ===
|
||||
# 1. 检查总订单数(持仓+挂单)是否超过最大限制
|
||||
total_orders = len(self.active_orders)
|
||||
@ -474,6 +484,100 @@ class PaperTradingService:
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
def _cancel_opposite_pending_orders(self, symbol: str, new_side: OrderSide) -> int:
|
||||
"""
|
||||
取消同一交易对的反向挂单
|
||||
|
||||
Args:
|
||||
symbol: 交易对
|
||||
new_side: 新信号的方向
|
||||
|
||||
Returns:
|
||||
取消的订单数量
|
||||
"""
|
||||
# 找出所有反向挂单
|
||||
opposite_side = OrderSide.SHORT if new_side == OrderSide.LONG else OrderSide.LONG
|
||||
opposite_pending = [
|
||||
order for order in self.active_orders.values()
|
||||
if order.symbol == symbol
|
||||
and order.side == opposite_side
|
||||
and order.status == OrderStatus.PENDING
|
||||
]
|
||||
|
||||
if not opposite_pending:
|
||||
return 0
|
||||
|
||||
cancelled_count = 0
|
||||
for order in opposite_pending:
|
||||
result = self._cancel_pending_order(order)
|
||||
if result:
|
||||
cancelled_count += 1
|
||||
logger.info(f"自动取消反向挂单: {order.order_id} | {symbol} {opposite_side.value} @ ${order.entry_price:,.2f}")
|
||||
|
||||
if cancelled_count > 0:
|
||||
logger.info(f"已取消 {cancelled_count} 个反向挂单({symbol} {opposite_side.value}),新信号方向: {new_side.value}")
|
||||
|
||||
return cancelled_count
|
||||
|
||||
def _close_opposite_positions(self, symbol: str, new_side: OrderSide, signal_grade: str, current_price: float) -> int:
|
||||
"""
|
||||
智能平掉反向持仓(可选策略)
|
||||
|
||||
Args:
|
||||
symbol: 交易对
|
||||
new_side: 新信号的方向
|
||||
signal_grade: 新信号等级
|
||||
current_price: 当前价格
|
||||
|
||||
Returns:
|
||||
平仓的订单数量
|
||||
"""
|
||||
# 找出所有反向持仓
|
||||
opposite_side = OrderSide.SHORT if new_side == OrderSide.LONG else OrderSide.LONG
|
||||
opposite_positions = [
|
||||
order for order in self.active_orders.values()
|
||||
if order.symbol == symbol
|
||||
and order.side == opposite_side
|
||||
and order.status == OrderStatus.OPEN
|
||||
]
|
||||
|
||||
if not opposite_positions:
|
||||
return 0
|
||||
|
||||
closed_count = 0
|
||||
for order in opposite_positions:
|
||||
# 计算当前盈亏
|
||||
if order.side == OrderSide.LONG:
|
||||
pnl_percent = ((current_price - order.filled_price) / order.filled_price) * 100
|
||||
else:
|
||||
pnl_percent = ((order.filled_price - current_price) / order.filled_price) * 100
|
||||
|
||||
# 智能决策:只在特定条件下平仓
|
||||
should_close = False
|
||||
reason = ""
|
||||
|
||||
# 条件1:A级信号 + 反向持仓亏损超过3%
|
||||
if signal_grade == 'A' and pnl_percent < -3:
|
||||
should_close = True
|
||||
reason = f"A级反向信号且当前亏损{pnl_percent:.2f}%,提前止损"
|
||||
|
||||
# 条件2:A级信号 + 反向持仓盈利但接近止损(盈利<1%)
|
||||
elif signal_grade == 'A' and 0 < pnl_percent < 1:
|
||||
should_close = True
|
||||
reason = f"A级反向信号且盈利较小({pnl_percent:.2f}%),落袋为安"
|
||||
|
||||
if should_close:
|
||||
result = self._close_order(order, OrderStatus.CLOSED_MANUAL, current_price)
|
||||
if result:
|
||||
closed_count += 1
|
||||
logger.info(f"自动平掉反向持仓: {order.order_id} | {symbol} {opposite_side.value} | 原因: {reason}")
|
||||
|
||||
if closed_count > 0:
|
||||
logger.info(f"已平掉 {closed_count} 个反向持仓({symbol} {opposite_side.value})")
|
||||
|
||||
return closed_count
|
||||
|
||||
|
||||
def get_active_orders(self, symbol: Optional[str] = None) -> List[Dict[str, Any]]:
|
||||
"""获取活跃订单"""
|
||||
orders = list(self.active_orders.values())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user