Esta estratégia porta o assessor especializado do MetaTrader Exp_Open_Oscillator_Cloud_MMRec para a API de alto nível do StockSharp. O sistema opera o cruzamento do indicador Open Oscillator Cloud, que compara o preço de abertura atual com as aberturas das barras mais altas e mais baixas dentro de uma janela deslizante e suaviza o resultado com uma média móvel configurável.
Lógica da estratégia
Construção do indicador
Uma janela de lookback (Oscillator Period, padrão 20 barras) de velas concluídas do período selecionado é construída.
A barra com o máximo mais alto é encontrada e seu preço de abertura é armazenado; a barra com o mínimo mais baixo é encontrada e seu preço de abertura é armazenado.
Dois valores brutos são calculados para a vela atual:
Banda superior = abertura atual − preço de abertura no máximo mais alto.
Banda inferior = preço de abertura no mínimo mais baixo − abertura atual.
Ambas as séries são suavizadas com a média móvel escolhida (Smoothing Method, Smoothing Length). Os tipos suportados são médias móveis Simples, Exponencial, Suavizada e Ponderada.
O histórico suavizado é armazenado e o sinal é atrasado por Signal Bar velas completamente fechadas (padrão 1) para imitar a lógica original do EA que age na barra anterior.
Critérios de entrada
Entrada comprado: a banda superior da barra anterior estava acima da banda inferior e o último valor atrasado cruza para baixo (upper ≤ lower). Pode ser desativado via Enable Long Entries.
Entrada vendido: a banda superior da barra anterior estava abaixo da banda inferior e o último valor atrasado cruza para cima (upper ≥ lower). Pode ser desativado via Enable Short Entries.
Critérios de saída
Saída comprado: a banda superior da barra anterior estava abaixo da banda inferior, sinalizando um regime baixista. Controlado por Enable Long Exits.
Saída vendido: a banda superior da barra anterior estava acima da banda inferior, sinalizando um regime altista. Controlado por Enable Short Exits.
Gestão de risco: se Stop Loss Points ou Take Profit Points forem maiores que zero, a estratégia fecha automaticamente a posição quando o preço atinge essas distâncias (medidas em passos de preço do instrumento) da entrada.
Gerenciamento de ordens
Apenas ordens de mercado são usadas. Antes de abrir uma nova posição, o lado oposto é zerado para permanecer alinhado com o comportamento de posição única do robô MetaTrader.
O parâmetro Trade Volume define o tamanho base de posição para cada entrada.
Parâmetros
Candle Type – período das velas usadas para o oscilador (padrão 1 hora).
Oscillator Period – número de velas na janela deslizante (padrão 20).
Smoothing Method – média móvel aplicada às lacunas de abertura (Simple, Exponential, Smoothed, Weighted).
Smoothing Length – comprimento da média móvel de suavização (padrão 10).
Signal Bar – número de barras completamente fechadas para atrasar a avaliação do sinal (padrão 1).
Enable Long Entries / Enable Short Entries – permite ou bloqueia a abertura de operações em cada direção.
Enable Long Exits / Enable Short Exits – permite ou bloqueia saídas automáticas para a respectiva direção.
Trade Volume – tamanho de cada ordem de mercado (padrão 1 contrato/lote).
Stop Loss Points – distância do stop protetor em passos de preço (0 desativa o stop, padrão 1000).
Take Profit Points – distância do alvo de lucro em passos de preço (0 desativa o alvo, padrão 2000).
Notas de implementação
Os métodos de suavização correspondem às opções mais comuns do EA original. Modos exóticos como JJMA, T3, VIDYA ou AMA não são portados porque o StockSharp já fornece alternativas ricas para otimização e robustez.
Os sinais são avaliados apenas em eventos CandleStates.Finished para evitar agir sobre dados incompletos.
A estratégia mantém um histórico interno de valores suavizados em vez de consultar buffers de indicadores, o que está alinhado com o fluxo de trabalho de alto nível recomendado pelo StockSharp.
Os níveis de proteção são limpos automaticamente quando a posição fica zerada para evitar que stops desatualizados reabram operações.
Comportamento padrão
Seguidor de tendência em ambas as direções com confirmação atrasada para reduzir ruído.
Usa gerenciamento de dinheiro fixo (constante Trade Volume) respeitando distâncias de stop loss e take profit semelhantes à versão MetaTrader.
Adequado como modelo para experimentar com diferentes tipos de suavização ou combinar o oscilador com filtros adicionais.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Open oscillator cloud strategy using EMA crossover as trend proxy.
/// </summary>
public class OpenOscillatorCloudMmrecStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public OpenOscillatorCloudMmrecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, 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 fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fast;
_prevSlow = slow;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast;
_prevSlow = slow;
if (!prevAbove && currAbove)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else if (prevAbove && !currAbove)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class open_oscillator_cloud_mmrec_strategy(Strategy):
def __init__(self):
super(open_oscillator_cloud_mmrec_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow Period", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(open_oscillator_cloud_mmrec_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(open_oscillator_cloud_mmrec_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return open_oscillator_cloud_mmrec_strategy()