import talib.abstract as ta from pandas import DataFrame from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter class BbRsiStrategy(IStrategy): """ 布林带均值回归策略(4h) 逻辑: 买入:价格跌破布林带下轨 + RSI 超卖 + 成交量放大 → 预期价格回归中轨 卖出:价格触及布林带中轨(止盈)或上轨(激进止盈) 适合震荡行情,与趋势策略互补。 """ INTERFACE_VERSION = 3 timeframe = "1h" can_short = False # 均值回归目标:价格回归布林带中轨约有 2~3% 收益 minimal_roi = { "0": 0.06, # 立即止盈 6% "240": 0.03, # 持仓 240 分钟(1根4h K线)达到 3% 止盈 "480": 0.01, # 持仓 2 根 K线达到 1% 止盈 } stoploss = -0.06 # 止损 6% # 不用追踪止损,均值回归到目标就走 trailing_stop = False startup_candle_count = 30 # Hyperopt 参数范围 buy_rsi = IntParameter(20, 40, default=30, space="buy") sell_rsi = IntParameter(55, 80, default=65, space="sell") bb_std = DecimalParameter(1.5, 3.0, default=2.0, decimals=1, space="buy") def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: # RSI dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) # 布林带:预计算所有 Hyperopt 可能用到的标准差档位(1.5~3.0,步长0.1) import numpy as np for std in np.arange(1.5, 3.1, 0.1): std = round(std, 1) upper, mid, lower = ta.BBANDS( dataframe["close"], timeperiod=20, nbdevup=std, nbdevdn=std ) dataframe[f"bb_upper_{std}"] = upper dataframe[f"bb_mid_{std}"] = mid dataframe[f"bb_lower_{std}"] = lower # 成交量均线(过滤低流动性) dataframe["volume_mean"] = dataframe["volume"].rolling(20).mean() # ATR(衡量波动率,避免在低波动期入场) dataframe["atr"] = ta.ATR(dataframe, timeperiod=14) return dataframe def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: std = self.bb_std.value dataframe.loc[ ( (dataframe["close"] < dataframe[f"bb_lower_{std}"]) & # 价格跌破下轨 (dataframe["rsi"] < self.buy_rsi.value) & # RSI 超卖 (dataframe["volume"] > dataframe["volume_mean"]) & # 成交量放大,信号有效 (dataframe["atr"] > 0) # 确保有波动 ), "enter_long", ] = 1 return dataframe def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: std = self.bb_std.value dataframe.loc[ ( (dataframe["close"] > dataframe[f"bb_mid_{std}"]) | # 价格回归中轨,止盈 (dataframe["rsi"] > self.sell_rsi.value) # RSI 超买 ), "exit_long", ] = 1 return dataframe