Ver no GitHub

Estratégia de Cruzamento de Tripla Média Móvel

Esta estratégia opera com base na relação entre três médias móveis: rápida, média e lenta. É uma conversão do especialista MQL X3MA_EA_V2_0.

Lógica de trading

  • Entrada
    • Quando EnableEntryMediumSlowCross é verdadeiro, uma posição comprada é aberta quando a média móvel média cruza acima da lenta. O cruzamento inverso aciona uma entrada vendida.
    • Quando a opção é falsa, a estratégia aguarda que a média rápida cruze a média enquanto ambas permaneçam do mesmo lado da lenta. Posições compradas requerem fast > medium > slow e posições vendidas requerem fast < medium < slow.
  • Saída
    • Quando EnableExitFastSlowCross é verdadeiro, posições abertas são fechadas quando as médias rápida e lenta se cruzam na direção oposta.

Todos os sinais são avaliados em velas concluídas.

Parâmetros

Nome Descrição
FastMaLength Período da média móvel rápida.
MediumMaLength Período da média móvel média.
SlowMaLength Período da média móvel lenta.
EnableEntryMediumSlowCross Permitir entradas no cruzamento médio/lento.
EnableExitFastSlowCross Fechar posições no cruzamento rápido/lento.
CandleType Período dos candles.

Notas

A estratégia usa a API de alto nível com SubscribeCandles e Bind. Os valores dos indicadores são acessados por meio do callback ProcessCandle sem usar GetValue. A lógica de proteção é habilitada com StartProtection() em OnStarted.

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>
/// Triple EMA crossover strategy.
/// </summary>
public class X3MaEaV20Strategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _midPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevMid;
	private bool _hasPrev;

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

	public X3MaEaV20Strategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast MA", "Fast EMA period", "MA");
		_midPeriod = Param(nameof(MidPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Mid MA", "Mid EMA period", "MA");
		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow MA", "Slow EMA period", "MA");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

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

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var mid = new ExponentialMovingAverage { Length = MidPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType)
			.Bind(fast, mid, slow, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal midVal, decimal slowVal)
	{
		if (candle.State != CandleStates.Finished) return;

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevMid = midVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevMid && fastVal > midVal;
		var crossDown = _prevFast >= _prevMid && fastVal < midVal;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastVal;
		_prevMid = midVal;
	}
}