EMA WMA RSI é uma conversão do MetaTrader 4 consultor especialista "EMA WMA RSI" criado por cmillion. O robô original compara uma média móvel exponencial (EMA) e uma média móvel ponderada linear (WMA) calculada a partir de aberturas de velas e filtra cada cruzamento com um limite de Índice de Força Relativa (RSI). A porta StockSharp mantém a mesma lógica do indicador, opera em velas finalizadas e reproduz as opções de gerenciamento de dinheiro: achatamento de contraposição opcional, níveis de stop-loss/take-profit baseados em pontos e um trailing stop que pode seguir distâncias fixas, o fractal mais recente ou extremos recentes de velas.
A estratégia é projetada para um único símbolo e período selecionado por meio do parâmetro Candle Type. Ele assume MetaTrader "pontos" (o tick mínimo) ao converter distâncias de risco em preços absolutos, portanto, metadados de instrumentos como Security.Step e Security.StepPrice devem ser preenchidos para obter melhores resultados.
Lógica estratégica
Indicadores
EMA – período definido por EMA Period, aplicado aos preços de abertura das velas.
WMA – período definido por WMA Period, também alimentado com aberturas de velas.
RSI – RSI Period, calculado no mesmo fluxo de preço de abertura.
Todos os indicadores são atualizados uma vez por vela finalizada. A porta espelha a execução original de "barra aberta", armazenando os valores EMA/WMA da barra anterior e comparando-os com a barra atual imediatamente após ela fechar.
Regras de entrada
Configuração longa
O valor atual de EMA está abaixo do WMA, enquanto a barra anterior estava EMA acima do WMA (uma cruz descendente).
O valor RSI está acima de 50.
Se existir uma posição curta, ela será opcionalmente fechada quando Close Counter Trades estiver ativado; caso contrário, o sinal será ignorado até que a estratégia seja plana.
Quando as condições são mantidas, uma ordem de compra a mercado é enviada usando o volume fixo ou o dimensionamento baseado em risco.
Configuração curta – lógica simétrica: EMA cruza acima do WMA, a barra anterior mostrou EMA abaixo do WMA, RSI está abaixo de 50 e a estratégia nivela uma compra ou pula a negociação.
Regras de saída
Proteção inicial – Stop Loss (points) e Take Profit (points) são convertidos em distâncias absolutas usando o tamanho do tick do instrumento. Qualquer valor pode ser definido como zero para desativá-lo.
Parada final
Se Trailing Stop (points) for maior que zero, o stop segue o preço a uma distância fixa medida a partir do último fechamento (apenas apertando, nunca afrouxando).
Se a distância final for zero, o algoritmo procura níveis adaptativos:
Trailing Source = CandleExtremes analisa os máximos/mínimos das velas anteriores. Um stop longo move-se para o primeiro mínimo, pelo menos cinco pontos abaixo do preço atual; uma parada curta usa máximas cinco pontos acima.
Trailing Source = Fractals verifica fractais previamente confirmados de Bill Williams (duas velas de cada lado). O mesmo buffer de cinco pontos se aplica para evitar colocar o stop muito próximo do preço atual.
Os ajustes finais só são ativados depois que o preço ultrapassa o preço de entrada original, reproduzindo o comportamento MetaTrader EA.
Saída da posição – Quando o trailing stop ou take-profit é tocado dentro do intervalo de uma vela, a posição é fechada com uma ordem de mercado e o estado interno é redefinido.
Dimensionamento de posição
Fixed Volume fornece o tamanho exato da ordem de mercado (lotes/contratos). Este é o padrão, correspondendo ao parâmetro EA Lot.
Definir Fixed Volume como zero ativa o dimensionamento baseado em risco. A estratégia estima o risco monetário por unidade usando a distância de stop disponível (seja o stop loss configurado ou a distância de trilha efetiva) e Security.StepPrice. Risk % determina quanto patrimônio do portfólio é exposto por negociação. Se o volume fixo e a porcentagem de risco forem zero, o sinal será ignorado.
Parâmetros
Parâmetro
Descrição
Padrão
EMA Period
Período da média móvel exponencial aplicada às aberturas das velas.
28
WMA Period
Período da média móvel ponderada linear nas aberturas.
8
RSI Period
Comprimento RSI usado como filtro direcional.
14
Stop Loss (points)
Compensação de stop loss em MetaTrader pontos. 0 desativa a parada protetora.
0
Take Profit (points)
Compensação de lucro em pontos. 0 desativa o alvo.
500
Trailing Stop (points)
Distância de fuga fixa em pontos. 0 muda para rastreamento adaptativo (fractais ou mínimos/máximos de velas).
70
Trailing Source
Método de trilha adaptativo: CandleExtremes para altos/baixos brutos, Fractals para Williams fractais.
CandleExtremes
Close Counter Trades
Feche uma posição oposta antes de abrir uma nova negociação.
false
Fixed Volume
Volume de ordens de mercado. Defina como 0 para ativar o dimensionamento baseado em risco.
0.1
Risk %
Porcentagem do patrimônio do portfólio comprometido quando Fixed Volume é zero. Requer uma distância de parada válida.
10
Candle Type
Prazo principal usado para indicadores e avaliação de sinais.
30-minute candles
Notas de implementação
As conversões por etapas de preço dependem de Security.Step (ou Security.PriceStep) e Security.StepPrice. Forneça metadados realistas de instrumentos para manter a precisão dos cálculos ponto-preço.
A estratégia processa apenas velas finalizadas e usa seus preços de abertura para atualizações de indicadores, correspondendo à lógica da "nova barra" no código MQL4.
Os níveis finais mantêm pelo menos um buffer de cinco pontos longe do preço atual, assim como a função auxiliar original SlLastBar.
Quando o fechamento da contraposição está desabilitado, a estratégia nunca faz hedge – apenas uma única posição líquida é gerenciada por vez.
Nenhuma implementação Python está incluída neste pacote.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// EMA WMA RSI: Dual EMA crossover with RSI filter and ATR stops.
/// </summary>
public class EmaWmaRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public EmaWmaRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 8)
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 28)
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fastEma, slowEma, rsi, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fastEma); DrawIndicator(area, slowEma); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0) { _prevFast = fastVal; _prevSlow = slowVal; return; }
var close = candle.ClosePrice;
if (Position > 0)
{
if ((fastVal < slowVal && _prevFast >= _prevSlow) || close <= _entryPrice - atrVal * 2m) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 2m) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
else if (fastVal < slowVal && _prevFast >= _prevSlow && rsiVal < 50) { _entryPrice = close; SellMarket(); }
}
_prevFast = fastVal; _prevSlow = slowVal;
}
}
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.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, RelativeStrengthIndex, AverageTrueRange
class ema_wma_rsi_strategy(Strategy):
def __init__(self):
super(ema_wma_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_ema_length = self.Param("FastEmaLength", 8) \
.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 28) \
.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastEmaLength(self):
return self._fast_ema_length.Value
@property
def SlowEmaLength(self):
return self._slow_ema_length.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(ema_wma_rsi_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._fast_ema = ExponentialMovingAverage()
self._fast_ema.Length = self.FastEmaLength
self._slow_ema = ExponentialMovingAverage()
self._slow_ema.Length = self.SlowEmaLength
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._fast_ema, self._slow_ema, self._rsi, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast_val, slow_val, rsi_val, atr_val):
if candle.State != CandleStates.Finished:
return
fv = float(fast_val)
sv = float(slow_val)
rv = float(rsi_val)
av = float(atr_val)
if self._prev_fast == 0 or self._prev_slow == 0 or av <= 0:
self._prev_fast = fv
self._prev_slow = sv
return
close = float(candle.ClosePrice)
if self.Position > 0:
if (fv < sv and self._prev_fast >= self._prev_slow) or close <= self._entry_price - av * 2.0:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if (fv > sv and self._prev_fast <= self._prev_slow) or close >= self._entry_price + av * 2.0:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if fv > sv and self._prev_fast <= self._prev_slow and rv > 50:
self._entry_price = close
self.BuyMarket()
elif fv < sv and self._prev_fast >= self._prev_slow and rv < 50:
self._entry_price = close
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def OnReseted(self):
super(ema_wma_rsi_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def CreateClone(self):
return ema_wma_rsi_strategy()