增加智能判断反向信号
This commit is contained in:
parent
8f4938f17a
commit
3f8b5fee23
@ -116,6 +116,7 @@ class Settings(BaseSettings):
|
|||||||
paper_trading_leverage: int = 10 # 杠杆倍数
|
paper_trading_leverage: int = 10 # 杠杆倍数
|
||||||
paper_trading_margin_per_order: float = 1000 # 每单保证金 (USDT)
|
paper_trading_margin_per_order: float = 1000 # 每单保证金 (USDT)
|
||||||
paper_trading_max_orders: int = 10 # 最大持仓+挂单总数
|
paper_trading_max_orders: int = 10 # 最大持仓+挂单总数
|
||||||
|
paper_trading_auto_close_opposite: bool = False # 是否自动平掉反向持仓(智能策略)
|
||||||
# 废弃的配置(保留兼容性)
|
# 废弃的配置(保留兼容性)
|
||||||
paper_trading_position_a: float = 1000 # A级信号仓位 (USDT)
|
paper_trading_position_a: float = 1000 # A级信号仓位 (USDT)
|
||||||
paper_trading_position_b: float = 500 # B级信号仓位 (USDT)
|
paper_trading_position_b: float = 500 # B级信号仓位 (USDT)
|
||||||
|
|||||||
@ -24,6 +24,7 @@ class PaperTradingService:
|
|||||||
self.leverage = self.settings.paper_trading_leverage # 杠杆倍数
|
self.leverage = self.settings.paper_trading_leverage # 杠杆倍数
|
||||||
self.margin_per_order = self.settings.paper_trading_margin_per_order # 每单保证金
|
self.margin_per_order = self.settings.paper_trading_margin_per_order # 每单保证金
|
||||||
self.max_orders = self.settings.paper_trading_max_orders # 最大订单数
|
self.max_orders = self.settings.paper_trading_max_orders # 最大订单数
|
||||||
|
self.auto_close_opposite = self.settings.paper_trading_auto_close_opposite # 是否自动平掉反向持仓
|
||||||
|
|
||||||
# 确保表已创建
|
# 确保表已创建
|
||||||
self._ensure_table_exists()
|
self._ensure_table_exists()
|
||||||
@ -31,7 +32,7 @@ class PaperTradingService:
|
|||||||
# 加载活跃订单到内存
|
# 加载活跃订单到内存
|
||||||
self._load_active_orders()
|
self._load_active_orders()
|
||||||
|
|
||||||
logger.info("模拟交易服务初始化完成")
|
logger.info(f"模拟交易服务初始化完成(自动平反向持仓: {'启用' if self.auto_close_opposite else '禁用'})")
|
||||||
|
|
||||||
def _ensure_table_exists(self):
|
def _ensure_table_exists(self):
|
||||||
"""确保数据表已创建"""
|
"""确保数据表已创建"""
|
||||||
@ -89,6 +90,15 @@ class PaperTradingService:
|
|||||||
side = OrderSide.LONG if action == 'buy' else OrderSide.SHORT
|
side = OrderSide.LONG if action == 'buy' else OrderSide.SHORT
|
||||||
entry_price = signal.get('entry_price') or signal.get('price', 0)
|
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. 检查总订单数(持仓+挂单)是否超过最大限制
|
# 1. 检查总订单数(持仓+挂单)是否超过最大限制
|
||||||
total_orders = len(self.active_orders)
|
total_orders = len(self.active_orders)
|
||||||
@ -474,6 +484,100 @@ class PaperTradingService:
|
|||||||
finally:
|
finally:
|
||||||
db.close()
|
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]]:
|
def get_active_orders(self, symbol: Optional[str] = None) -> List[Dict[str, Any]]:
|
||||||
"""获取活跃订单"""
|
"""获取活跃订单"""
|
||||||
orders = list(self.active_orders.values())
|
orders = list(self.active_orders.values())
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user