在 GitHub 上查看
FullDump BB RSI 策略
该策略移植自 MT5 的 “FullDump” 专家顾问,结合布林带与 RSI 的多步骤过滤逻辑。它先识别动能耗尽,再通过布林带确认价格有回归均值的倾向,只有当价格重新站上/跌破中轨时才入场。风控流程完全复现原版:固定止损/止盈加自定义偏移,并在价格重新触碰相反布林带时把止损推到保本位。
概览
- 适用市场:任意支持布林带与 RSI 的高流动性品种。
- 周期:可配置的蜡烛类型(默认 15 分钟)。
- 方向:多空双向。
- 委托类型:带预设保护水平的市价单。
- 核心思想:在布林带外的极值区域寻找反转机会,并等待价格回归中轨后建仓。
交易逻辑
- RSI 扫描(步骤 1)
- 做多:最近
Depth 根蜡烛中至少有一次 RSI 低于 30。
- 做空:最近窗口内至少有一次 RSI 高于 70。
- 布林带突破(步骤 2)
- 做多:当前收盘价低于或等于最近任意一次下轨值。
- 做空:当前收盘价高于或等于最近任意一次上轨值。
- 回归中轨(步骤 3)
- 做多:收盘价必须重新站上布林中轨。
- 做空:收盘价必须位于布林中轨之下。
- 执行入场
- 当条件满足且当前没有相同方向的仓位时,按设定手数发送市价单。
风险控制
- 止损:做多时设置在最近
Depth 根蜡烛最低点减去偏移;做空时设置在最高点加上偏移。
- 止盈:目标位为当前的相反布林带再加/减同样的偏移量。
- 保本:价格触碰相反布林带后,止损上调/下调至开仓价。
- 平仓:价格触发止损或止盈时立即出场;若出现反向信号会先平掉当前仓位再考虑反向建仓。
参数
| 名称 |
说明 |
默认值 |
备注 |
BandsPeriod |
布林带计算周期。 |
20 |
可优化(10 → 40,步长 1)。 |
RsiPeriod |
RSI 平滑周期。 |
14 |
可优化(7 → 21,步长 1)。 |
Depth |
检查条件的最近蜡烛数量。 |
6 |
可优化(3 → 12,步长 1)。 |
IndentInPoints |
止损与止盈的价格步长偏移。 |
10 |
可优化(5 → 30,步长 5)。 |
OrderVolume |
交易手数。 |
1 |
用于开仓与平仓。 |
CandleType |
计算所用的蜡烛类型。 |
15 分钟蜡烛 |
可调整以适配不同节奏。 |
标签
- 类别:均值回归、波动率通道。
- 指标:Bollinger Bands、Relative Strength Index。
- 风控:固定止损、固定止盈、保本移动。
- 复杂度:中等(多条件逻辑和内部状态管理)。
- 自动化:完全自动下单与管理。
- 适用场景:震荡行情,价格往往在布林带内来回摆动。
注意事项
- 偏移值会乘以品种的最小报价步长,从而模拟 MT5 中基于点(pip)的设置。
- 策略通过保存最近的指标值队列,忠实还原原程序的
Depth 检查逻辑。
- 使用前请确保有足够历史数据,让 RSI 与布林带先完成初始化。
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// FullDump BB RSI strategy (simplified). Uses RSI oversold/overbought
/// with EMA trend filter for mean reversion entries.
/// </summary>
public class FullDumpBbRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _emaPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public int EmaPeriod
{
get => _emaPeriod.Value;
set => _emaPeriod.Value = value;
}
public FullDumpBbRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI averaging period", "Indicators");
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "Trend filter EMA", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ema, (ICandleMessage candle, decimal rsiValue, decimal emaValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
// RSI oversold => buy
if (rsiValue < 25m && Position <= 0)
BuyMarket();
// RSI overbought => sell
else if (rsiValue > 75m && Position >= 0)
SellMarket();
// Trend following on EMA cross
else if (close > emaValue && rsiValue > 60m && rsiValue < 70m && Position <= 0)
BuyMarket();
else if (close < emaValue && rsiValue < 40m && rsiValue > 30m && Position >= 0)
SellMarket();
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class full_dump_bb_rsi_strategy(Strategy):
def __init__(self):
super(full_dump_bb_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candles", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI averaging period", "Indicators")
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "Trend filter EMA", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@property
def EmaPeriod(self):
return self._ema_period.Value
def OnStarted2(self, time):
super(full_dump_bb_rsi_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_value, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
rv = float(rsi_value)
ev = float(ema_value)
if rv < 25 and self.Position <= 0:
self.BuyMarket()
elif rv > 75 and self.Position >= 0:
self.SellMarket()
elif close > ev and rv > 60 and rv < 70 and self.Position <= 0:
self.BuyMarket()
elif close < ev and rv < 40 and rv > 30 and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return full_dump_bb_rsi_strategy()