1
This commit is contained in:
parent
63e798f003
commit
a38f7cf09d
|
|
@ -966,6 +966,13 @@ class ConfigManager:
|
|||
'TREND_STATE_TTL_SEC': eff_get('TREND_STATE_TTL_SEC', 3600),
|
||||
'RECO_USE_TREND_ENTRY_FILTER': eff_get('RECO_USE_TREND_ENTRY_FILTER', True),
|
||||
'RECO_MAX_TREND_MOVE_BEFORE_ENTRY': eff_get('RECO_MAX_TREND_MOVE_BEFORE_ENTRY', 0.04),
|
||||
# 回撤/区间入场(前低前高)
|
||||
'ENTRY_PULLBACK_FILTER_ENABLED': eff_get('ENTRY_PULLBACK_FILTER_ENABLED', False),
|
||||
'ENTRY_PULLBACK_INTERVAL': eff_get('ENTRY_PULLBACK_INTERVAL', None),
|
||||
'ENTRY_PULLBACK_LOOKBACK_BARS': eff_get('ENTRY_PULLBACK_LOOKBACK_BARS', 24),
|
||||
'ENTRY_PULLBACK_MIN_BARS': eff_get('ENTRY_PULLBACK_MIN_BARS', 5),
|
||||
'ENTRY_PULLBACK_MAX_LONG_IN_RANGE': eff_get('ENTRY_PULLBACK_MAX_LONG_IN_RANGE', 0.62),
|
||||
'ENTRY_PULLBACK_MIN_SHORT_IN_RANGE': eff_get('ENTRY_PULLBACK_MIN_SHORT_IN_RANGE', 0.38),
|
||||
|
||||
# 当前交易预设(让 trading_system 能知道是哪种模式)
|
||||
'TRADING_PROFILE': profile,
|
||||
|
|
|
|||
|
|
@ -363,6 +363,16 @@ DEFAULT_TRADING_CONFIG = {
|
|||
# 推荐系统使用的最大允许趋势幅度(相对于趋势信号价),默认与自动交易相同或略微更严格
|
||||
'RECO_MAX_TREND_MOVE_BEFORE_ENTRY': 0.04,
|
||||
|
||||
# ===== 回撤/区间入场过滤(参考近N根K线前低、前高,减少买在区间顶部、卖在区间底部)=====
|
||||
# 与 USE_TREND_ENTRY_FILTER(相对「信号价」的追价幅度)互补:本组用 K 线区间衡量是否已跑到局部极值附近。
|
||||
'ENTRY_PULLBACK_FILTER_ENABLED': False, # True 启用;建议先 True 观察日志中 [回撤过滤] 跳过比例再调阈值
|
||||
'ENTRY_PULLBACK_INTERVAL': None, # None=沿用 ENTRY_INTERVAL(默认1h);可改为 '15m' 等更敏感周期
|
||||
'ENTRY_PULLBACK_LOOKBACK_BARS': 24, # 统计区间用的 K 线根数(需 >= MIN_BARS)
|
||||
'ENTRY_PULLBACK_MIN_BARS': 5, # 至少多少根有效 K 才启用过滤,不足则跳过本过滤
|
||||
# 现价在 [区间低,区间高] 中的相对位置 pos∈[0,1]:0=贴前低,1=贴前高
|
||||
'ENTRY_PULLBACK_MAX_LONG_IN_RANGE': 0.62, # 做多:pos 超过此值则不开(默认拒绝最上约 38% 区域)
|
||||
'ENTRY_PULLBACK_MIN_SHORT_IN_RANGE': 0.38, # 做空:pos 低于此值则不开(默认拒绝最下约 38% 区域)
|
||||
|
||||
# ===== 智能入场(方案C)=====
|
||||
# 根治方案:默认关闭。关闭后回归“纯限价单模式”(不追价/不市价兜底/未成交撤单跳过)
|
||||
'SMART_ENTRY_ENABLED': True, # 开启智能入场,提高成交率
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import random
|
|||
import time
|
||||
import aiohttp
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
from datetime import datetime
|
||||
try:
|
||||
from .binance_client import BinanceClient, AlgoOrderPositionUnavailableError
|
||||
|
|
@ -149,6 +149,46 @@ except Exception:
|
|||
get_balance_from_cache = lambda: None
|
||||
|
||||
|
||||
def _pullback_range_metrics_from_klines(
|
||||
klines: Optional[List],
|
||||
current_price: float,
|
||||
) -> Optional[Tuple[float, float, float]]:
|
||||
"""
|
||||
用近若干根 K 线的最高价/最低价构成区间,衡量当前价在区间内的相对位置。
|
||||
|
||||
返回 (recent_low, recent_high, position_01),其中 position_01∈[0,1]:
|
||||
- 0 表示贴在区间下沿(接近「前低」一侧)
|
||||
- 1 表示贴在区间上沿(接近「前高」一侧)
|
||||
|
||||
多单若 position_01 过大,说明价格已跑到区间顶部,容易「一回撤就扫损」;
|
||||
空单若 position_01 过小,同理接近区间下沿追空风险大。
|
||||
"""
|
||||
if not klines or current_price is None:
|
||||
return None
|
||||
try:
|
||||
cur = float(current_price)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
if cur <= 0:
|
||||
return None
|
||||
highs: List[float] = []
|
||||
lows: List[float] = []
|
||||
for k in klines:
|
||||
try:
|
||||
highs.append(float(k[2]))
|
||||
lows.append(float(k[3]))
|
||||
except (IndexError, TypeError, ValueError):
|
||||
continue
|
||||
if len(highs) < 2:
|
||||
return None
|
||||
hi = max(highs)
|
||||
lo = min(lows)
|
||||
if hi <= lo:
|
||||
return None
|
||||
pos = (cur - lo) / (hi - lo)
|
||||
return (lo, hi, pos)
|
||||
|
||||
|
||||
class PositionManager:
|
||||
"""仓位管理类"""
|
||||
|
||||
|
|
@ -424,6 +464,59 @@ class PositionManager:
|
|||
return None
|
||||
except Exception as e:
|
||||
logger.debug(f"{symbol} 趋势入场过滤时出错(忽略,按正常逻辑继续): {e}")
|
||||
|
||||
# ===== 回撤/区间入场过滤(参考近 N 根 K 线的前低/前高,避免买在区间顶部、卖在区间底部)=====
|
||||
try:
|
||||
pb_enabled = bool(config.TRADING_CONFIG.get("ENTRY_PULLBACK_FILTER_ENABLED", False))
|
||||
if pb_enabled:
|
||||
min_bars = max(3, int(config.TRADING_CONFIG.get("ENTRY_PULLBACK_MIN_BARS", 5) or 5))
|
||||
lookback = max(min_bars, int(config.TRADING_CONFIG.get("ENTRY_PULLBACK_LOOKBACK_BARS", 24) or 24))
|
||||
interval_pb = config.TRADING_CONFIG.get("ENTRY_PULLBACK_INTERVAL") or config.TRADING_CONFIG.get(
|
||||
"ENTRY_INTERVAL", "1h"
|
||||
)
|
||||
max_long_pos = float(config.TRADING_CONFIG.get("ENTRY_PULLBACK_MAX_LONG_IN_RANGE", 0.62) or 0.62)
|
||||
min_short_pos = float(config.TRADING_CONFIG.get("ENTRY_PULLBACK_MIN_SHORT_IN_RANGE", 0.38) or 0.38)
|
||||
max_long_pos = min(1.0, max(0.0, max_long_pos))
|
||||
min_short_pos = min(1.0, max(0.0, min_short_pos))
|
||||
if min_short_pos > max_long_pos:
|
||||
min_short_pos, max_long_pos = max_long_pos, min_short_pos
|
||||
|
||||
rt = None
|
||||
try:
|
||||
rt = self.client.get_realtime_price(symbol)
|
||||
except Exception:
|
||||
rt = None
|
||||
cur_pb = float(rt or estimated_entry_price)
|
||||
|
||||
bars_pb = klines if klines and len(klines) >= min_bars else None
|
||||
if not bars_pb:
|
||||
try:
|
||||
fetched = await self.client.get_klines(
|
||||
symbol=symbol, interval=str(interval_pb), limit=lookback
|
||||
)
|
||||
bars_pb = fetched if fetched and len(fetched) >= min_bars else None
|
||||
except Exception as e:
|
||||
logger.debug(f"{symbol} 回撤过滤拉取K线失败(跳过该过滤): {e}")
|
||||
bars_pb = None
|
||||
|
||||
metrics = _pullback_range_metrics_from_klines(bars_pb, cur_pb)
|
||||
if metrics is not None:
|
||||
lo_pb, hi_pb, pos_pb = metrics
|
||||
es = estimated_side.upper()
|
||||
if es == "BUY" and pos_pb > max_long_pos:
|
||||
logger.info(
|
||||
f"{symbol} [回撤过滤] 做多跳过:现价={cur_pb:.6f} 在近{len(bars_pb)}根{interval_pb}区间"
|
||||
f"[{lo_pb:.6f},{hi_pb:.6f}] 中位置={pos_pb:.2f} > 上限{max_long_pos:.2f}(接近区间上沿/前高,易回撤扫损)"
|
||||
)
|
||||
return None
|
||||
if es == "SELL" and pos_pb < min_short_pos:
|
||||
logger.info(
|
||||
f"{symbol} [回撤过滤] 做空跳过:现价={cur_pb:.6f} 在近{len(bars_pb)}根{interval_pb}区间"
|
||||
f"[{lo_pb:.6f},{hi_pb:.6f}] 中位置={pos_pb:.2f} < 下限{min_short_pos:.2f}(接近区间下沿/前低,易反弹扫损)"
|
||||
)
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.debug(f"{symbol} 回撤/区间入场过滤异常(忽略,继续开仓流程): {e}")
|
||||
|
||||
# 估算止损价格(用于固定风险计算)
|
||||
estimated_stop_loss = None
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user