A estratégia reversa MA é uma conversão StockSharp do simples MetaTrader 4 consultor especialista "MA_Reverse". O robô original
monitora quanto tempo o preço do lance permanece acima ou abaixo de uma média móvel simples de 14 períodos (SMA). Depois de uma seqüência longa o suficiente em um
direção, abre uma posição apostando em uma reversão de curto prazo. A porta StockSharp mantém a mesma ideia contando o número
de velas concluídas consecutivas fechando acima ou abaixo de SMA e executando uma ordem de mercado assim que o limite configurado for
alcançado.
Lógica de negociação
Assine as velas do período selecionado e calcule uma média móvel simples com o período definido por SmaPeriod.
Mantenha um contador inteiro (StreakThreshold controla o comprimento alvo) que aumenta enquanto o fechamento da vela permanece acima
a média móvel e diminui enquanto o fechamento permanece abaixo dela. Tocar na média móvel zera o contador.
Quando o contador atingir StreakThreshold e o fechamento estiver pelo menos MinimumDeviation acima de SMA, a estratégia vende com um
ordem de mercado. A suposição é que uma excursão de alta prolongada a partir da média móvel provavelmente reverterá à média.
Quando o contador atinge -StreakThreshold e o fechamento está pelo menos MinimumDeviation abaixo de SMA, a lógica espelha o
comportamento e abre uma posição longa.
Após cada negociação, o contador mantém seu valor em execução, assim como a fonte EA, para que possa começar imediatamente a medir o
próxima sequência.
Gerenciamento de pedidos
As entradas no mercado usam o parâmetro TradeVolume. Se houver uma posição oposta no livro, a estratégia primeiro fecha-o e
em seguida, abre a nova negociação em uma única ordem de mercado para que as reversões correspondam ao comportamento MetaTrader.
Um take-profit global é configurado através do ajudante StartProtection de StockSharp. A distância é igual a TakeProfitPoints
multiplicado pela etapa do preço do título, reproduzindo a meta de lucro de "30 * pontos" do código MQL. Quando o alvo é atingido o
posição é fechada com uma ordem de mercado.
Nenhum stop-loss é implementado no especialista original e, portanto, nenhum é adicionado no porto. O controle de risco é inteiramente feito por
o take-profit e pelas configurações de gerenciamento de dinheiro do usuário.
Parâmetros
Parâmetro
Descrição
TradeVolume
Tamanho do lote usado para cada entrada no mercado. O valor também é usado para dimensionar reversões ao mudar de direção.
SmaPeriod
Número de velas utilizadas pela média móvel simples. O padrão corresponde à média móvel de 14 períodos de EA.
StreakThreshold
Número de fechamentos consecutivos que devem permanecer em um lado do SMA antes que uma ordem de reversão seja permitida.
MinimumDeviation
Distância absoluta mínima entre o fechamento e o SMA que confirma a condição de rompimento.
TakeProfitPoints
Distância de lucro expressa em etapas de preço. É multiplicado pelo PriceStep do instrumento para obter a compensação absoluta do preço.
CandleType
Tipo de vela (período de tempo) usado para calcular o SMA e avaliar os contadores de sequência.
Notas
A lógica do contador funciona com velas finalizadas fornecidas por SubscribeCandles, o que torna a implementação robusta e
compatível com testes históricos. O comportamento corresponde à versão MetaTrader baseada em ticks, desde que as velas estejam boas
granulado o suficiente para capturar excursões de curto prazo.
Como StockSharp agrega posições por padrão, múltiplas entradas consecutivas são gerenciadas como uma única posição com um único
distância flutuante de lucro. Isso equivale a fazer com que MetaTrader coloque o mesmo lucro em todos os pedidos porque o
a distância do preço médio de entrada atual permanece constante.
A estratégia não adiciona seu próprio indicador a Strategy.Indicators porque a infraestrutura de ligação gerencia o indicador
vida útil automaticamente.
Sempre valide as configurações de etapa de preço e volume para seus símbolos de corretor específicos para que o parâmetro TakeProfitPoints
produz o tamanho de destino absoluto desejado.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Moving average reversal strategy converted from the MetaTrader MA_Reverse expert advisor.
/// Counts how many consecutive closes remain on one side of the SMA and opens a trade once the streak is long enough.
/// </summary>
public class MaReverseStrategy : Strategy
{
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _streakThreshold;
private readonly StrategyParam<decimal> _minimumDeviation;
private readonly StrategyParam<DataType> _candleType;
private int _streak;
public MaReverseStrategy()
{
_smaPeriod = Param(nameof(SmaPeriod), 14)
.SetDisplay("SMA Period", "Number of candles used by the moving average.", "Indicator");
_streakThreshold = Param(nameof(StreakThreshold), 3)
.SetDisplay("Streak Threshold", "Number of consecutive closes required before reversing.", "Logic");
_minimumDeviation = Param(nameof(MinimumDeviation), 0.0001m)
.SetDisplay("Minimum Deviation", "Minimum distance between price and SMA to confirm the reversal.", "Logic");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe used for SMA calculation.", "General");
}
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
public int StreakThreshold
{
get => _streakThreshold.Value;
set => _streakThreshold.Value = value;
}
public decimal MinimumDeviation
{
get => _minimumDeviation.Value;
set => _minimumDeviation.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_streak = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_streak = 0;
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
var closePrice = candle.ClosePrice;
var deviation = closePrice - smaValue;
if (deviation == 0m)
{
_streak = 0;
return;
}
if (deviation > 0m)
{
// Price above SMA
if (_streak < 0)
_streak = 0;
_streak++;
if (_streak >= StreakThreshold && deviation > MinimumDeviation)
{
// Long streak above SMA => sell (reversal)
if (Position >= 0)
{
SellMarket();
_streak = 0;
}
}
}
else
{
// Price below SMA
if (_streak > 0)
_streak = 0;
_streak--;
if (-_streak >= StreakThreshold && -deviation > MinimumDeviation)
{
// Long streak below SMA => buy (reversal)
if (Position <= 0)
{
BuyMarket();
_streak = 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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ma_reverse_strategy(Strategy):
"""
MA reversal: counts consecutive closes on one side of SMA.
After streak threshold, opens a reversal trade.
"""
def __init__(self):
super(ma_reverse_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 14).SetDisplay("SMA Period", "SMA period", "Indicators")
self._streak_threshold = self.Param("StreakThreshold", 3).SetDisplay("Streak", "Consecutive closes needed", "Logic")
self._min_deviation = self.Param("MinDeviation", 0.0001).SetDisplay("Min Deviation", "Min distance from SMA", "Logic")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._streak = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ma_reverse_strategy, self).OnReseted()
self._streak = 0
def OnStarted2(self, time):
super(ma_reverse_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self._sma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sma_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
sma = float(sma_val)
deviation = close - sma
if deviation == 0:
self._streak = 0
return
if deviation > 0:
if self._streak < 0:
self._streak = 0
self._streak += 1
if self._streak >= self._streak_threshold.Value and deviation > self._min_deviation.Value:
if self.Position >= 0:
self.SellMarket()
self._streak = 0
else:
if self._streak > 0:
self._streak = 0
self._streak -= 1
if -self._streak >= self._streak_threshold.Value and -deviation > self._min_deviation.Value:
if self.Position <= 0:
self.BuyMarket()
self._streak = 0
def CreateClone(self):
return ma_reverse_strategy()