Ver no GitHub

Estratégia X-Alert 3

Esta estratégia replica a lógica do especialista original X_alert_3.mq4. Monitora duas médias móveis com parâmetros configuráveis e produz um alerta informativo quando ocorre um cruzamento.

Como funciona

  1. Duas médias móveis são calculadas em cada vela concluída.
  2. Um alerta de alta é gerado quando:
    • MA1 está acima de MA2 na vela atual.
    • MA1 está acima de MA2 na vela anterior.
    • MA1 estava abaixo de MA2 duas velas atrás.
  3. Um alerta de baixa é gerado quando:
    • MA1 está abaixo de MA2 na vela atual.
    • MA1 está abaixo de MA2 na vela anterior.
    • MA1 estava acima de MA2 duas velas atrás.
  4. A estratégia não abre ou fecha nenhuma posição. Ela apenas escreve mensagens no log.

Parâmetros

Parâmetro Descrição Padrão
Ma1Period Período da primeira média móvel. 1
Ma1Type Tipo da primeira média móvel (Simple, Exponential, Smoothed, Weighted). Simple
Ma2Period Período da segunda média móvel. 14
Ma2Type Tipo da segunda média móvel. Simple
PriceType Preço fonte usado nos cálculos (Close, Open, High, Low, Median, Typical, Weighted). Median
CandleType Série de velas usada para processamento. período de 1 minuto

Notas

  • A implementação rastreia as últimas duas diferenças entre as médias móveis para detectar cruzamentos sem acessar diretamente valores históricos do indicador.
  • Os alertas são escritos usando AddInfoLog para manter a estratégia sem efeitos colaterais.
  • O parâmetro do MetaTrader RunIntervalSeconds não é necessário no StockSharp e foi omitido.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on crossover of two moving averages.
/// Buys when fast MA crosses above slow MA, sells when crosses below.
/// </summary>
public class XAlert3Strategy : Strategy
{
	private readonly StrategyParam<int> _ma1Period;
	private readonly StrategyParam<int> _ma2Period;
	private readonly StrategyParam<DataType> _candleType;

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

	public int Ma1Period { get => _ma1Period.Value; set => _ma1Period.Value = value; }
	public int Ma2Period { get => _ma2Period.Value; set => _ma2Period.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public XAlert3Strategy()
	{
		_ma1Period = Param(nameof(Ma1Period), 10)
			.SetGreaterThanZero()
			.SetDisplay("MA1 Period", "Fast moving average period", "Indicators");

		_ma2Period = Param(nameof(Ma2Period), 30)
			.SetGreaterThanZero()
			.SetDisplay("MA2 Period", "Slow moving average period", "Indicators");

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

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

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

		var fast = new ExponentialMovingAverage { Length = Ma1Period };
		var slow = new ExponentialMovingAverage { Length = Ma2Period };

		SubscribeCandles(CandleType)
			.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)
		{
			if (Position < 0) BuyMarket();
			if (Position <= 0) BuyMarket();
		}
		else if (_prevFast >= _prevSlow && fast < slow)
		{
			if (Position > 0) SellMarket();
			if (Position >= 0) SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}