Ver en GitHub

BandOsMaEstrategia personalizada

Descripción general

Esta estrategia es un puerto directo del asesor experto MetaTrader 5 ubicado en MQL/45596/mql5/Experts/MQL5Book/p7/BandOsMACustom.mq5. El robot original combina el histograma MACD (también conocido como OsMA) con Bollinger bandas y un media móvil que se aplica a los valores del histograma en lugar de a los precios brutos. Siempre que el histograma atraviesa la banda inferior, el experto abre una operación larga, mientras que los toques de la banda superior desencadenan entradas cortas. El histograma que cruza un La media móvil separada cierra la posición. Un tope protector y un El paso del trailing stop (igual a una quincuagésima parte del stop) mantiene el riesgo bajo control.

La implementación StockSharp conserva este comportamiento utilizando el nivel alto API, por lo que la lógica comercial sigue siendo legible y depurable dentro del marco.

Aspectos destacados de la conversión

  • El histograma MACD se implementa mediante MovingAverageConvergenceDivergenceHistogram, alimentado con el precio de la vela que corresponde al modo MetaTrader PRICE_* seleccionado por el AppliedPrice parámetro.
  • Bollinger Las bandas y la media móvil de salida procesan la salida de OsMA en lugar de que los datos de precios. Un búfer de historial compacto reproduce el MetaTrader shift argumentos a favor de ambos indicadores.
  • La estrategia mantiene la señalización original largo/corto: cruces por debajo del los cortos iniciales de la banda inferior, los cruces por encima de los cortos iniciales de la banda superior y el OsMA cruza su media móvil y cierra la operación.
  • StartProtection refleja el bloque de stop-loss más MetaTrader trailing-stop. El paso final se calcula como StopLossPoints / 50, al igual que MQL la clase TrailingStop lo hizo.

Indicadores

Indicador Propósito
MovingAverageConvergenceDivergenceHistogram Recrea la salida iOsMA de MetaTrader.
BollingerBands Calcula los umbrales superior e inferior sobre el histograma.
Media móvil (SMA/EMA/SMMA/LWMA) El filtro sale cuando el histograma lo cruza.

Parámetros

Nombre Predeterminado Descripción
CandleType plazo de 1 hora Plazo principal utilizado para todos los cálculos de indicadores.
FastOsmaPeriod 12 Longitud rápida EMA del cálculo de OsMA.
SlowOsmaPeriod 26 Longitud lenta de EMA a partir del cálculo de OsMA.
SignalPeriod 9 Longitud de la señal SMA del cálculo de OsMA.
AppliedPrice Típico Precio aplicado estilo MetaTrader que alimenta el histograma.
BandsPeriod 26 Longitud de las Bollinger Bandas dibujadas en los valores del histograma.
BandsShift 0 Desplazamiento a la derecha (en barras) aplicado a los valores Bollinger.
BandsDeviation 2.0 Multiplicador de desviación estándar para las bandas.
MaPeriod 10 Longitud de la media móvil de salida calculada en el histograma.
MaShift 0 Desplazamiento a la derecha (en barras) aplicado a la media móvil de salida.
MaMethod Sencillo Método de media móvil (SMA, EMA, SMMA, LWMA).
StopLossPoints 1000 Distancia de parada protectora expresada en incrementos de precio.
OrderVolume 0,01 Volumen de operaciones, idéntico a la entrada MetaTrader “Lotes”.

Reglas comerciales

  1. Suscríbase a la serie de velas seleccionada y proporcione el precio aplicado elegido en el histograma MACD.
  2. Pase cada valor de histograma a las Bollinger Bandas y la media móvil de salida.
  3. Detectar señales utilizando los buffers desplazados:
    • Si el histograma cae por la banda inferior, establece una señal alcista.
    • Si el histograma sube por la banda superior, establece una señal bajista.
    • Cuando el histograma cruza la media móvil de salida, borre el activo señal, que permite cerrar la posición.
  4. Gestionar posiciones:
    • Cierre las posiciones largas existentes cada vez que desaparezca la señal alcista; cerrar pantalones cortos cuando la señal bajista desaparece.
    • Abrir en largo cuando la señal alcista está activa y no hay apertura posición; abrir un corto cuando la señal bajista está activa y la posición es plano.
  5. Aplique StartProtection con la distancia de stop-loss configurada y un seguimiento paso igual a StopLossPoints / 50 pasos de precio.

Notas

  • Todos los comentarios en el código fuente están en inglés para cumplir con el repositorio. directrices.
  • Los buffers de historial garantizan que la versión StockSharp respeta MetaTrader BandsShift y MaShift parámetros sin solicitar valores de indicador por índice.
  • La estrategia se alinea con las convenciones API de alto nivel: SubscribeCandles impulsa actualizaciones de indicadores y dirige llamadas a BuyMarket/SellMarket imitador la colocación de la orden del experto original.
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy combining the MACD histogram (OsMA) with Bollinger Bands to trade reversals.
/// Similar to BandOsMa but with customizable moving average filter for exit signals.
/// </summary>
public class BandOsMaCustomStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<int> _macdSignalPeriod;
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<int> _maPeriod;

	private BollingerBands _bollinger;
	private SMA _osmaMA;

	private decimal _prevOsma;
	private decimal _prevUpper;
	private decimal _prevLower;
	private decimal _prevMa;
	private bool _hasPrev;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int MacdFastPeriod
	{
		get => _macdFastPeriod.Value;
		set => _macdFastPeriod.Value = value;
	}

	public int MacdSlowPeriod
	{
		get => _macdSlowPeriod.Value;
		set => _macdSlowPeriod.Value = value;
	}

	public int MacdSignalPeriod
	{
		get => _macdSignalPeriod.Value;
		set => _macdSignalPeriod.Value = value;
	}

	public int BollingerPeriod
	{
		get => _bollingerPeriod.Value;
		set => _bollingerPeriod.Value = value;
	}

	public decimal BollingerDeviation
	{
		get => _bollingerDeviation.Value;
		set => _bollingerDeviation.Value = value;
	}

	public int MaPeriod
	{
		get => _maPeriod.Value;
		set => _maPeriod.Value = value;
	}

	public BandOsMaCustomStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Primary timeframe", "General");

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 20)
			.SetDisplay("MACD Fast", "Fast EMA length", "Indicators");

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 50)
			.SetDisplay("MACD Slow", "Slow EMA length", "Indicators");

		_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 12)
			.SetDisplay("MACD Signal", "Signal EMA length", "Indicators");

		_bollingerPeriod = Param(nameof(BollingerPeriod), 14)
			.SetDisplay("Bollinger Period", "OsMA Bollinger Bands period", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetDisplay("Bollinger Deviation", "Bollinger Bands deviation", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 10)
			.SetDisplay("MA Period", "OsMA moving average period for exit filter", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFastPeriod },
				LongMa = { Length = MacdSlowPeriod }
			},
			SignalMa = { Length = MacdSignalPeriod }
		};

		_bollinger = new BollingerBands
		{
			Length = BollingerPeriod,
			Width = BollingerDeviation
		};

		_osmaMA = new SMA { Length = MaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, macd);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var val = (IMovingAverageConvergenceDivergenceSignalValue)macdValue;
		if (val.Macd is not decimal macdLine || val.Signal is not decimal signalLine)
			return;

		var osma = macdLine - signalLine;

		var bbResult = (BollingerBandsValue)_bollinger.Process(new DecimalIndicatorValue(_bollinger, osma, candle.CloseTime));
		if (bbResult.UpBand is not decimal upper || bbResult.LowBand is not decimal lower)
			return;

		var maResult = _osmaMA.Process(new DecimalIndicatorValue(_osmaMA, osma, candle.CloseTime));
		if (maResult.IsEmpty)
			return;

		var ma = maResult.GetValue<decimal>();

		if (_hasPrev)
		{
			var buySignal = _prevOsma > _prevLower && osma <= lower && osma < ma;
			var sellSignal = _prevOsma < _prevUpper && osma >= upper && osma > ma;

			if (buySignal && Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + 1 : 1);
			else if (sellSignal && Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + 1 : 1);
		}

		_prevOsma = osma;
		_prevUpper = upper;
		_prevLower = lower;
		_prevMa = ma;
		_hasPrev = true;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_bollinger = null;
		_osmaMA = null;
		_prevOsma = 0;
		_prevUpper = 0;
		_prevLower = 0;
		_prevMa = 0;
		_hasPrev = false;

		base.OnReseted();
	}
}