This commit is contained in:
薇薇安 2026-01-17 19:18:09 +08:00
parent 3dc037599b
commit c778afdcb6
3 changed files with 89 additions and 43 deletions

View File

@ -75,23 +75,56 @@ async def check_config_feasibility():
required_position_value = min_margin_usdt * leverage required_position_value = min_margin_usdt * leverage
required_position_percent = required_position_value / available_balance if available_balance > 0 else 0 required_position_percent = required_position_value / available_balance if available_balance > 0 else 0
# 检查是否可行 # 计算使用最小仓位百分比时,实际能得到的保证金
is_feasible = required_position_percent <= max_position_percent min_position_value = available_balance * min_position_percent
actual_min_margin = min_position_value / leverage if leverage > 0 else min_position_value
# 检查是否可行:
# 1. 需要的仓位百分比不能超过最大允许的仓位百分比
# 2. 使用最小仓位百分比时,实际保证金必须 >= 最小保证金要求
is_feasible = (required_position_percent <= max_position_percent) and (actual_min_margin >= min_margin_usdt)
suggestions = [] suggestions = []
if not is_feasible: if not is_feasible:
# 不可行,给出建议 # 不可行,给出建议
# 方案1降低最小保证金 # 判断是哪个条件不满足
suggested_min_margin = (available_balance * max_position_percent) / leverage if required_position_percent > max_position_percent:
suggestions.append({ # 条件1不满足需要的仓位百分比超过最大允许
"type": "reduce_min_margin", # 方案1降低最小保证金
"title": "降低最小保证金", suggested_min_margin = (available_balance * max_position_percent) / leverage
"description": f"将 MIN_MARGIN_USDT 调整为 {suggested_min_margin:.2f} USDT当前: {min_margin_usdt:.2f} USDT", suggestions.append({
"config_key": "MIN_MARGIN_USDT", "type": "reduce_min_margin",
"suggested_value": round(suggested_min_margin, 2), "title": "降低最小保证金",
"reason": f"当前配置需要 {required_position_percent*100:.1f}% 的仓位价值,但最大允许 {max_position_percent*100:.1f}%" "description": f"将 MIN_MARGIN_USDT 调整为 {suggested_min_margin:.2f} USDT当前: {min_margin_usdt:.2f} USDT",
}) "config_key": "MIN_MARGIN_USDT",
"suggested_value": round(suggested_min_margin, 2),
"reason": f"当前配置需要 {required_position_percent*100:.1f}% 的仓位价值,但最大允许 {max_position_percent*100:.1f}%"
})
if actual_min_margin < min_margin_usdt:
# 条件2不满足使用最小仓位时实际保证金不足
# 方案1降低最小保证金到实际能支持的值
suggestions.append({
"type": "reduce_min_margin_to_supported",
"title": "降低最小保证金到可支持值",
"description": f"将 MIN_MARGIN_USDT 调整为 {actual_min_margin:.2f} USDT当前: {min_margin_usdt:.2f} USDT实际只支持 {actual_min_margin:.2f} USDT",
"config_key": "MIN_MARGIN_USDT",
"suggested_value": round(actual_min_margin, 2),
"reason": f"当前账户余额和配置下,使用最小仓位 {min_position_percent*100:.1f}% 时,实际保证金只有 {actual_min_margin:.2f} USDT无法满足 {min_margin_usdt:.2f} USDT 的要求"
})
# 方案2提高最小仓位百分比
required_min_position_percent = (min_margin_usdt * leverage) / available_balance if available_balance > 0 else 0
if required_min_position_percent <= max_position_percent:
suggestions.append({
"type": "increase_min_position",
"title": "提高最小仓位百分比",
"description": f"将 MIN_POSITION_PERCENT 调整为 {required_min_position_percent*100:.2f}%(当前: {min_position_percent*100:.1f}%",
"config_key": "MIN_POSITION_PERCENT",
"suggested_value": round(required_min_position_percent, 4),
"reason": f"需要至少 {required_min_position_percent*100:.2f}% 的仓位才能满足 {min_margin_usdt:.2f} USDT 的保证金要求"
})
# 方案2增加账户余额 # 方案2增加账户余额
required_balance = required_position_value / max_position_percent required_balance = required_position_value / max_position_percent
@ -141,7 +174,10 @@ async def check_config_feasibility():
"calculated_values": { "calculated_values": {
"required_position_value": required_position_value, "required_position_value": required_position_value,
"required_position_percent": required_position_percent * 100, "required_position_percent": required_position_percent * 100,
"max_allowed_position_percent": max_position_percent * 100 "max_allowed_position_percent": max_position_percent * 100,
"min_position_value": min_position_value,
"actual_min_margin": actual_min_margin,
"min_position_percent": min_position_percent * 100
}, },
"suggestions": suggestions "suggestions": suggestions
} }

View File

@ -301,10 +301,19 @@ const ConfigPanel = () => {
最小保证金: <strong>{feasibilityCheck.current_config?.min_margin_usdt?.toFixed(2) || 'N/A'}</strong> USDT 最小保证金: <strong>{feasibilityCheck.current_config?.min_margin_usdt?.toFixed(2) || 'N/A'}</strong> USDT
</p> </p>
{!feasibilityCheck.feasible && ( {!feasibilityCheck.feasible && (
<p className="warning-text"> <div className="warning-text">
需要仓位价值: <strong>{feasibilityCheck.calculated_values?.required_position_percent?.toFixed(1)}%</strong> | <p>
最大允许: <strong>{feasibilityCheck.calculated_values?.max_allowed_position_percent?.toFixed(1)}%</strong> 需要仓位价值: <strong>{feasibilityCheck.calculated_values?.required_position_percent?.toFixed(1)}%</strong> |
</p> 最大允许: <strong>{feasibilityCheck.calculated_values?.max_allowed_position_percent?.toFixed(1)}%</strong>
</p>
{feasibilityCheck.calculated_values?.actual_min_margin !== undefined && (
<p>
实际支持保证金: <strong>{feasibilityCheck.calculated_values.actual_min_margin.toFixed(2)} USDT</strong>
(使用最小仓位 {feasibilityCheck.calculated_values.min_position_percent?.toFixed(1)}%) |
要求: <strong>{feasibilityCheck.current_config?.min_margin_usdt?.toFixed(2)} USDT</strong>
</p>
)}
</div>
)} )}
</div> </div>
{feasibilityCheck.suggestions && feasibilityCheck.suggestions.length > 0 && ( {feasibilityCheck.suggestions && feasibilityCheck.suggestions.length > 0 && (

View File

@ -24,7 +24,8 @@ class RiskManager:
client: 币安客户端 client: 币安客户端
""" """
self.client = client self.client = client
self.config = config.TRADING_CONFIG # 不保存引用,每次都从 config.TRADING_CONFIG 读取最新配置
# self.config = config.TRADING_CONFIG # 移除,避免使用旧配置
async def check_position_size(self, symbol: str, quantity: float) -> bool: async def check_position_size(self, symbol: str, quantity: float) -> bool:
""" """
@ -57,11 +58,11 @@ class RiskManager:
current_price = ticker['price'] current_price = ticker['price']
position_value = quantity * current_price position_value = quantity * current_price
# 检查单笔仓位是否超过最大限制 # 检查单笔仓位是否超过最大限制(每次都从最新配置读取)
max_position_value = available_balance * self.config['MAX_POSITION_PERCENT'] max_position_value = available_balance * config.TRADING_CONFIG['MAX_POSITION_PERCENT']
min_position_value = available_balance * self.config['MIN_POSITION_PERCENT'] min_position_value = available_balance * config.TRADING_CONFIG['MIN_POSITION_PERCENT']
max_position_pct = self.config['MAX_POSITION_PERCENT'] * 100 max_position_pct = config.TRADING_CONFIG['MAX_POSITION_PERCENT'] * 100
min_position_pct = self.config['MIN_POSITION_PERCENT'] * 100 min_position_pct = config.TRADING_CONFIG['MIN_POSITION_PERCENT'] * 100
logger.info(f" 数量: {quantity:.4f}") logger.info(f" 数量: {quantity:.4f}")
logger.info(f" 价格: {current_price:.4f} USDT") logger.info(f" 价格: {current_price:.4f} USDT")
@ -150,8 +151,8 @@ class RiskManager:
logger.warning("账户总余额为0无法开仓") logger.warning("账户总余额为0无法开仓")
return False return False
max_total_position = total_balance * self.config['MAX_TOTAL_POSITION_PERCENT'] max_total_position = total_balance * config.TRADING_CONFIG['MAX_TOTAL_POSITION_PERCENT']
max_total_position_pct = self.config['MAX_TOTAL_POSITION_PERCENT'] * 100 max_total_position_pct = config.TRADING_CONFIG['MAX_TOTAL_POSITION_PERCENT'] * 100
# 详细日志 # 详细日志
logger.info("=" * 60) logger.info("=" * 60)
@ -243,9 +244,9 @@ class RiskManager:
logger.info(f" 当前价格: {current_price:.4f} USDT") logger.info(f" 当前价格: {current_price:.4f} USDT")
# 根据涨跌幅调整仓位大小(涨跌幅越大,仓位可以适当增加) # 根据涨跌幅调整仓位大小(涨跌幅越大,仓位可以适当增加)
base_position_percent = self.config['MAX_POSITION_PERCENT'] base_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT']
max_position_percent = self.config['MAX_POSITION_PERCENT'] max_position_percent = config.TRADING_CONFIG['MAX_POSITION_PERCENT']
min_position_percent = self.config['MIN_POSITION_PERCENT'] min_position_percent = config.TRADING_CONFIG['MIN_POSITION_PERCENT']
# 涨跌幅超过5%时可以适当增加仓位但不超过1.5倍) # 涨跌幅超过5%时可以适当增加仓位但不超过1.5倍)
if abs(change_percent) > 5: if abs(change_percent) > 5:
@ -303,9 +304,9 @@ class RiskManager:
position_value = required_quantity * current_price position_value = required_quantity * current_price
# 检查最小保证金要求如果保证金小于此值自动调整到0.5U保证金) # 检查最小保证金要求如果保证金小于此值自动调整到0.5U保证金)
min_margin_usdt = self.config.get('MIN_MARGIN_USDT', 0.5) # 默认0.5 USDT min_margin_usdt = config.TRADING_CONFIG.get('MIN_MARGIN_USDT', 0.5) # 默认0.5 USDT
# 使用传入的实际杠杆,如果没有传入则使用配置的基础杠杆 # 使用传入的实际杠杆,如果没有传入则使用配置的基础杠杆
actual_leverage = leverage if leverage is not None else self.config.get('LEVERAGE', 10) actual_leverage = leverage if leverage is not None else config.TRADING_CONFIG.get('LEVERAGE', 10)
# 计算实际需要的保证金 = 仓位价值 / 杠杆 # 计算实际需要的保证金 = 仓位价值 / 杠杆
required_margin = position_value / actual_leverage required_margin = position_value / actual_leverage
@ -378,7 +379,7 @@ class RiskManager:
是否应该交易 是否应该交易
""" """
# 检查最小涨跌幅阈值 # 检查最小涨跌幅阈值
if abs(change_percent) < self.config['MIN_CHANGE_PERCENT']: if abs(change_percent) < config.TRADING_CONFIG['MIN_CHANGE_PERCENT']:
logger.debug(f"{symbol} 涨跌幅 {change_percent:.2f}% 小于阈值") logger.debug(f"{symbol} 涨跌幅 {change_percent:.2f}% 小于阈值")
return False return False
@ -427,8 +428,8 @@ class RiskManager:
margin = position_value / leverage if leverage > 0 else position_value margin = position_value / leverage if leverage > 0 else position_value
# 优先使用ATR动态止损如果启用且ATR可用 # 优先使用ATR动态止损如果启用且ATR可用
use_atr_stop = self.config.get('USE_ATR_STOP_LOSS', True) use_atr_stop = config.TRADING_CONFIG.get('USE_ATR_STOP_LOSS', True)
atr_multiplier = self.config.get('ATR_STOP_LOSS_MULTIPLIER', 1.8) atr_multiplier = config.TRADING_CONFIG.get('ATR_STOP_LOSS_MULTIPLIER', 1.8)
if use_atr_stop and atr is not None and atr > 0: if use_atr_stop and atr is not None and atr > 0:
# 基于ATR的动态止损 # 基于ATR的动态止损
@ -449,7 +450,7 @@ class RiskManager:
logger.debug(f"ATR不可用使用固定百分比止损") logger.debug(f"ATR不可用使用固定百分比止损")
# 获取止损百分比(相对于保证金) # 获取止损百分比(相对于保证金)
stop_loss_percent = stop_loss_pct or self.config['STOP_LOSS_PERCENT'] stop_loss_percent = stop_loss_pct or config.TRADING_CONFIG['STOP_LOSS_PERCENT']
# 计算止损金额(相对于保证金) # 计算止损金额(相对于保证金)
stop_loss_amount = margin * stop_loss_percent stop_loss_amount = margin * stop_loss_percent
@ -464,7 +465,7 @@ class RiskManager:
# 同时计算基于价格百分比的止损价(作为最小值保护) # 同时计算基于价格百分比的止损价(作为最小值保护)
# 获取最小价格变动百分比(如果配置了) # 获取最小价格变动百分比(如果配置了)
min_price_change_pct = self.config.get('MIN_STOP_LOSS_PRICE_PCT', None) min_price_change_pct = config.TRADING_CONFIG.get('MIN_STOP_LOSS_PRICE_PCT', None)
if min_price_change_pct is not None: if min_price_change_pct is not None:
# 基于价格百分比的止损价 # 基于价格百分比的止损价
if side == 'BUY': if side == 'BUY':
@ -584,8 +585,8 @@ class RiskManager:
margin = position_value / leverage if leverage > 0 else position_value margin = position_value / leverage if leverage > 0 else position_value
# 优先使用ATR动态止盈如果启用且ATR可用 # 优先使用ATR动态止盈如果启用且ATR可用
use_atr_stop = self.config.get('USE_ATR_STOP_LOSS', True) use_atr_stop = config.TRADING_CONFIG.get('USE_ATR_STOP_LOSS', True)
atr_tp_multiplier = self.config.get('ATR_TAKE_PROFIT_MULTIPLIER', 3.0) atr_tp_multiplier = config.TRADING_CONFIG.get('ATR_TAKE_PROFIT_MULTIPLIER', 3.0)
if use_atr_stop and atr is not None and atr > 0: if use_atr_stop and atr is not None and atr > 0:
# 基于ATR的动态止盈对应3:1盈亏比 # 基于ATR的动态止盈对应3:1盈亏比
@ -606,7 +607,7 @@ class RiskManager:
logger.debug(f"ATR不可用使用固定百分比止盈") logger.debug(f"ATR不可用使用固定百分比止盈")
# 获取止盈百分比(相对于保证金) # 获取止盈百分比(相对于保证金)
take_profit_percent = take_profit_pct or self.config['TAKE_PROFIT_PERCENT'] take_profit_percent = take_profit_pct or config.TRADING_CONFIG['TAKE_PROFIT_PERCENT']
# 计算止盈金额(相对于保证金) # 计算止盈金额(相对于保证金)
take_profit_amount = margin * take_profit_percent take_profit_amount = margin * take_profit_percent
@ -621,7 +622,7 @@ class RiskManager:
# 同时计算基于价格百分比的止盈价(作为最小值保护) # 同时计算基于价格百分比的止盈价(作为最小值保护)
# 获取最小价格变动百分比(如果配置了) # 获取最小价格变动百分比(如果配置了)
min_price_change_pct = self.config.get('MIN_TAKE_PROFIT_PRICE_PCT', None) min_price_change_pct = config.TRADING_CONFIG.get('MIN_TAKE_PROFIT_PRICE_PCT', None)
if min_price_change_pct is not None: if min_price_change_pct is not None:
# 基于价格百分比的止盈价 # 基于价格百分比的止盈价
if side == 'BUY': if side == 'BUY':
@ -671,10 +672,10 @@ class RiskManager:
杠杆倍数 杠杆倍数
""" """
# 获取配置参数 # 获取配置参数
use_dynamic_leverage = self.config.get('USE_DYNAMIC_LEVERAGE', True) use_dynamic_leverage = config.TRADING_CONFIG.get('USE_DYNAMIC_LEVERAGE', True)
base_leverage = self.config.get('LEVERAGE', 10) base_leverage = config.TRADING_CONFIG.get('LEVERAGE', 10)
max_leverage = self.config.get('MAX_LEVERAGE', 20) max_leverage = config.TRADING_CONFIG.get('MAX_LEVERAGE', 20)
min_signal_strength = self.config.get('MIN_SIGNAL_STRENGTH', 7) min_signal_strength = config.TRADING_CONFIG.get('MIN_SIGNAL_STRENGTH', 7)
# 如果未启用动态杠杆,返回基础杠杆 # 如果未启用动态杠杆,返回基础杠杆
if not use_dynamic_leverage: if not use_dynamic_leverage: