a
This commit is contained in:
parent
cd74e96c22
commit
1344435667
|
|
@ -476,7 +476,8 @@ class BinanceClient:
|
||||||
side: str,
|
side: str,
|
||||||
quantity: float,
|
quantity: float,
|
||||||
order_type: str = 'MARKET',
|
order_type: str = 'MARKET',
|
||||||
price: Optional[float] = None
|
price: Optional[float] = None,
|
||||||
|
reduce_only: bool = False
|
||||||
) -> Optional[Dict]:
|
) -> Optional[Dict]:
|
||||||
"""
|
"""
|
||||||
下单
|
下单
|
||||||
|
|
@ -528,24 +529,27 @@ class BinanceClient:
|
||||||
logger.warning(f" 需要增加数量或提高仓位大小")
|
logger.warning(f" 需要增加数量或提高仓位大小")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# 构建订单参数
|
||||||
|
order_params = {
|
||||||
|
'symbol': symbol,
|
||||||
|
'side': side,
|
||||||
|
'type': order_type,
|
||||||
|
'quantity': adjusted_quantity
|
||||||
|
}
|
||||||
|
|
||||||
|
# 如果是平仓订单,添加 reduceOnly 参数
|
||||||
|
if reduce_only:
|
||||||
|
order_params['reduceOnly'] = True
|
||||||
|
logger.debug(f"{symbol} 使用 reduceOnly=True 平仓订单")
|
||||||
|
|
||||||
if order_type == 'MARKET':
|
if order_type == 'MARKET':
|
||||||
order = await self.client.futures_create_order(
|
order = await self.client.futures_create_order(**order_params)
|
||||||
symbol=symbol,
|
|
||||||
side=side,
|
|
||||||
type='MARKET',
|
|
||||||
quantity=adjusted_quantity
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if price is None:
|
if price is None:
|
||||||
raise ValueError("限价单必须指定价格")
|
raise ValueError("限价单必须指定价格")
|
||||||
order = await self.client.futures_create_order(
|
order_params['timeInForce'] = 'GTC'
|
||||||
symbol=symbol,
|
order_params['price'] = price
|
||||||
side=side,
|
order = await self.client.futures_create_order(**order_params)
|
||||||
type='LIMIT',
|
|
||||||
timeInForce='GTC',
|
|
||||||
quantity=adjusted_quantity,
|
|
||||||
price=price
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info(f"下单成功: {symbol} {side} {adjusted_quantity} @ {order_type} (名义价值: {notional_value:.2f} USDT)")
|
logger.info(f"下单成功: {symbol} {side} {adjusted_quantity} @ {order_type} (名义价值: {notional_value:.2f} USDT)")
|
||||||
return order
|
return order
|
||||||
|
|
|
||||||
|
|
@ -280,13 +280,24 @@ class PositionManager:
|
||||||
f"(持仓数量: {position_amt:.4f})"
|
f"(持仓数量: {position_amt:.4f})"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 平仓
|
# 平仓(使用 reduceOnly=True 确保只减少持仓,不增加反向持仓)
|
||||||
|
try:
|
||||||
|
logger.debug(f"{symbol} [平仓] 调用 place_order: {side} {quantity:.4f} @ MARKET (reduceOnly=True)")
|
||||||
order = await self.client.place_order(
|
order = await self.client.place_order(
|
||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
side=side,
|
side=side,
|
||||||
quantity=quantity,
|
quantity=quantity,
|
||||||
order_type='MARKET'
|
order_type='MARKET',
|
||||||
|
reduce_only=True # 平仓时使用 reduceOnly=True
|
||||||
)
|
)
|
||||||
|
logger.debug(f"{symbol} [平仓] place_order 返回: {order}")
|
||||||
|
except Exception as order_error:
|
||||||
|
logger.error(f"{symbol} [平仓] ❌ 下单失败: {order_error}")
|
||||||
|
logger.error(f" 下单参数: symbol={symbol}, side={side}, quantity={quantity:.4f}, order_type=MARKET")
|
||||||
|
logger.error(f" 错误类型: {type(order_error).__name__}")
|
||||||
|
import traceback
|
||||||
|
logger.error(f" 完整错误堆栈:\n{traceback.format_exc()}")
|
||||||
|
raise # 重新抛出异常,让外层捕获
|
||||||
|
|
||||||
if order:
|
if order:
|
||||||
logger.info(f"{symbol} [平仓] ✓ 平仓订单已提交 (订单ID: {order.get('orderId', 'N/A')})")
|
logger.info(f"{symbol} [平仓] ✓ 平仓订单已提交 (订单ID: {order.get('orderId', 'N/A')})")
|
||||||
|
|
@ -351,13 +362,48 @@ class PositionManager:
|
||||||
f"(原因: {reason})"
|
f"(原因: {reason})"
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
else:
|
||||||
|
# place_order 返回 None,说明下单失败
|
||||||
|
logger.error(f"{symbol} [平仓] ❌ 下单返回 None,可能的原因:")
|
||||||
|
logger.error(f" 1. 订单名义价值不足(小于最小要求)")
|
||||||
|
logger.error(f" 2. 数量精度调整后为 0 或负数")
|
||||||
|
logger.error(f" 3. 无法获取价格信息")
|
||||||
|
logger.error(f" 4. 其他下单错误(已在 place_order 中记录)")
|
||||||
|
logger.error(f" 持仓信息: {side} {quantity:.4f} @ MARKET")
|
||||||
|
|
||||||
|
# 尝试获取更多诊断信息
|
||||||
|
try:
|
||||||
|
symbol_info = await self.client.get_symbol_info(symbol)
|
||||||
|
ticker = await self.client.get_ticker_24h(symbol)
|
||||||
|
if ticker:
|
||||||
|
current_price = ticker['price']
|
||||||
|
notional_value = quantity * current_price
|
||||||
|
min_notional = symbol_info.get('minNotional', 5.0) if symbol_info else 5.0
|
||||||
|
logger.error(f" 当前价格: {current_price:.4f} USDT")
|
||||||
|
logger.error(f" 订单名义价值: {notional_value:.2f} USDT")
|
||||||
|
logger.error(f" 最小名义价值: {min_notional:.2f} USDT")
|
||||||
|
if notional_value < min_notional:
|
||||||
|
logger.error(f" ⚠ 订单名义价值不足,无法平仓")
|
||||||
|
except Exception as diag_error:
|
||||||
|
logger.warning(f" 无法获取诊断信息: {diag_error}")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{symbol} [平仓] ❌ 平仓失败: {e}")
|
logger.error(f"{symbol} [平仓] ❌ 平仓失败: {e}")
|
||||||
|
logger.error(f" 错误类型: {type(e).__name__}")
|
||||||
import traceback
|
import traceback
|
||||||
logger.error(f" 错误详情:\n{traceback.format_exc()}")
|
logger.error(f" 完整错误堆栈:\n{traceback.format_exc()}")
|
||||||
|
|
||||||
|
# 尝试清理本地记录(即使平仓失败)
|
||||||
|
try:
|
||||||
|
await self._stop_position_monitoring(symbol)
|
||||||
|
if symbol in self.active_positions:
|
||||||
|
del self.active_positions[symbol]
|
||||||
|
logger.info(f"{symbol} [平仓] 已清理本地持仓记录")
|
||||||
|
except Exception as cleanup_error:
|
||||||
|
logger.warning(f"{symbol} [平仓] 清理本地记录时出错: {cleanup_error}")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def check_stop_loss_take_profit(self) -> List[str]:
|
async def check_stop_loss_take_profit(self) -> List[str]:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user