feat(config): 添加市场状态方案以优化交易策略

在配置管理中引入市场状态方案,允许在不同市场条件下快速切换策略(如熊市、牛市、正常、保守)。更新相关参数以自动覆盖止损、仓位和趋势过滤设置,增强策略灵活性。同时,前端组件更新以支持市场状态方案的展示与选择,提升用户体验。
This commit is contained in:
薇薇安 2026-02-22 19:15:05 +08:00
parent 3b0526f392
commit 452e40bdf5
7 changed files with 555 additions and 2 deletions

View File

@ -814,7 +814,7 @@ class ConfigManager:
short_filter_default = False if is_fast else True
max_trend_move_default = 0.08 if is_fast else 0.05
return {
result = {
# 仓位控制
'MAX_POSITION_PERCENT': eff_get('MAX_POSITION_PERCENT', 0.12), # 单笔最大保证金占比12%,加大单笔盈利空间)
'MAX_TOTAL_POSITION_PERCENT': eff_get('MAX_TOTAL_POSITION_PERCENT', 0.40), # 总保证金占比上限
@ -947,8 +947,47 @@ class ConfigManager:
'SYMBOL_LOSS_COOLDOWN_SEC': eff_get('SYMBOL_LOSS_COOLDOWN_SEC', 3600),
# 第一目标止盈最小盈亏比(相对止损距离)
'MIN_RR_FOR_TP1': eff_get('MIN_RR_FOR_TP1', 1.5), # 2026-02-12保证 TP1 至少 1.5 倍止损距离,改善盈亏比
# 市场状态方案(便于在不同行情间切换)
'MARKET_SCHEME': str(eff_get('MARKET_SCHEME', 'normal') or 'normal').lower(),
'BLOCK_LONG_WHEN_4H_DOWN': eff_get('BLOCK_LONG_WHEN_4H_DOWN', False), # 4H 下跌时禁止开多(熊市/保守用)
}
# 根据市场方案覆盖关键参数(便于快速切换熊市/牛市/保守等预设)
_SCHEME_PRESETS = {
'normal': {
'MIN_STOP_LOSS_PRICE_PCT': 0.03,
'MAX_POSITION_PERCENT': 0.12,
'ATR_STOP_LOSS_MULTIPLIER': 2.5,
'BLOCK_LONG_WHEN_4H_DOWN': False,
},
'bear': {
'MIN_STOP_LOSS_PRICE_PCT': 0.05, # 放宽止损约 -5%
'MAX_POSITION_PERCENT': 0.08, # 单仓 ≤ 8%
'ATR_STOP_LOSS_MULTIPLIER': 2.5,
'BLOCK_LONG_WHEN_4H_DOWN': True, # 4H 下跌不开多
'BETA_FILTER_ENABLED': True,
},
'bull': {
'MIN_STOP_LOSS_PRICE_PCT': 0.03,
'MAX_POSITION_PERCENT': 0.12,
'ATR_STOP_LOSS_MULTIPLIER': 2.0,
'BLOCK_LONG_WHEN_4H_DOWN': False,
},
'conservative': {
'MIN_STOP_LOSS_PRICE_PCT': 0.06, # 最宽松止损
'MAX_POSITION_PERCENT': 0.06, # 最小仓位
'ATR_STOP_LOSS_MULTIPLIER': 2.5,
'BLOCK_LONG_WHEN_4H_DOWN': True,
'BETA_FILTER_ENABLED': True,
},
}
scheme = result.get('MARKET_SCHEME', 'normal') or 'normal'
if scheme in _SCHEME_PRESETS:
for k, v in _SCHEME_PRESETS[scheme].items():
result[k] = v
return result
def _sync_to_redis(self):
"""将配置同步到Redis缓存账号维度"""
if not self._redis_connected or not self._redis_client:

View File

@ -57,6 +57,13 @@ DEFAULTS_TO_SYNC = [
"description": "止盈按保证金封顶,避免过远"},
{"config_key": "USE_MARGIN_CAP_FOR_SL", "config_value": "true", "config_type": "boolean", "category": "risk",
"description": "止损按保证金封顶,避免扛单"},
# 市场状态方案2026-02 三项优化 + 方案切换)
{"config_key": "MARKET_SCHEME", "config_value": "normal", "config_type": "string", "category": "strategy",
"description": "市场方案normal / bear / bull / conservative。切换后自动覆盖止损、仓位、趋势过滤等参数。"},
{"config_key": "BLOCK_LONG_WHEN_4H_DOWN", "config_value": "false", "config_type": "boolean", "category": "strategy",
"description": "4H 趋势下跌时禁止开多。bear / conservative 方案下自动为 true。"},
{"config_key": "AUTO_MARKET_SCHEME_ENABLED", "config_value": "false", "config_type": "boolean", "category": "strategy",
"description": "开启后crontab 定时运行 scripts/update_market_scheme.py --apply 时自动更新 MARKET_SCHEME根据 BTC 行情识别牛/熊/正常)。"},
]

View File

@ -381,6 +381,57 @@ const GlobalConfig = () => {
FIXED_RISK_PERCENT: 0.01, // 1%
},
},
// 便///
scheme_bear: {
name: '熊市',
desc: '【熊市专用】放宽止损5%、单仓≤8%、4H下跌禁止开多、大盘过滤开启。避免逆势抄底、减少回撤。',
signatureKeys: ['MARKET_SCHEME'],
configs: {
MARKET_SCHEME: 'bear',
MIN_STOP_LOSS_PRICE_PCT: 0.05,
MAX_POSITION_PERCENT: 0.08,
ATR_STOP_LOSS_MULTIPLIER: 2.5,
BLOCK_LONG_WHEN_4H_DOWN: true,
BETA_FILTER_ENABLED: true,
},
},
scheme_normal: {
name: '正常',
desc: '【常规市场】止损3%、单仓12%、4H下跌可开多。适合震荡或温和行情。',
signatureKeys: ['MARKET_SCHEME'],
configs: {
MARKET_SCHEME: 'normal',
MIN_STOP_LOSS_PRICE_PCT: 0.03,
MAX_POSITION_PERCENT: 0.12,
ATR_STOP_LOSS_MULTIPLIER: 2.5,
BLOCK_LONG_WHEN_4H_DOWN: false,
},
},
scheme_bull: {
name: '牛市',
desc: '【牛市专用】止损3%、单仓12%、4H下跌可开多、ATR倍数略低。偏积极。',
signatureKeys: ['MARKET_SCHEME'],
configs: {
MARKET_SCHEME: 'bull',
MIN_STOP_LOSS_PRICE_PCT: 0.03,
MAX_POSITION_PERCENT: 0.12,
ATR_STOP_LOSS_MULTIPLIER: 2.0,
BLOCK_LONG_WHEN_4H_DOWN: false,
},
},
scheme_conservative: {
name: '保守',
desc: '【极保守】止损6%、单仓6%、4H下跌禁止开多。最小仓位、最严趋势过滤。',
signatureKeys: ['MARKET_SCHEME'],
configs: {
MARKET_SCHEME: 'conservative',
MIN_STOP_LOSS_PRICE_PCT: 0.06,
MAX_POSITION_PERCENT: 0.06,
ATR_STOP_LOSS_MULTIPLIER: 2.5,
BLOCK_LONG_WHEN_4H_DOWN: true,
BETA_FILTER_ENABLED: true,
},
},
aggressive: {
name: '激进短线(高风险)',
desc: '针对晚间高波动2%风险/单,交易频率高,止损较紧但止盈合理。注意:回撤风险较高。',
@ -445,6 +496,9 @@ const GlobalConfig = () => {
SYNC_RECOVER_MISSING_POSITIONS: { value: true, type: 'boolean', category: 'position', description: '同步时补建「币安有仓、DB 无记录」的交易记录。' },
SYNC_RECOVER_ONLY_WHEN_HAS_SLTP: { value: true, type: 'boolean', category: 'position', description: '仅当该持仓存在止损/止盈单时才补建(未配置 SYSTEM_ORDER_ID_PREFIX 时生效)。' },
SYSTEM_ORDER_ID_PREFIX: { value: 'SYS', type: 'string', category: 'position', description: '系统单标识:下单时写入 newClientOrderId 前缀,同步时仅对「开仓订单 clientOrderId 以此前缀开头」的持仓补建;设空则用「是否有止损止盈单」判断。' },
MARKET_SCHEME: { value: 'normal', type: 'string', category: 'strategy', description: '市场方案normal / bear / bull / conservative。切换后自动覆盖止损、仓位、4H趋势过滤等参数。' },
BLOCK_LONG_WHEN_4H_DOWN: { value: false, type: 'boolean', category: 'strategy', description: '4H 趋势下跌时禁止开多。bear / conservative 方案下自动为 true。' },
AUTO_MARKET_SCHEME_ENABLED: { value: false, type: 'boolean', category: 'strategy', description: '开启后crontab 定时运行 update_market_scheme.py --apply 时自动更新 MARKET_SCHEME根据 BTC 行情识别牛/熊/正常)。' },
}
const loadConfigs = async () => {
@ -967,9 +1021,13 @@ const GlobalConfig = () => {
swing: { group: 'backup', tag: '纯限价' },
strict: { group: 'backup', tag: '精选低频' },
conservative: { group: 'backup', tag: '保守' },
scheme_bear: { group: 'scheme', tag: '熊市' },
scheme_normal: { group: 'scheme', tag: '正常' },
scheme_bull: { group: 'scheme', tag: '牛市' },
scheme_conservative: { group: 'scheme', tag: '保守' },
}
// //+
// //+ +
const presetGroups = [
{
key: 'altcoin',
@ -983,6 +1041,12 @@ const GlobalConfig = () => {
desc: '需要更少出单或纯限价时可选:波段回归、精选低频、保守传统。',
presetKeys: ['swing', 'strict', 'conservative'],
},
{
key: 'scheme',
title: '市场状态方案',
desc: '按当前行情切换熊市放宽止损、降仓、4H 下跌不开多)→ 正常 → 牛市 → 保守(最小仓位、最严过滤)。',
presetKeys: ['scheme_bear', 'scheme_normal', 'scheme_bull', 'scheme_conservative'],
},
]

View File

@ -0,0 +1,62 @@
# 市场行情自动识别与 MARKET_SCHEME 更新
## 1. 功能说明
`update_market_scheme.py` 基于 Binance 公开 API 自动识别当前市场行情(牛/熊/正常),并可选更新全局配置 `MARKET_SCHEME`从而自动切换止损、仓位、4H 趋势过滤等参数。
**数据来源(无需 API Key**
- 24h 涨跌幅:`/fapi/v1/ticker/24hr`
- 资金费率:`/fapi/v1/premiumIndex`
- 大户多空比:`/futures/data/topLongShortPositionRatio`
- 4H K 线:`/fapi/v1/klines`(计算 trend_4h
**打分规则:**
| 指标 | 偏多 (+1) | 偏空 (-1) |
|--------------|-------------|--------------|
| 24h 涨跌幅 | ≥ 2% | ≤ -2% |
| 4H 趋势 | up | down |
| 资金费率 | ≥ 0.00005 | ≤ -0.00005 |
| 大户多空比 | ≥ 1.1 | ≤ 0.9 |
总分 ≥ 2 → bull≤ -2 → bear否则 normal。
## 2. 使用方式
```bash
# 仅检测并打印(不更新 DB
python scripts/update_market_scheme.py
# 若开启 AUTO_MARKET_SCHEME_ENABLED则更新 DB
python scripts/update_market_scheme.py --apply
# 强制更新(忽略 AUTO_MARKET_SCHEME_ENABLED 开关)
python scripts/update_market_scheme.py --apply --force
```
## 3. 启用自动更新
1. 在「全局配置」中设置 `AUTO_MARKET_SCHEME_ENABLED``true`
2. 或执行一次同步默认配置:`cd backend && python sync_global_config_defaults.py`,然后在全局配置页手动改为 true
3. 配置 crontab 定时执行 `update_market_scheme.py --apply`
## 4. Crontab 配置示例
每 4 小时执行一次0 点、4 点、8 点…):
```cron
0 */4 * * * cd /path/to/auto_trade_sys && /path/to/.venv/bin/python scripts/update_market_scheme.py --apply >> /tmp/update_market_scheme.log 2>&1
```
或每 6 小时:
```cron
0 */6 * * * cd /path/to/auto_trade_sys && /path/to/.venv/bin/python scripts/update_market_scheme.py --apply >> /tmp/update_market_scheme.log 2>&1
```
## 5. 注意事项
- 脚本会清除 `global_strategy_config_v5` Redis 缓存,使交易进程下次读取时从 DB 获取最新配置
- 若希望立即生效,可在前端点击「清除全局缓存」并「重启所有账号交易」
- 若不开启 `AUTO_MARKET_SCHEME_ENABLED`,脚本仅打印识别结果,不修改 DB可用 `--force` 临时强制更新

View File

@ -0,0 +1,117 @@
#!/usr/bin/env python3
"""
定时任务自动识别市场行情并更新 MARKET_SCHEME需开启 AUTO_MARKET_SCHEME_ENABLED
用法:
cd /path/to/auto_trade_sys && python scripts/update_market_scheme.py # 仅检测并打印
python scripts/update_market_scheme.py --apply # 若开启自动模式则更新 DB
python scripts/update_market_scheme.py --apply --force # 强制更新(忽略 AUTO 开关)
crontab 示例 4 小时执行:
0 */4 * * * cd /path/to/auto_trade_sys && python scripts/update_market_scheme.py --apply >> /tmp/update_market_scheme.log 2>&1
"""
import argparse
import logging
import os
import sys
from pathlib import Path
# 项目根目录
proj = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(proj / "backend"))
sys.path.insert(0, str(proj))
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
logger = logging.getLogger(__name__)
def _get_auto_enabled() -> bool:
"""从 DB 读取 AUTO_MARKET_SCHEME_ENABLED默认 False。"""
try:
from database.models import GlobalStrategyConfig
val = GlobalStrategyConfig.get_value("AUTO_MARKET_SCHEME_ENABLED", False)
if isinstance(val, bool):
return val
if isinstance(val, str):
return val.lower() in ("true", "1", "yes")
return bool(val)
except Exception as e:
logger.warning(f"读取 AUTO_MARKET_SCHEME_ENABLED 失败: {e},默认不自动更新")
return False
def _update_market_scheme(scheme: str) -> bool:
"""更新 MARKET_SCHEME 到 DB并清除全局配置 Redis 缓存。"""
try:
from database.models import GlobalStrategyConfig
except ImportError as e:
logger.error(f"导入 GlobalStrategyConfig 失败: {e}")
return False
try:
GlobalStrategyConfig.set(
"MARKET_SCHEME",
scheme,
"string",
"strategy",
"市场方案normal / bear / bull / conservative。由 update_market_scheme 定时任务自动更新。",
updated_by="update_market_scheme",
)
logger.info(f"已更新 MARKET_SCHEME = {scheme}")
# 清除全局配置 Redis 缓存,让 trading_system 下次读取时从 DB 获取
try:
import redis
redis_url = os.getenv("REDIS_URL", "redis://localhost:6379")
redis_use_tls = os.getenv("REDIS_USE_TLS", "False").lower() == "true"
redis_username = os.getenv("REDIS_USERNAME", None)
redis_password = os.getenv("REDIS_PASSWORD", None)
if redis_use_tls and not redis_url.startswith("rediss://"):
redis_url = redis_url.replace("redis://", "rediss://", 1)
r = redis.from_url(
redis_url,
username=redis_username,
password=redis_password,
decode_responses=True,
)
r.ping()
r.delete("global_strategy_config_v5")
logger.info("已清除全局配置 Redis 缓存")
except Exception as e:
logger.warning(f"清除 Redis 缓存失败(不影响 DB 更新): {e}")
return True
except Exception as e:
logger.error(f"更新 MARKET_SCHEME 失败: {e}", exc_info=True)
return False
def main():
parser = argparse.ArgumentParser(description="自动识别市场行情并可选更新 MARKET_SCHEME")
parser.add_argument("--apply", action="store_true", help="若开启自动模式则更新 DB")
parser.add_argument("--force", action="store_true", help="强制更新(忽略 AUTO_MARKET_SCHEME_ENABLED")
args = parser.parse_args()
from trading_system.market_regime_detector import detect_market_regime
regime, details = detect_market_regime()
logger.info(f"市场行情识别: {regime} | 详情: {details}")
if not args.apply:
print(f"REGIME={regime} DETAILS={details}")
return 0
if not args.force and not _get_auto_enabled():
logger.info("AUTO_MARKET_SCHEME_ENABLED 未开启,跳过更新。如需强制更新请加 --force")
return 0
ok = _update_market_scheme(regime)
return 0 if ok else 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -0,0 +1,257 @@
"""
市场行情自动识别模块
基于 Binance 公开 API 判断当前市场状态//正常用于自动切换 MARKET_SCHEME
可被 crontab 定时任务调用如每 4 小时执行一次
使用的接口无需 API Key
- GET /fapi/v1/ticker/24hr24h 涨跌幅
- GET /fapi/v1/premiumIndex资金费率
- GET /futures/data/topLongShortPositionRatio大户多空比
- GET /fapi/v1/klines4H K 线计算 trend_4h
"""
import json
import logging
import ssl
import urllib.request
from typing import Optional, Tuple
logger = logging.getLogger(__name__)
BINANCE_FUTURES_BASE = "https://fapi.binance.com"
BINANCE_FUTURES_DATA = "https://fapi.binance.com/futures/data"
REQUEST_TIMEOUT = 15
def _http_get(url: str, params: Optional[dict] = None) -> Optional[dict]:
"""发起 GET 请求,返回 JSON 或 None。"""
if params:
qs = "&".join(f"{k}={v}" for k, v in params.items())
url = f"{url}?{qs}"
try:
req = urllib.request.Request(url, headers={"Accept": "application/json"})
ctx = ssl.create_default_context()
with urllib.request.urlopen(req, timeout=REQUEST_TIMEOUT, context=ctx) as resp:
raw = resp.read().decode("utf-8")
data = json.loads(raw)
return data
except Exception as e:
logger.warning(f"HTTP GET 失败 {url[:80]}: {e}")
return None
def fetch_btc_24h_change() -> Optional[float]:
"""获取 BTCUSDT 24h 涨跌幅百分比。"""
data = _http_get(f"{BINANCE_FUTURES_BASE}/fapi/v1/ticker/24hr", {"symbol": "BTCUSDT"})
if not data or not isinstance(data, dict):
return None
try:
return float(data.get("priceChangePercent", 0))
except (TypeError, ValueError):
return None
def fetch_btc_funding_rate() -> Optional[float]:
"""获取 BTCUSDT 最近资金费率。正=多头付费,负=空头付费。"""
data = _http_get(f"{BINANCE_FUTURES_BASE}/fapi/v1/premiumIndex", {"symbol": "BTCUSDT"})
if not data or not isinstance(data, dict):
return None
try:
return float(data.get("lastFundingRate", 0))
except (TypeError, ValueError):
return None
def fetch_btc_long_short_ratio(period: str = "1d", limit: int = 1) -> Optional[float]:
"""获取 BTCUSDT 大户持仓多空比。>1 偏多,<1 偏空。"""
data = _http_get(
f"{BINANCE_FUTURES_DATA}/topLongShortPositionRatio",
{"symbol": "BTCUSDT", "period": period, "limit": limit},
)
if not data or not isinstance(data, list) or len(data) == 0:
return None
try:
return float(data[-1].get("longShortRatio", 1))
except (TypeError, ValueError):
return None
def fetch_btc_klines_4h(limit: int = 60) -> Optional[list]:
"""获取 BTCUSDT 4H K 线。"""
data = _http_get(
f"{BINANCE_FUTURES_BASE}/fapi/v1/klines",
{"symbol": "BTCUSDT", "interval": "4h", "limit": limit},
)
if not data or not isinstance(data, list):
return None
return data
def _judge_trend_4h(
price_4h: float,
ema20_4h: Optional[float],
ema50_4h: Optional[float],
macd_hist: Optional[float],
) -> str:
"""根据 4H 价格、EMA、MACD 判断趋势方向。"""
if ema20_4h is None:
return "neutral"
score = 0
total = 0
if price_4h > ema20_4h:
score += 1
elif price_4h < ema20_4h:
score -= 1
total += 1
if ema50_4h is not None:
if ema20_4h > ema50_4h:
score += 1
elif ema20_4h < ema50_4h:
score -= 1
total += 1
if macd_hist is not None:
if macd_hist > 0:
score += 1
elif macd_hist < 0:
score -= 1
total += 1
if total == 0:
return "neutral"
if score >= 2:
return "up"
if score <= -2:
return "down"
return "neutral"
def compute_trend_4h_from_klines(klines: list) -> str:
"""从 4H K 线计算 trend_4h。"""
try:
from .indicators import TechnicalIndicators
except ImportError:
from indicators import TechnicalIndicators
closes = [float(k[4]) for k in klines] # 收盘价
if len(closes) < 50:
return "neutral"
ema20 = TechnicalIndicators.calculate_ema(closes, 20)
ema50 = TechnicalIndicators.calculate_ema(closes, 50)
macd = TechnicalIndicators.calculate_macd(closes, 12, 26, 9)
macd_hist = macd.get("histogram") if macd else None
price_4h = closes[-1]
return _judge_trend_4h(price_4h, ema20, ema50, macd_hist)
def detect_regime(
change_24h: Optional[float] = None,
funding_rate: Optional[float] = None,
long_short_ratio: Optional[float] = None,
trend_4h: Optional[str] = None,
*,
change_bull: float = 2.0,
change_bear: float = -2.0,
funding_bull: float = 0.00005,
funding_bear: float = -0.00005,
lsr_bull: float = 1.1,
lsr_bear: float = 0.9,
) -> Tuple[str, dict]:
"""
根据各项指标打分综合判断市场行情
Returns:
(regime, details): regime 'bull'|'bear'|'normal'details 为各项得分详情
"""
score = 0
details = {}
# 1. 24h 涨跌幅
if change_24h is not None:
details["change_24h"] = round(change_24h, 2)
if change_24h >= change_bull:
score += 1
details["change_score"] = 1
elif change_24h <= change_bear:
score -= 1
details["change_score"] = -1
else:
details["change_score"] = 0
# 2. 4H 趋势
if trend_4h:
details["trend_4h"] = trend_4h
if trend_4h == "up":
score += 1
details["trend_score"] = 1
elif trend_4h == "down":
score -= 1
details["trend_score"] = -1
else:
details["trend_score"] = 0
# 3. 资金费率
if funding_rate is not None:
details["funding_rate"] = round(funding_rate, 6)
if funding_rate >= funding_bull:
score += 1
details["funding_score"] = 1
elif funding_rate <= funding_bear:
score -= 1
details["funding_score"] = -1
else:
details["funding_score"] = 0
# 4. 大户多空比
if long_short_ratio is not None:
details["long_short_ratio"] = round(long_short_ratio, 4)
if long_short_ratio >= lsr_bull:
score += 1
details["lsr_score"] = 1
elif long_short_ratio <= lsr_bear:
score -= 1
details["lsr_score"] = -1
else:
details["lsr_score"] = 0
details["total_score"] = score
if score >= 2:
return "bull", details
if score <= -2:
return "bear", details
return "normal", details
def detect_market_regime(symbol: str = "BTCUSDT") -> Tuple[str, dict]:
"""
主入口拉取 Binance 数据并判断市场行情
Args:
symbol: 基准交易对默认 BTCUSDT
Returns:
(regime, details): regime 'bull'|'bear'|'normal'
"""
if symbol != "BTCUSDT":
logger.warning("当前仅支持 BTCUSDT将使用 BTCUSDT")
symbol = "BTCUSDT"
change_24h = fetch_btc_24h_change()
funding_rate = fetch_btc_funding_rate()
long_short_ratio = fetch_btc_long_short_ratio(period="1d", limit=1)
klines = fetch_btc_klines_4h(limit=60)
trend_4h = compute_trend_4h_from_klines(klines) if klines else None
regime, details = detect_regime(
change_24h=change_24h,
funding_rate=funding_rate,
long_short_ratio=long_short_ratio,
trend_4h=trend_4h,
)
return regime, details

View File

@ -198,6 +198,13 @@ class TradingStrategy:
# 确定交易方向(基于技术指标)
trade_direction = trade_signal['direction']
# 4H 下跌禁止开多(熊市/保守方案:避免逆势抄底)
block_long_4h_down = bool(config.TRADING_CONFIG.get("BLOCK_LONG_WHEN_4H_DOWN", False))
if block_long_4h_down and trade_direction == "BUY" and trade_signal.get("trend_4h") == "down":
logger.info(
f"{symbol} 4H 趋势下跌禁止开多BLOCK_LONG_WHEN_4H_DOWN=true跳过"
)
continue
# 开仓前资金费率过滤:避免在费率极端不利于己方时进场
if not await self._check_funding_rate_filter(symbol, trade_direction):
logger.info(f"{symbol} 资金费率过滤未通过,跳过开仓")