A Estratégia ABE BE RSI é uma versão do MetaTrader consultor especialista Expert_ABE_BE_RSI. O sistema combina padrões clássicos de reversão de velas com confirmação de impulso do Índice de Força Relativa (RSI). Duas velas consecutivas devem formar um padrão envolvente de alta ou baixa, e a vela concluída mais recentemente deve mostrar uma leitura RSI dentro dos limites predefinidos. Regras cruzadas RSI adicionais são aplicadas para nivelar ou reverter posições existentes, refletindo de perto a lógica de decisão da implementação MQL original.
Lógica de negociação
Detecção de padrões envolventes
A estratégia avalia as duas últimas velas concluídas. Um sinal de alta requer:
A vela t-2 fecha mais baixo do que abre (corpo de baixa).
A vela t-1 fecha mais alto do que abre (corpo de alta).
O tamanho do corpo da vela t-1 excede a média móvel dos tamanhos de corpo recentes (o padrão é cinco barras).
A vela t-1 fecha acima da abertura da vela t-2 e abre abaixo do seu fechamento, garantindo um verdadeiro evento envolvente.
O ponto médio da vela t-2 está abaixo da média móvel dos preços de fechamento, confirmando uma tendência de baixa de curto prazo.
Um sinal de absorção de baixa usa as condições simétricas: a vela mais antiga é de alta, a vela mais recente é de baixa com um corpo maior que a média e a vela mais recente engole totalmente o corpo anterior enquanto o ponto médio da barra mais antiga fica acima da média móvel para confirmar um esgotamento da tendência de baixa.
RSI Confirmação
As entradas longas exigem que o RSI da vela fechada mais recentemente esteja abaixo do nível de entrada de alta configurado (padrão 40).
As entradas curtas exigem que o RSI da vela fechada mais recentemente esteja acima do nível de entrada de baixa (padrão 60).
Gerenciamento de saídas
RSI cruzamentos em dois níveis são monitorados para fechar posições existentes:
As posições curtas são cobertas quando RSI sobe acima do limite de saída inferior (padrão 30) ou superior (padrão 70) após estar abaixo dele na vela anterior.
As posições longas são fechadas quando RSI cai abaixo de qualquer limite após ter estado acima dele na vela anterior.
Execução de pedido
As ordens de mercado são usadas tanto para entradas quanto para saídas. Ao reverter, a estratégia primeiro fecha a exposição atual e depois entra na nova direção com o volume base configurado. O dimensionamento de posição imita o modelo de lote fixo do especialista MQL.
Parâmetros
Nome
Descrição
Padrão
Volume
Tamanho do pedido em contratos.
0.1
RsiPeriod
Número de barras usadas pelo filtro RSI.
11
MovingAveragePeriod
Período para o tamanho do corpo da vela e médias móveis do preço de fechamento.
5
BullishEntryLevel
Valor máximo de RSI que ainda valida uma entrada envolvente de alta.
40
BearishEntryLevel
Valor mínimo de RSI necessário para uma entrada de baixa.
60
ExitLowerLevel
Nível de cruzamento inferior RSI para posições planas.
30
ExitUpperLevel
Nível de cruzamento superior RSI para posições planas.
70
CandleType
Série de velas processada pela estratégia.
1 hour time frame
Todos os parâmetros podem ser otimizados no Designer ou Runner graças aos wrappers StrategyParam.
Pipeline de Indicadores
Índice de Força Relativa (RSI) – calcula o impulso sobre o RsiPeriod configurável e fornece limites de entrada/saída.
Média Móvel Simples de preços de fechamento – fornece um contexto de tendência usado para validar padrões envolventes.
Média móvel simples dos tamanhos do corpo da vela – garante que a vela envolvente seja maior que o tamanho médio do corpo nas últimas MovingAveragePeriod barras.
Notas de uso
A estratégia atua apenas em velas totalmente concluídas (CandleStates.Finished). Os dados parciais da barra são ignorados para evitar sinais prematuros.
O histórico de velas é armazenado internamente para avaliar condições de engolfamento sem percorrer grandes coleções, respeitando as diretrizes de conversão de todo o projeto.
StartProtection() é ativado para que os mecanismos de proteção base StockSharp se tornem ativos quando a exposição da posição for diferente de zero.
Diferenças em relação ao Expert Advisor original
O Expert Advisor original depende do sistema de votação por sinal de MetaTrader. Neste porto, os votos são traduzidos em ações diretas de entrada e saída que replicam as mesmas condições.
O gerenciamento de dinheiro é simplificado para um único parâmetro Volume, refletindo o tamanho fixo do lote (Money_FixLot_Lots) usado pelo especialista de origem.
O suporte para trailing-stop não está incluído, pois a versão MT5 usava um módulo "no trailing".
Testes recomendados
Anexe a estratégia a um gráfico no Designer ou API Runner com um símbolo que reage historicamente a reversões envolventes (por exemplo, principais pares de FX).
Verifique RSI e os parâmetros de média móvel antes de executar sessões ao vivo; os padrões reproduzem as configurações publicadas do Expert Advisor.
Use os recursos de otimização integrados para explorar RSI limites alternativos ou períodos médios para diferentes mercados.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// ABE BE RSI strategy: Engulfing pattern with RSI confirmation.
/// Bullish engulfing + oversold RSI for long, bearish engulfing + overbought RSI for short.
/// </summary>
public class AbeBeRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _oversold;
private readonly StrategyParam<decimal> _overbought;
private readonly StrategyParam<int> _signalCooldownCandles;
private readonly List<ICandleMessage> _candles = new();
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public AbeBeRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_oversold = Param(nameof(Oversold), 40m)
.SetDisplay("Oversold", "RSI oversold level", "Signals");
_overbought = Param(nameof(Overbought), 60m)
.SetDisplay("Overbought", "RSI overbought level", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candles.Clear();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_candlesSinceTrade = SignalCooldownCandles;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
_candles.Add(candle);
if (_candles.Count > 5)
_candles.RemoveAt(0);
if (_candles.Count >= 2)
{
var curr = _candles[^1];
var prev = _candles[^2];
var bullishEngulfing = prev.OpenPrice > prev.ClosePrice
&& curr.ClosePrice > curr.OpenPrice
&& curr.OpenPrice <= prev.ClosePrice
&& curr.ClosePrice >= prev.OpenPrice;
var bearishEngulfing = prev.ClosePrice > prev.OpenPrice
&& curr.OpenPrice > curr.ClosePrice
&& curr.OpenPrice >= prev.ClosePrice
&& curr.ClosePrice <= prev.OpenPrice;
if (bullishEngulfing && rsiValue < Oversold && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (bearishEngulfing && rsiValue > Overbought && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class abe_be_rsi_strategy(Strategy):
def __init__(self):
super(abe_be_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._oversold = self.Param("Oversold", 40.0)
self._overbought = self.Param("Overbought", 60.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles = []
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def Oversold(self):
return self._oversold.Value
@Oversold.setter
def Oversold(self, value):
self._oversold.Value = value
@property
def Overbought(self):
return self._overbought.Value
@Overbought.setter
def Overbought(self, value):
self._overbought.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(abe_be_rsi_strategy, self).OnReseted()
self._candles.clear()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(abe_be_rsi_strategy, self).OnStarted2(time)
self._candles.clear()
self._candles_since_trade = self.SignalCooldownCandles
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
rsi_val = float(rsi_value)
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2:
curr = self._candles[-1]
prev = self._candles[-2]
bullish_engulfing = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.OpenPrice) <= float(prev.ClosePrice)
and float(curr.ClosePrice) >= float(prev.OpenPrice))
bearish_engulfing = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.OpenPrice) >= float(prev.ClosePrice)
and float(curr.ClosePrice) <= float(prev.OpenPrice))
if bullish_engulfing and rsi_val < self.Oversold and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif bearish_engulfing and rsi_val > self.Overbought and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return abe_be_rsi_strategy()