Ver en GitHub

Estrategia Open Oscillator Cloud MMRec

Esta estrategia porta el asesor experto de MetaTrader Exp_Open_Oscillator_Cloud_MMRec a la API de alto nivel de StockSharp. El sistema opera el cruce del indicador Open Oscillator Cloud, que compara el precio de apertura actual con las aperturas de las barras más altas y más bajas dentro de una ventana deslizante y suaviza el resultado con una media móvil configurable.

Lógica de la estrategia

Construcción del indicador

  • Se construye una ventana de retroceso (Oscillator Period, por defecto 20 barras) de velas terminadas del marco temporal seleccionado.
  • Se encuentra la barra con el máximo más alto y se almacena su precio de apertura, y se encuentra la barra con el mínimo más bajo y se almacena su precio de apertura.
  • Se calculan dos valores brutos para la vela actual:
    • Banda superior = apertura actual − precio de apertura en el máximo más alto.
    • Banda inferior = precio de apertura en el mínimo más bajo − apertura actual.
  • Ambas series se suavizan con la media móvil elegida (Smoothing Method, Smoothing Length). Los tipos admitidos son medias móviles Simple, Exponencial, Suavizada y Ponderada.
  • Se almacena el historial suavizado y se retrasa la señal por Signal Bar velas completamente cerradas (por defecto 1) para imitar la lógica original del EA que actúa sobre la barra anterior.

Criterios de entrada

  • Entrada largo: la banda superior de la barra anterior estaba por encima de la banda inferior y el último valor retrasado cruza hacia abajo (upper ≤ lower). Puede desactivarse mediante Enable Long Entries.
  • Entrada corto: la banda superior de la barra anterior estaba por debajo de la banda inferior y el último valor retrasado cruza hacia arriba (upper ≥ lower). Puede desactivarse mediante Enable Short Entries.

Criterios de salida

  • Salida largo: la banda superior de la barra anterior estaba por debajo de la banda inferior, señalando un régimen bajista. Controlado por Enable Long Exits.
  • Salida corto: la banda superior de la barra anterior estaba por encima de la banda inferior, señalando un régimen alcista. Controlado por Enable Short Exits.
  • Gestión de riesgos: si Stop Loss Points o Take Profit Points son mayores que cero, la estrategia cierra automáticamente la posición una vez que el precio alcanza esas distancias (medidas en pasos de precio del instrumento) desde la entrada.

Gestión de órdenes

  • Solo se utilizan órdenes de mercado. Antes de abrir una nueva posición, el lado opuesto se aplana para permanecer alineado con el comportamiento de posición única del robot MetaTrader.
  • El parámetro Trade Volume establece el tamaño base de posición para cada entrada.

Parámetros

  • Candle Type – marco temporal de las velas usadas para el oscilador (por defecto 1 hora).
  • Oscillator Period – número de velas en la ventana deslizante (por defecto 20).
  • Smoothing Method – media móvil aplicada a las brechas de apertura (Simple, Exponential, Smoothed, Weighted).
  • Smoothing Length – longitud de la media móvil de suavizado (por defecto 10).
  • Signal Bar – número de barras completamente cerradas para retrasar la evaluación de señales (por defecto 1).
  • Enable Long Entries / Enable Short Entries – permite o bloquea la apertura de operaciones en cada dirección.
  • Enable Long Exits / Enable Short Exits – permite o bloquea las salidas automáticas para la dirección respectiva.
  • Trade Volume – tamaño de cada orden de mercado (por defecto 1 contrato/lote).
  • Stop Loss Points – distancia del stop protector en pasos de precio (0 desactiva el stop, por defecto 1000).
  • Take Profit Points – distancia del objetivo de beneficio en pasos de precio (0 desactiva el objetivo, por defecto 2000).

Notas de implementación

  • Los métodos de suavizado coinciden con las opciones más comunes del EA original. Los modos exóticos como JJMA, T3, VIDYA o AMA no se portan porque StockSharp ya ofrece ricas alternativas para optimización y robustez.
  • Las señales se evalúan solo en eventos CandleStates.Finished para evitar actuar sobre datos incompletos.
  • La estrategia mantiene un historial interno de valores suavizados en lugar de consultar buffers de indicadores, lo que se alinea con el flujo de trabajo de alto nivel recomendado por StockSharp.
  • Los niveles de protección se borran automáticamente cuando la posición queda plana para evitar que stops obsoletos reactiven operaciones.

Comportamiento por defecto

  • Seguimiento de tendencia en ambas direcciones con confirmación retrasada para reducir el ruido.
  • Utiliza gestión de dinero fija (constante Trade Volume) respetando las distancias de stop loss y take profit, similar a la versión MetaTrader.
  • Adecuada como plantilla para experimentar con diferentes tipos de suavizado o combinar el oscilador con filtros adicionales.
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();
		}
	}
}