This commit is contained in:
薇薇安 2026-01-19 00:12:29 +08:00
parent 6bec109ce9
commit bec62631cb
2 changed files with 45 additions and 27 deletions

View File

@ -223,6 +223,16 @@ function Recommendations() {
}
}
const fmtPrice = (v) => {
const n = Number(v || 0)
if (!isFinite(n)) return '-'
// =
if (Math.abs(n) >= 100) return n.toFixed(2)
if (Math.abs(n) >= 1) return n.toFixed(4)
if (Math.abs(n) >= 0.01) return n.toFixed(6)
return n.toFixed(8)
}
const getStatusBadge = (status) => {
const statusMap = {
active: { text: '有效', class: 'status-active' },
@ -356,7 +366,7 @@ function Recommendations() {
<div className="price-item">
<label>当前价格:</label>
<span>
{parseFloat(rec.current_price || 0).toFixed(4)} USDT
{fmtPrice(rec.current_price)} USDT
{rec.current_price_source === 'mark_price' && (
<span
className="price-updated-badge"
@ -418,7 +428,7 @@ function Recommendations() {
<div className="param-item limit-price highlight">
<label>建议挂单价:</label>
<span className="limit-price-value highlight-price">
{parseFloat(rec.suggested_limit_price || 0).toFixed(4)} USDT
{fmtPrice(rec.suggested_limit_price)} USDT
{rec.current_price && (
<span className="price-diff">
({rec.direction === 'BUY' ? '低于' : '高于'}当前价
@ -430,15 +440,15 @@ function Recommendations() {
)}
<div className="param-item">
<label>建议止损:</label>
<span>{parseFloat(rec.suggested_stop_loss || 0).toFixed(4)}</span>
<span>{fmtPrice(rec.suggested_stop_loss)}</span>
</div>
<div className="param-item">
<label>第一目标:</label>
<span>{parseFloat(rec.suggested_take_profit_1 || 0).toFixed(4)}</span>
<span>{fmtPrice(rec.suggested_take_profit_1)}</span>
</div>
<div className="param-item">
<label>第二目标:</label>
<span>{parseFloat(rec.suggested_take_profit_2 || 0).toFixed(4)}</span>
<span>{fmtPrice(rec.suggested_take_profit_2)}</span>
</div>
<div className="param-item">
<label>建议仓位:</label>

View File

@ -331,18 +331,23 @@ class TradeRecommender:
signal_strength += 2
reasons.append("4H周期共振确认")
# 判断是否应该交易使用传入的参数如果没有则使用config中的值
# 推荐系统默认不再输出“逆4H趋势”的推荐用户反馈方向不对的主要来源
# 如果未来需要放开,可做成配置项 ALLOW_COUNTER_TREND_RECOMMENDATIONS。
if direction and trend_4h and trend_4h in ("up", "down"):
if (direction == 'BUY' and trend_4h == 'down') or (direction == 'SELL' and trend_4h == 'up'):
reasons.append("❌ 逆4H趋势跳过推荐")
return {
'should_trade': False,
'direction': direction,
'reason': ', '.join(reasons) if reasons else '逆趋势',
'strength': max(0, signal_strength - 2),
'trend_4h': trend_4h
}
# 判断是否应该推荐使用传入的参数如果没有则使用config中的值
if min_signal_strength is None:
min_signal_strength = config.TRADING_CONFIG.get('MIN_SIGNAL_STRENGTH', 7)
should_trade = signal_strength >= min_signal_strength
# 对于推荐系统允许逆4H趋势交易但降低信号强度标记为高风险
if direction and trend_4h:
if (direction == 'BUY' and trend_4h == 'down') or (direction == 'SELL' and trend_4h == 'up'):
# 推荐系统允许逆趋势但降低信号强度减2分
signal_strength = max(0, signal_strength - 2)
reasons.append("⚠️ 逆4H趋势高风险")
# 不禁止,但标记为高风险
should_trade = (direction is not None) and (signal_strength >= min_signal_strength)
return {
'should_trade': should_trade,
@ -395,10 +400,20 @@ class TradeRecommender:
price_ts_ms = None
direction = trade_signal['direction']
if not direction:
return None
# 计算建议的止损止盈(基于保证金)
entry_price = current_price
# 先计算建议挂单价(限价单),然后用“挂单价”作为止损/止盈的基准入场价
# 否则会出现:止损按 current_price 算、但挂单按回调价算 → 止损/挂单价不匹配,甚至相等
limit_price_offset_pct = config.TRADING_CONFIG.get('LIMIT_ORDER_OFFSET_PCT', 0.5) # 默认0.5%
if direction == 'BUY':
suggested_limit_price = current_price * (1 - limit_price_offset_pct / 100)
else: # SELL
suggested_limit_price = current_price * (1 + limit_price_offset_pct / 100)
# 计算建议的止损止盈(基于保证金),以“计划入场价=挂单价”为基准
entry_price = suggested_limit_price
# 估算仓位数量和杠杆(用于计算止损止盈)
# 重要语义suggested_position_pct 表示“保证金占用比例”
account_balance = symbol_info.get('account_balance', 1000)
@ -453,15 +468,6 @@ class TradeRecommender:
position_multiplier = min(1.0 + (signal_strength - 5) * 0.1, 1.5)
suggested_position_pct = base_position_pct * position_multiplier
# 计算建议的挂单价(使用限价单,而不是市价单)
# 对于做多建议价格略低于当前价格当前价格的99.5%),以便在回调时买入
# 对于做空建议价格略高于当前价格当前价格的100.5%),以便在反弹时卖出
limit_price_offset_pct = config.TRADING_CONFIG.get('LIMIT_ORDER_OFFSET_PCT', 0.5) # 默认0.5%
if direction == 'BUY':
suggested_limit_price = current_price * (1 - limit_price_offset_pct / 100)
else: # SELL
suggested_limit_price = current_price * (1 + limit_price_offset_pct / 100)
# 添加时间戳
timestamp = time.time()
recommendation_time = datetime.now().isoformat()
@ -533,6 +539,8 @@ class TradeRecommender:
'suggested_stop_loss': stop_loss_price,
'suggested_take_profit_1': take_profit_1,
'suggested_take_profit_2': take_profit_2,
# 计划入场价(限价挂单价)作为止损/止盈计算基准
'planned_entry_price': entry_price,
'suggested_position_percent': suggested_position_pct,
'suggested_leverage': config.TRADING_CONFIG.get('LEVERAGE', 10),
'volume_24h': symbol_info.get('volume24h'),