feat(config): Add auto trade symbol whitelist functionality
Introduced a new configuration option for an auto trade symbol whitelist, allowing only specified contracts to execute automatic trades. Updated relevant components to support this feature, enhancing control over automated trading strategies. The whitelist can be configured to restrict or allow trades based on user-defined criteria, improving risk management and trading precision.
This commit is contained in:
parent
f8afa22651
commit
a08b8d31c6
|
|
@ -242,6 +242,12 @@ AUTO_TRADE_FILTER_DEFAULTS = {
|
||||||
"category": "strategy",
|
"category": "strategy",
|
||||||
"description": "震荡市额外提高的最小信号门槛。比如 2 表示在基础 MIN_SIGNAL_STRENGTH 上再 +2。",
|
"description": "震荡市额外提高的最小信号门槛。比如 2 表示在基础 MIN_SIGNAL_STRENGTH 上再 +2。",
|
||||||
},
|
},
|
||||||
|
"AUTO_TRADE_SYMBOL_WHITELIST": {
|
||||||
|
"value": "",
|
||||||
|
"type": "string",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "自动交易白名单(逗号/空格分隔)。非空则仅这些合约自动下单,其余仍扫描并生成推荐;空表示不限制。用于「窄宇宙强执行」。",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
# 风险/策略预设(用于一键切换“稳健 / 快速验证”等模式)
|
# 风险/策略预设(用于一键切换“稳健 / 快速验证”等模式)
|
||||||
|
|
|
||||||
|
|
@ -921,6 +921,8 @@ class ConfigManager:
|
||||||
'AUTO_TRADE_ALLOW_UNKNOWN': eff_get('AUTO_TRADE_ALLOW_UNKNOWN', False),
|
'AUTO_TRADE_ALLOW_UNKNOWN': eff_get('AUTO_TRADE_ALLOW_UNKNOWN', False),
|
||||||
'AUTO_TRADE_ALLOW_4H_NEUTRAL': eff_get('AUTO_TRADE_ALLOW_4H_NEUTRAL', allow_neutral_default),
|
'AUTO_TRADE_ALLOW_4H_NEUTRAL': eff_get('AUTO_TRADE_ALLOW_4H_NEUTRAL', allow_neutral_default),
|
||||||
'RANGING_MARKET_SIGNAL_BOOST': eff_get('RANGING_MARKET_SIGNAL_BOOST', 2),
|
'RANGING_MARKET_SIGNAL_BOOST': eff_get('RANGING_MARKET_SIGNAL_BOOST', 2),
|
||||||
|
# 自动交易白名单:非空则仅这些合约自动下单;空表示不限制(窄宇宙)
|
||||||
|
'AUTO_TRADE_SYMBOL_WHITELIST': (eff_get('AUTO_TRADE_SYMBOL_WHITELIST', '') or '').strip(),
|
||||||
|
|
||||||
# 智能入场/限价偏移(部分逻辑会直接读取 TRADING_CONFIG)
|
# 智能入场/限价偏移(部分逻辑会直接读取 TRADING_CONFIG)
|
||||||
'LIMIT_ORDER_OFFSET_PCT': eff_get('LIMIT_ORDER_OFFSET_PCT', 0.5),
|
'LIMIT_ORDER_OFFSET_PCT': eff_get('LIMIT_ORDER_OFFSET_PCT', 0.5),
|
||||||
|
|
|
||||||
|
|
@ -206,6 +206,7 @@ def get_strategy_execution_overview() -> Dict[str, Any]:
|
||||||
mgr.reload_from_redis()
|
mgr.reload_from_redis()
|
||||||
for key in (
|
for key in (
|
||||||
"AUTO_TRADE_ENABLED", "AUTO_TRADE_ONLY_TRENDING", "AUTO_TRADE_ALLOW_4H_NEUTRAL",
|
"AUTO_TRADE_ENABLED", "AUTO_TRADE_ONLY_TRENDING", "AUTO_TRADE_ALLOW_4H_NEUTRAL",
|
||||||
|
"AUTO_TRADE_SYMBOL_WHITELIST",
|
||||||
"MIN_SIGNAL_STRENGTH", "LOW_VOLATILITY_MIN_SIGNAL_STRENGTH", "MARKET_REGIME_AUTO",
|
"MIN_SIGNAL_STRENGTH", "LOW_VOLATILITY_MIN_SIGNAL_STRENGTH", "MARKET_REGIME_AUTO",
|
||||||
"TOP_N_SYMBOLS", "SCAN_INTERVAL", "PRIMARY_INTERVAL", "CONFIRM_INTERVAL",
|
"TOP_N_SYMBOLS", "SCAN_INTERVAL", "PRIMARY_INTERVAL", "CONFIRM_INTERVAL",
|
||||||
"MAX_OPEN_POSITIONS", "MAX_DAILY_ENTRIES", "FIXED_RISK_PERCENT", "USE_FIXED_RISK_SIZING",
|
"MAX_OPEN_POSITIONS", "MAX_DAILY_ENTRIES", "FIXED_RISK_PERCENT", "USE_FIXED_RISK_SIZING",
|
||||||
|
|
@ -236,6 +237,7 @@ def get_strategy_execution_overview() -> Dict[str, Any]:
|
||||||
auto_on = _g("AUTO_TRADE_ENABLED", True, cfg)
|
auto_on = _g("AUTO_TRADE_ENABLED", True, cfg)
|
||||||
only_trending = _g("AUTO_TRADE_ONLY_TRENDING", True, cfg)
|
only_trending = _g("AUTO_TRADE_ONLY_TRENDING", True, cfg)
|
||||||
allow_4h_neutral = _g("AUTO_TRADE_ALLOW_4H_NEUTRAL", False, cfg)
|
allow_4h_neutral = _g("AUTO_TRADE_ALLOW_4H_NEUTRAL", False, cfg)
|
||||||
|
wl_raw = str(cfg.get("AUTO_TRADE_SYMBOL_WHITELIST") or "").strip()
|
||||||
min_strength = _g("MIN_SIGNAL_STRENGTH", 8, cfg)
|
min_strength = _g("MIN_SIGNAL_STRENGTH", 8, cfg)
|
||||||
low_vol_strength = _g("LOW_VOLATILITY_MIN_SIGNAL_STRENGTH", 9, cfg)
|
low_vol_strength = _g("LOW_VOLATILITY_MIN_SIGNAL_STRENGTH", 9, cfg)
|
||||||
regime_auto = _g("MARKET_REGIME_AUTO", True, cfg)
|
regime_auto = _g("MARKET_REGIME_AUTO", True, cfg)
|
||||||
|
|
@ -249,6 +251,10 @@ def get_strategy_execution_overview() -> Dict[str, Any]:
|
||||||
c1.append("• 信号强度 ≥ " + str(min_strength) + "(技术指标综合评分);低波动期自动提高至 " + str(low_vol_strength) + "(" + ("已开启" if regime_auto else "未开启") + "市场节奏识别)。")
|
c1.append("• 信号强度 ≥ " + str(min_strength) + "(技术指标综合评分);低波动期自动提高至 " + str(low_vol_strength) + "(" + ("已开启" if regime_auto else "未开启") + "市场节奏识别)。")
|
||||||
c1.append("• 市场状态:仅当「仅做趋势市」开启时,要求市场状态为 trending 才下单;ranging/unknown 只生成推荐、不自动下单。当前「仅做趋势市」=" + ("是" if only_trending else "否") + "。")
|
c1.append("• 市场状态:仅当「仅做趋势市」开启时,要求市场状态为 trending 才下单;ranging/unknown 只生成推荐、不自动下单。当前「仅做趋势市」=" + ("是" if only_trending else "否") + "。")
|
||||||
c1.append("• 4H 趋势:允许 4H 中性时自动交易 = " + ("是" if allow_4h_neutral else "否") + ";为否时 4H 为中性会跳过自动下单。")
|
c1.append("• 4H 趋势:允许 4H 中性时自动交易 = " + ("是" if allow_4h_neutral else "否") + ";为否时 4H 为中性会跳过自动下单。")
|
||||||
|
if wl_raw:
|
||||||
|
c1.append("• 自动交易白名单:已配置(仅名单内合约会自动下单;其余仍可出现在推荐中)。")
|
||||||
|
else:
|
||||||
|
c1.append("• 自动交易白名单:未启用(空表示不限制合约)。")
|
||||||
sections.append({
|
sections.append({
|
||||||
"title": "一、总开关与自动交易条件",
|
"title": "一、总开关与自动交易条件",
|
||||||
"content": "\n".join(c1),
|
"content": "\n".join(c1),
|
||||||
|
|
|
||||||
110
config/strategy_narrow_universe.json
Normal file
110
config/strategy_narrow_universe.json
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
{
|
||||||
|
"AUTO_TRADE_ONLY_TRENDING": {
|
||||||
|
"value": true,
|
||||||
|
"type": "boolean",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "仅趋势市自动下单;震荡/unknown 只出推荐"
|
||||||
|
},
|
||||||
|
"AUTO_TRADE_ALLOW_4H_NEUTRAL": {
|
||||||
|
"value": false,
|
||||||
|
"type": "boolean",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "4H 中性时不自动下单,减少震荡扫损"
|
||||||
|
},
|
||||||
|
"AUTO_TRADE_ALLOW_RANGING": {
|
||||||
|
"value": false,
|
||||||
|
"type": "boolean",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "与 ONLY_TRENDING 配合:不在横盘自动开仓"
|
||||||
|
},
|
||||||
|
"AUTO_TRADE_ALLOW_UNKNOWN": {
|
||||||
|
"value": false,
|
||||||
|
"type": "boolean",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "市场状态未判定时不自动开仓"
|
||||||
|
},
|
||||||
|
"MIN_SIGNAL_STRENGTH": {
|
||||||
|
"value": 9,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "提高入场门槛,减少边缘单"
|
||||||
|
},
|
||||||
|
"RANGING_MARKET_SIGNAL_BOOST": {
|
||||||
|
"value": 3,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "震荡市在基础门槛上再加 3"
|
||||||
|
},
|
||||||
|
"TOP_N_SYMBOLS": {
|
||||||
|
"value": 12,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "每次扫描深入分析的前 N 个标的,略缩小候选池"
|
||||||
|
},
|
||||||
|
"AUTO_TRADE_SYMBOL_WHITELIST": {
|
||||||
|
"value": "",
|
||||||
|
"type": "string",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "核心:填逗号分隔合约如 SOLUSDT,LINKUSDT 则仅这些自动下单;留空则不限(仅启用下面黑名单/降仓)。"
|
||||||
|
},
|
||||||
|
"MANUAL_BLOCKED_SYMBOLS": {
|
||||||
|
"value": "MOVRUSDT",
|
||||||
|
"type": "string",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "曾出现单日大亏的标的可拉黑"
|
||||||
|
},
|
||||||
|
"MANUAL_REDUCED_SYMBOLS": {
|
||||||
|
"value": "HYPEUSDT,XANUSDT,WIFUSDT,ANKRUSDT,RIVERUSDT,POLYXUSDT,PIPPINUSDT,AINUSDT,ANIMEUSDT,COSUSDT,GUNUSDT,HYPERUSDT,WETUSDT,MONUSDT,ONUSDT,MYXUSDT,TRADOORUSDT",
|
||||||
|
"type": "string",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "弱势/反复试错币:降仓并抬高信号门槛"
|
||||||
|
},
|
||||||
|
"MANUAL_REDUCED_SYMBOL_POSITION_FACTOR": {
|
||||||
|
"value": 0.35,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "降仓名单仓位系数"
|
||||||
|
},
|
||||||
|
"MANUAL_REDUCED_SYMBOL_SIGNAL_BOOST": {
|
||||||
|
"value": 1,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "降仓名单额外 +1 信号门槛"
|
||||||
|
},
|
||||||
|
"ENTRY_PULLBACK_FILTER_ENABLED": {
|
||||||
|
"value": true,
|
||||||
|
"type": "boolean",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "回踩/区间入场过滤"
|
||||||
|
},
|
||||||
|
"ENTRY_PULLBACK_MIN_BARS": {
|
||||||
|
"value": 6,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "略严一档,减少追高"
|
||||||
|
},
|
||||||
|
"ENTRY_PULLBACK_MAX_LONG_IN_RANGE": {
|
||||||
|
"value": 0.56,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "做多要求在区间偏低位置"
|
||||||
|
},
|
||||||
|
"ENTRY_PULLBACK_MIN_SHORT_IN_RANGE": {
|
||||||
|
"value": 0.44,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "做空要求在区间偏高位置"
|
||||||
|
},
|
||||||
|
"BETA_FILTER_ENABLED": {
|
||||||
|
"value": true,
|
||||||
|
"type": "boolean",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "大盘共振过滤"
|
||||||
|
},
|
||||||
|
"BETA_FILTER_THRESHOLD": {
|
||||||
|
"value": -0.01,
|
||||||
|
"type": "number",
|
||||||
|
"category": "strategy",
|
||||||
|
"description": "与推荐脚本默认一致"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,8 @@ if str(PROJECT_ROOT) not in sys.path:
|
||||||
|
|
||||||
# 默认推荐配置(可按你的风格长期维护)
|
# 默认推荐配置(可按你的风格长期维护)
|
||||||
DEFAULT_RECOMMENDED: Dict[str, Dict[str, Any]] = {
|
DEFAULT_RECOMMENDED: Dict[str, Dict[str, Any]] = {
|
||||||
|
# 空=不限制;非空则仅名单内合约自动下单(窄宇宙),见 config/strategy_narrow_universe.json
|
||||||
|
"AUTO_TRADE_SYMBOL_WHITELIST": {"value": "", "type": "string", "category": "strategy"},
|
||||||
"AUTO_TRADE_ONLY_TRENDING": {"value": True, "type": "boolean", "category": "strategy"},
|
"AUTO_TRADE_ONLY_TRENDING": {"value": True, "type": "boolean", "category": "strategy"},
|
||||||
"BETA_FILTER_ENABLED": {"value": True, "type": "boolean", "category": "strategy"},
|
"BETA_FILTER_ENABLED": {"value": True, "type": "boolean", "category": "strategy"},
|
||||||
"BETA_FILTER_THRESHOLD": {"value": -0.01, "type": "number", "category": "strategy"},
|
"BETA_FILTER_THRESHOLD": {"value": -0.01, "type": "number", "category": "strategy"},
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,8 @@ DEFAULT_TRADING_CONFIG = {
|
||||||
'AUTO_TRADE_ALLOW_4H_NEUTRAL': True,
|
'AUTO_TRADE_ALLOW_4H_NEUTRAL': True,
|
||||||
# 震荡市额外提高的最小信号门槛(0-3 建议范围);默认 +2,减少边缘信号
|
# 震荡市额外提高的最小信号门槛(0-3 建议范围);默认 +2,减少边缘信号
|
||||||
'RANGING_MARKET_SIGNAL_BOOST': 2,
|
'RANGING_MARKET_SIGNAL_BOOST': 2,
|
||||||
|
# 自动交易白名单(逗号分隔)。非空则仅名单内合约自动下单;空=不限制。扫描仍可覆盖全市场,仅自动分支拦截。
|
||||||
|
'AUTO_TRADE_SYMBOL_WHITELIST': '',
|
||||||
|
|
||||||
# ===== 趋势入场过滤(防止追在半山腰)=====
|
# ===== 趋势入场过滤(防止追在半山腰)=====
|
||||||
# 是否启用基于趋势状态的入场过滤:
|
# 是否启用基于趋势状态的入场过滤:
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ try:
|
||||||
from .position_manager import PositionManager
|
from .position_manager import PositionManager
|
||||||
from .signal_filters import SignalFilterContext, apply_signal_filters
|
from .signal_filters import SignalFilterContext, apply_signal_filters
|
||||||
from . import config
|
from . import config
|
||||||
from .symbol_policy import resolve_symbol_trading_policy
|
from .symbol_policy import resolve_symbol_trading_policy, auto_trade_whitelist_allows
|
||||||
from .shadow_mode import evaluate_shadow_mode, invalidate_cache as shadow_invalidate_cache
|
from .shadow_mode import evaluate_shadow_mode, invalidate_cache as shadow_invalidate_cache
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from binance_client import BinanceClient
|
from binance_client import BinanceClient
|
||||||
|
|
@ -22,7 +22,7 @@ except ImportError:
|
||||||
from position_manager import PositionManager
|
from position_manager import PositionManager
|
||||||
from signal_filters import SignalFilterContext, apply_signal_filters
|
from signal_filters import SignalFilterContext, apply_signal_filters
|
||||||
import config
|
import config
|
||||||
from symbol_policy import resolve_symbol_trading_policy
|
from symbol_policy import resolve_symbol_trading_policy, auto_trade_whitelist_allows
|
||||||
from shadow_mode import evaluate_shadow_mode, invalidate_cache as shadow_invalidate_cache
|
from shadow_mode import evaluate_shadow_mode, invalidate_cache as shadow_invalidate_cache
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -183,6 +183,14 @@ class TradingStrategy:
|
||||||
logger.info(f"{symbol} 自动交易已关闭(AUTO_TRADE_ENABLED=false),跳过自动下单(推荐已生成)")
|
logger.info(f"{symbol} 自动交易已关闭(AUTO_TRADE_ENABLED=false),跳过自动下单(推荐已生成)")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# 窄宇宙:可选自动交易白名单(非空则仅名单内合约自动下单)
|
||||||
|
wl_raw = config.TRADING_CONFIG.get("AUTO_TRADE_SYMBOL_WHITELIST", "") or ""
|
||||||
|
if not auto_trade_whitelist_allows(symbol, wl_raw):
|
||||||
|
logger.info(
|
||||||
|
f"{symbol} 不在自动交易白名单内,跳过自动下单(仅生成推荐)|AUTO_TRADE_SYMBOL_WHITELIST"
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
# 提升胜率:可配置的“仅 trending 自动交易”过滤
|
# 提升胜率:可配置的“仅 trending 自动交易”过滤
|
||||||
only_trending = bool(config.TRADING_CONFIG.get("AUTO_TRADE_ONLY_TRENDING", True))
|
only_trending = bool(config.TRADING_CONFIG.get("AUTO_TRADE_ONLY_TRENDING", True))
|
||||||
allow_ranging = bool(config.TRADING_CONFIG.get("AUTO_TRADE_ALLOW_RANGING", False))
|
allow_ranging = bool(config.TRADING_CONFIG.get("AUTO_TRADE_ALLOW_RANGING", False))
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,22 @@ from typing import Any, Dict, Set
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def auto_trade_whitelist_allows(symbol: str, whitelist_raw: Any) -> bool:
|
||||||
|
"""
|
||||||
|
自动交易白名单(窄宇宙)。
|
||||||
|
|
||||||
|
- 当 AUTO_TRADE_SYMBOL_WHITELIST 为空/未配置时:不限制,与历史行为一致。
|
||||||
|
- 非空时:仅名单内的合约允许自动下单;仍会扫描并生成推荐(由 strategy 层在自动分支前拦截)。
|
||||||
|
"""
|
||||||
|
sym = (symbol or "").strip().upper()
|
||||||
|
if not sym:
|
||||||
|
return False
|
||||||
|
allowed = _parse_symbol_list(whitelist_raw)
|
||||||
|
if not allowed:
|
||||||
|
return True
|
||||||
|
return sym in allowed
|
||||||
|
|
||||||
|
|
||||||
def _parse_symbol_list(raw: Any) -> Set[str]:
|
def _parse_symbol_list(raw: Any) -> Set[str]:
|
||||||
"""兼容 string/list/dict 三种配置格式,统一转成大写 symbol 集合。"""
|
"""兼容 string/list/dict 三种配置格式,统一转成大写 symbol 集合。"""
|
||||||
if raw is None:
|
if raw is None:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user