feat: add per-symbol strategy params with sweep-optimized values
Support per-symbol strategy parameters (ATR_SL_MULT_XRPUSDT, etc.) via env vars, falling back to global defaults. Sweep results: - XRPUSDT: SL=1.5 TP=4.0 ADX=30 (PF 2.39, Sharpe 61.0) - TRXUSDT: SL=1.0 TP=4.0 ADX=30 (PF 3.87, Sharpe 62.8) - DOGEUSDT: SL=2.0 TP=2.0 ADX=30 (PF 1.80, Sharpe 44.1) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
18
src/bot.py
18
src/bot.py
@@ -18,6 +18,7 @@ class TradingBot:
|
||||
def __init__(self, config: Config, symbol: str = None, risk: RiskManager = None):
|
||||
self.config = config
|
||||
self.symbol = symbol or config.symbol
|
||||
self.strategy = config.get_symbol_params(self.symbol)
|
||||
self.exchange = BinanceFuturesClient(config, symbol=self.symbol)
|
||||
self.notifier = DiscordNotifier(config.discord_webhook_url)
|
||||
self.risk = risk or RiskManager(config)
|
||||
@@ -141,9 +142,9 @@ class TradingBot:
|
||||
df_with_indicators = ind.calculate_all()
|
||||
raw_signal, signal_detail = ind.get_signal(
|
||||
df_with_indicators,
|
||||
signal_threshold=self.config.signal_threshold,
|
||||
adx_threshold=self.config.adx_threshold,
|
||||
volume_multiplier=self.config.volume_multiplier,
|
||||
signal_threshold=self.strategy.signal_threshold,
|
||||
adx_threshold=self.strategy.adx_threshold,
|
||||
volume_multiplier=self.strategy.volume_multiplier,
|
||||
)
|
||||
|
||||
current_price = df_with_indicators["close"].iloc[-1]
|
||||
@@ -198,8 +199,8 @@ class TradingBot:
|
||||
logger.info(f"[{self.symbol}] 포지션 크기: 잔고={per_symbol_balance:.2f}/{balance:.2f} USDT, 증거금비율={margin_ratio:.1%}, 수량={quantity}")
|
||||
stop_loss, take_profit = Indicators(df).get_atr_stop(
|
||||
df, signal, price,
|
||||
atr_sl_mult=self.config.atr_sl_mult,
|
||||
atr_tp_mult=self.config.atr_tp_mult,
|
||||
atr_sl_mult=self.strategy.atr_sl_mult,
|
||||
atr_tp_mult=self.strategy.atr_tp_mult,
|
||||
)
|
||||
|
||||
notional = quantity * price
|
||||
@@ -429,7 +430,12 @@ class TradingBot:
|
||||
self._is_reentering = False
|
||||
|
||||
async def run(self):
|
||||
logger.info(f"[{self.symbol}] 봇 시작, 레버리지 {self.config.leverage}x")
|
||||
s = self.strategy
|
||||
logger.info(
|
||||
f"[{self.symbol}] 봇 시작, 레버리지 {self.config.leverage}x | "
|
||||
f"SL={s.atr_sl_mult}x TP={s.atr_tp_mult}x Signal≥{s.signal_threshold} "
|
||||
f"ADX≥{s.adx_threshold} Vol≥{s.volume_multiplier}x"
|
||||
)
|
||||
await self._recover_position()
|
||||
await self._init_oi_history()
|
||||
|
||||
|
||||
@@ -5,6 +5,16 @@ from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
|
||||
@dataclass
|
||||
class SymbolStrategyParams:
|
||||
"""Per-symbol strategy parameters (from sweep optimization)."""
|
||||
atr_sl_mult: float = 2.0
|
||||
atr_tp_mult: float = 2.0
|
||||
signal_threshold: int = 3
|
||||
adx_threshold: float = 25.0
|
||||
volume_multiplier: float = 2.5
|
||||
|
||||
|
||||
@dataclass
|
||||
class Config:
|
||||
api_key: str = ""
|
||||
@@ -57,3 +67,24 @@ class Config:
|
||||
corr_env = os.getenv("CORRELATION_SYMBOLS", "BTCUSDT,ETHUSDT")
|
||||
self.correlation_symbols = [s.strip() for s in corr_env.split(",") if s.strip()]
|
||||
|
||||
# Per-symbol strategy params: {symbol: SymbolStrategyParams}
|
||||
self._symbol_params: dict[str, SymbolStrategyParams] = {}
|
||||
for sym in self.symbols:
|
||||
self._symbol_params[sym] = SymbolStrategyParams(
|
||||
atr_sl_mult=float(os.getenv(f"ATR_SL_MULT_{sym}", str(self.atr_sl_mult))),
|
||||
atr_tp_mult=float(os.getenv(f"ATR_TP_MULT_{sym}", str(self.atr_tp_mult))),
|
||||
signal_threshold=int(os.getenv(f"SIGNAL_THRESHOLD_{sym}", str(self.signal_threshold))),
|
||||
adx_threshold=float(os.getenv(f"ADX_THRESHOLD_{sym}", str(self.adx_threshold))),
|
||||
volume_multiplier=float(os.getenv(f"VOL_MULTIPLIER_{sym}", str(self.volume_multiplier))),
|
||||
)
|
||||
|
||||
def get_symbol_params(self, symbol: str) -> SymbolStrategyParams:
|
||||
"""Get strategy params for a symbol. Falls back to global defaults."""
|
||||
return self._symbol_params.get(symbol, SymbolStrategyParams(
|
||||
atr_sl_mult=self.atr_sl_mult,
|
||||
atr_tp_mult=self.atr_tp_mult,
|
||||
signal_threshold=self.signal_threshold,
|
||||
adx_threshold=self.adx_threshold,
|
||||
volume_multiplier=self.volume_multiplier,
|
||||
))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user