a
This commit is contained in:
parent
6c04202a55
commit
df634a8f02
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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} 仓位检查未通过,无法开仓")
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user