Ver en GitHub

Estrategia de notificación Cross MA ATR

Descripción general

Esta estrategia es una versión StockSharp del asesor experto MetaTrader 4 "CrossMA". Opera el cruce entre dos promedios móviles simples y protege cada operación con un stop loss basado en el rango verdadero promedio (ATR). Además de la lógica original, la estrategia registra mensajes de información detallada en lugar de enviar correos electrónicos.

Lógica de trading

  1. La estrategia se suscribe a la serie de velas configuradas y calcula una media móvil simple rápida y lenta junto con un indicador ATR.
  2. Cuando el SMA rápido cruza por encima del SMA lento, se cierra cualquier exposición corta y se abre una posición larga. El stop loss se coloca un ATR por debajo del precio de entrada.
  3. Cuando el SMA rápido cruza por debajo del SMA lento, se cierra cualquier exposición larga y se abre una posición corta. El stop loss se coloca un ATR por encima del precio de entrada.
  4. En cada vela terminada se comprueba el precio de parada. Si el precio toca el nivel stop, la posición se cierra inmediatamente en el mercado.

Gestión del riesgo

  • El tamaño de la posición se calcula a partir del capital de la cuenta y el parámetro Maximum Risk. Si la información sobre el capital no está disponible, la estrategia vuelve al valor Base Volume.
  • Después de dos o más operaciones perdedoras consecutivas, el tamaño de la posición se reduce proporcionalmente al Decrease Factor, reproduciendo el comportamiento original de MetaTrader.
  • Todos los volúmenes están normalizados al paso de volumen de seguridad para garantizar tamaños de pedido válidos.

Notificaciones

En lugar de enviar correos electrónicos, la estrategia escribe mensajes de registro claros cada vez que se abren o cierran órdenes mediante señales o paradas. El registro se puede desactivar mediante el parámetro Enable Notifications.

Parámetros

  • Tipo de vela: tipo de vela utilizada para los cálculos del indicador.
  • Período rápido SMA: período de la media móvil rápida (predeterminado 4).
  • Período lento SMA – período del promedio móvil lento (predeterminado 12).
  • ATR Período: número de velas utilizadas por ATR para el cálculo de parada (predeterminado 6).
  • Volumen base: volumen mínimo negociado cuando el tamaño basado en el riesgo no está disponible (predeterminado 0,1).
  • Riesgo máximo: fracción del capital asignado a cada operación (predeterminado 0,02).
  • Factor de disminución: reduce el tamaño de la posición después de perder operaciones (predeterminado 3).
  • Habilitar notificaciones: habilita el registro de acciones comerciales.
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>
/// CrossMA strategy - fast/slow SMA crossover with ATR volatility filter.
/// Buys when fast SMA crosses above slow SMA.
/// Sells when fast SMA crosses below slow SMA.
/// </summary>
public class CrossMaAtrNotificationStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public CrossMaAtrNotificationStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 40)
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;

		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;

		if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}