This commit is contained in:
薇薇安 2026-01-13 23:50:13 +08:00
parent 6c04202a55
commit df634a8f02
2 changed files with 70 additions and 6 deletions

View File

@ -316,19 +316,26 @@ class BinanceClient:
# 提取数量精度信息
quantity_precision = s.get('quantityPrecision', 8)
# 从filters中提取minQty和stepSize
# 从filters中提取minQty、stepSize和minNotional
min_qty = None
step_size = None
min_notional = None
for f in s.get('filters', []):
if f['filterType'] == 'LOT_SIZE':
min_qty = float(f.get('minQty', 0))
step_size = float(f.get('stepSize', 0))
break
elif f['filterType'] == 'MIN_NOTIONAL':
min_notional = float(f.get('notional', 0))
# 如果没有从filters获取到minNotional使用默认值5 USDT
if min_notional is None or min_notional == 0:
min_notional = 5.0
info = {
'quantityPrecision': quantity_precision,
'minQty': min_qty or 0,
'stepSize': step_size or 0
'stepSize': step_size or 0,
'minNotional': min_notional
}
# 缓存信息
@ -416,7 +423,33 @@ class BinanceClient:
logger.error(f"调整后的数量无效: {adjusted_quantity} (原始: {quantity})")
return None
logger.info(f"下单: {symbol} {side} {adjusted_quantity} (原始: {quantity}) @ {order_type}")
# 获取当前价格以计算名义价值
if price is None:
ticker = await self.get_ticker_24h(symbol)
if not ticker:
logger.error(f"无法获取 {symbol} 的价格信息")
return None
current_price = ticker['price']
else:
current_price = price
# 计算订单名义价值
notional_value = adjusted_quantity * current_price
min_notional = symbol_info.get('minNotional', 5.0) if symbol_info else 5.0
logger.info(f"下单检查: {symbol} {side} {adjusted_quantity} (原始: {quantity}) @ {order_type}")
logger.info(f" 当前价格: {current_price:.4f} USDT")
logger.info(f" 订单名义价值: {notional_value:.2f} USDT")
logger.info(f" 最小名义价值: {min_notional:.2f} USDT")
# 检查名义价值是否满足最小要求
if notional_value < min_notional:
logger.warning(
f"{symbol} 订单名义价值不足: {notional_value:.2f} USDT < "
f"最小要求: {min_notional:.2f} USDT"
)
logger.warning(f" 需要增加数量或提高仓位大小")
return None
if order_type == 'MARKET':
order = await self.client.futures_create_order(
@ -437,7 +470,7 @@ class BinanceClient:
price=price
)
logger.info(f"下单成功: {symbol} {side} {adjusted_quantity} @ {order_type}")
logger.info(f"下单成功: {symbol} {side} {adjusted_quantity} @ {order_type} (名义价值: {notional_value:.2f} USDT)")
return order
except BinanceAPIException as e:
error_code = e.code if hasattr(e, 'code') else None
@ -446,6 +479,11 @@ class BinanceClient:
logger.error(f" 原始数量: {quantity}")
if symbol_info:
logger.error(f" 交易对精度: {symbol_info}")
elif error_code == -4164:
logger.error(f"下单失败 {symbol} {side}: 订单名义价值不足 - {e}")
logger.error(f" 订单名义价值必须至少为 5 USDT (除非选择 reduce only)")
if symbol_info:
logger.error(f" 最小名义价值: {symbol_info.get('minNotional', 5.0)} USDT")
else:
logger.error(f"下单失败 {symbol} {side}: {e}")
return None

View File

@ -252,14 +252,40 @@ class RiskManager:
position_value = available_balance * position_percent
logger.info(f" 计算仓位价值: {position_value:.2f} USDT ({position_percent*100:.1f}% of {available_balance:.2f})")
# 确保仓位价值满足最小名义价值要求币安要求至少5 USDT
min_notional = 5.0 # 币安合约最小名义价值
if position_value < min_notional:
logger.warning(f" ⚠ 仓位价值 {position_value:.2f} USDT < 最小名义价值 {min_notional:.2f} USDT")
# 尝试增加仓位价值到最小名义价值,但不超过最大仓位限制
max_allowed_value = available_balance * max_position_percent
if min_notional <= max_allowed_value:
position_value = min_notional
logger.info(f" ✓ 调整仓位价值到最小名义价值: {position_value:.2f} USDT")
else:
logger.warning(
f" ❌ 无法满足最小名义价值要求: "
f"需要 {min_notional:.2f} USDT但最大允许 {max_allowed_value:.2f} USDT"
)
return None
# 计算数量(考虑合约的最小数量精度)
quantity = position_value / current_price
logger.info(f" 计算数量: {quantity:.4f} (价值: {position_value:.2f} / 价格: {current_price:.4f})")
# 验证计算出的数量对应的名义价值
calculated_notional = quantity * current_price
if calculated_notional < min_notional:
# 如果计算出的名义价值仍然不足,增加数量
required_quantity = min_notional / current_price
logger.warning(f" ⚠ 计算出的名义价值 {calculated_notional:.2f} USDT < {min_notional:.2f} USDT")
logger.info(f" ✓ 调整数量从 {quantity:.4f}{required_quantity:.4f}")
quantity = required_quantity
position_value = required_quantity * current_price
# 检查是否通过风险控制
logger.info(f" 检查仓位大小是否符合风险控制要求...")
if await self.check_position_size(symbol, quantity):
logger.info(f"{symbol} 仓位计算成功: {quantity:.4f} (价值: {position_value:.2f} USDT)")
logger.info(f"{symbol} 仓位计算成功: {quantity:.4f} (价值: {position_value:.2f} USDT, 名义价值: {quantity * current_price:.2f} USDT)")
return quantity
else:
logger.warning(f"{symbol} 仓位检查未通过,无法开仓")