Estratégia Reversa é um sistema de negociação de reversão à média que combina Bollinger Bandas e o Índice de Força Relativa (RSI) para identificar movimentos exaustos. A estratégia procura reversões de preços perto dos envelopes Bollinger e, ao mesmo tempo, exige que o RSI volte de uma zona de sobrevenda ou sobrecompra. Uma vez satisfeitas ambas as condições, a estratégia entra contra o movimento anterior e gerencia as negociações com paradas e metas fixas baseadas em banda.
Lógica de negociação
Assine a série de velas configurada (velas padrão de 5 minutos).
Calcule Bollinger bandas usando uma média móvel simples com o período configurado e o multiplicador de desvio.
Calcule RSI usando o período de lookback configurado.
Acompanhe a vela finalizada anterior para detectar cruzamentos:
Configuração longa: o fechamento anterior está abaixo da banda inferior anterior e RSI está abaixo do limite de sobrevenda. O fechamento atual deve voltar acima da banda inferior enquanto RSI sobe acima do nível de sobrevenda.
Configuração curta: o fechamento anterior está acima da banda superior anterior e RSI está acima do limite de sobrecompra. O fechamento atual deve cair abaixo da banda superior enquanto RSI cai abaixo do nível de sobrecompra.
Quando uma configuração longa for acionada, compre no mercado, defina um stop de proteção um desvio padrão abaixo do fechamento de entrada e um take-profit dois desvios padrão acima dele.
Quando uma configuração curta for acionada, venda no mercado, defina um stop de proteção um desvio padrão acima do fechamento de entrada e um take-profit dois desvios padrão abaixo dele.
Gerenciar vagas abertas:
Feche negociações longas se o preço tocar a banda superior, atingir o stop ou atingir a meta de lucro.
Feche negociações curtas se o preço tocar a banda inferior, atingir o stop ou atingir a meta de lucro.
Parâmetros
Nome
Descrição
Padrão
CandleType
Prazo para assinatura da vela.
Período de 5 minutos
BollingerPeriod
Número de barras usadas para a média móvel e desvio padrão Bollinger.
20
BollingerWidth
Multiplicador de desvio padrão aplicado a Bollinger bandas.
2,0
RsiPeriod
Número de barras usadas para calcular o RSI.
14
RsiOverbought
RSI limite sinalizando condições de sobrecompra para entradas curtas.
70
RsiOversold
Limite de RSI sinalizando condições de sobrevenda para entradas longas.
30
Todos os parâmetros suportam otimização por meio do StockSharp Designer ou Runner. Ajustar os níveis de sobrevenda/sobrecompra altera o quão agressiva é a detecção de reversão, enquanto a largura Bollinger controla até que ponto o preço deve se estender antes que os sinais sejam considerados.
Notas de uso
A estratégia usa StockSharp API de alto nível com assinaturas automáticas de velas e vinculação de indicadores.
Todas as operações de negociação dependem de ordens de mercado (BuyMarket/SellMarket). Os níveis de stop-loss e take-profit são tratados em código e não como ordens pendentes.
A configuração padrão visa grandes reversões em gráficos intradiários, mas pode ser adaptada a intervalos de tempo mais longos alterando CandleType.
Considere combinar a estratégia com filtros adicionais (tendência, volatilidade, tempo de sessão) ao executar em ambientes ativos.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified from "Reverse" MetaTrader expert.
/// Uses Bollinger Band touches with RSI confirmation for mean-reversion entries.
/// Enters long when price crosses above lower band with RSI oversold,
/// enters short when price crosses below upper band with RSI overbought.
/// </summary>
public class ReverseStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _bollingerWidth;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiOverbought;
private readonly StrategyParam<decimal> _rsiOversold;
private ExponentialMovingAverage _ema;
private RelativeStrengthIndex _rsi;
private decimal _prevClose;
private decimal _prevRsi;
private decimal _prevLower;
private decimal _prevUpper;
private bool _hasPrev;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int BollingerPeriod
{
get => _bollingerPeriod.Value;
set => _bollingerPeriod.Value = value;
}
public decimal BollingerWidth
{
get => _bollingerWidth.Value;
set => _bollingerWidth.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public decimal RsiOverbought
{
get => _rsiOverbought.Value;
set => _rsiOverbought.Value = value;
}
public decimal RsiOversold
{
get => _rsiOversold.Value;
set => _rsiOversold.Value = value;
}
public ReverseStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for signals", "General");
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Bollinger Period", "MA length for Bollinger Bands", "Indicators");
_bollingerWidth = Param(nameof(BollingerWidth), 1m)
.SetGreaterThanZero()
.SetDisplay("Bollinger Width", "Standard deviation multiplier", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_rsiOverbought = Param(nameof(RsiOverbought), 70m)
.SetDisplay("RSI Overbought", "Upper threshold for short signals", "Signals");
_rsiOversold = Param(nameof(RsiOversold), 30m)
.SetDisplay("RSI Oversold", "Lower threshold for long signals", "Signals");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_ema = new ExponentialMovingAverage { Length = BollingerPeriod };
_rsi = new RelativeStrengthIndex { Length = RsiPeriod };
_hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_ema, _rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _ema);
DrawIndicator(area, _rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_ema.IsFormed || !_rsi.IsFormed)
return;
var close = candle.ClosePrice;
var bandOffset = emaValue * (BollingerWidth / 100m);
var upperBand = emaValue + bandOffset;
var lowerBand = emaValue - bandOffset;
if (!_hasPrev)
{
_prevClose = close;
_prevRsi = rsiValue;
_prevLower = lowerBand;
_prevUpper = upperBand;
_hasPrev = true;
return;
}
var volume = Volume;
if (volume <= 0)
volume = 1;
// Long: price crosses up from below lower band + RSI was oversold
var longSignal = _prevClose < _prevLower && close >= lowerBand && _prevRsi < RsiOversold;
// Short: price crosses down from above upper band + RSI was overbought
var shortSignal = _prevClose > _prevUpper && close <= upperBand && _prevRsi > RsiOverbought;
if (longSignal)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (shortSignal)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
// Exit long at upper band
if (Position > 0 && close >= upperBand)
SellMarket(Position);
// Exit short at lower band
if (Position < 0 && close <= lowerBand)
BuyMarket(Math.Abs(Position));
_prevClose = close;
_prevRsi = rsiValue;
_prevLower = lowerBand;
_prevUpper = upperBand;
}
/// <inheritdoc />
protected override void OnReseted()
{
_ema = null;
_rsi = null;
_prevClose = 0;
_prevRsi = 0;
_prevLower = 0;
_prevUpper = 0;
_hasPrev = false;
base.OnReseted();
}
}
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 ExponentialMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class reverse_strategy(Strategy):
def __init__(self):
super(reverse_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._bollinger_period = self.Param("BollingerPeriod", 20)
self._bollinger_width = self.Param("BollingerWidth", 1.0)
self._rsi_period = self.Param("RsiPeriod", 14)
self._rsi_overbought = self.Param("RsiOverbought", 70.0)
self._rsi_oversold = self.Param("RsiOversold", 30.0)
self._prev_close = 0.0
self._prev_rsi = 0.0
self._prev_lower = 0.0
self._prev_upper = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def BollingerPeriod(self):
return self._bollinger_period.Value
@BollingerPeriod.setter
def BollingerPeriod(self, value):
self._bollinger_period.Value = value
@property
def BollingerWidth(self):
return self._bollinger_width.Value
@BollingerWidth.setter
def BollingerWidth(self, value):
self._bollinger_width.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def RsiOverbought(self):
return self._rsi_overbought.Value
@RsiOverbought.setter
def RsiOverbought(self, value):
self._rsi_overbought.Value = value
@property
def RsiOversold(self):
return self._rsi_oversold.Value
@RsiOversold.setter
def RsiOversold(self, value):
self._rsi_oversold.Value = value
def OnReseted(self):
super(reverse_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_rsi = 0.0
self._prev_lower = 0.0
self._prev_upper = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(reverse_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_rsi = 0.0
self._prev_lower = 0.0
self._prev_upper = 0.0
self._has_prev = False
ema = ExponentialMovingAverage()
ema.Length = self.BollingerPeriod
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, rsi, self._process_candle).Start()
def _process_candle(self, candle, ema_value, rsi_value):
if candle.State != CandleStates.Finished:
return
ema_val = float(ema_value)
rsi_val = float(rsi_value)
close = float(candle.ClosePrice)
band_offset = ema_val * (float(self.BollingerWidth) / 100.0)
upper_band = ema_val + band_offset
lower_band = ema_val - band_offset
if not self._has_prev:
self._prev_close = close
self._prev_rsi = rsi_val
self._prev_lower = lower_band
self._prev_upper = upper_band
self._has_prev = True
return
# Long: price crosses up from below lower band + RSI was oversold
long_signal = (self._prev_close < self._prev_lower and close >= lower_band and
self._prev_rsi < float(self.RsiOversold))
# Short: price crosses down from above upper band + RSI was overbought
short_signal = (self._prev_close > self._prev_upper and close <= upper_band and
self._prev_rsi > float(self.RsiOverbought))
if long_signal:
if self.Position <= 0:
self.BuyMarket()
elif short_signal:
if self.Position >= 0:
self.SellMarket()
# Exit long at upper band
if self.Position > 0 and close >= upper_band:
self.SellMarket()
# Exit short at lower band
if self.Position < 0 and close <= lower_band:
self.BuyMarket()
self._prev_close = close
self._prev_rsi = rsi_val
self._prev_lower = lower_band
self._prev_upper = upper_band
def CreateClone(self):
return reverse_strategy()