Ver no GitHub

Estratégia Color 3rdGen XMA

Esta estratégia negocia com base na direção de uma média móvel de terceira geração. O indicador é uma combinação de duas médias móveis exponenciais e fica azul quando sobe e rosa quando cai. Um sinal de compra é registrado quando a média gira para cima, e um sinal de venda é registrado quando gira para baixo.

As ordens são colocadas apenas em um horário especificado pelo usuário após o aparecimento de um sinal. As posições também podem ser fechadas quando o sinal oposto é detectado ou quando um período de retenção predefinido expira. Níveis opcionais de stop-loss e take-profit são medidos em pontos.

Parâmetros

  • Length – período de suavização da média de terceira geração.
  • StartHour – hora em que novas posições podem ser abertas.
  • StartMinute – minuto dentro da hora em que as aberturas são permitidas.
  • HoldMinutes – tempo máximo para manter uma posição aberta.
  • Volume – volume de ordem usado para entradas.
  • StopLoss – distância de stop-loss em pontos. 0 desativa o stop.
  • TakeProfit – distância de take-profit em pontos. 0 desativa o alvo.
  • UseLongEntries – habilitar entradas compradas.
  • UseShortEntries – habilitar entradas vendidas.
  • CloseLongBySignal – fechar posições compradas quando um sinal de venda aparecer.
  • CloseShortBySignal – fechar posições vendidas quando um sinal de compra aparecer.
  • CandleType – período das velas usadas para cálculos.

Lógica

  1. Subscrever velas do período selecionado.
  2. Calcular a média móvel de terceira geração para cada vela.
  3. Detectar quando a média sobe ou cai entre velas consecutivas.
  4. Armazenar um sinal de compra ou venda com base na mudança de direção.
  5. No horário de abertura especificado, entrar na direção do sinal armazenado.
  6. Fechar posições em sinais opostos, quando o tempo de retenção decorre ou quando os níveis de stop-loss/take-profit são atingidos.
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>
/// Color 3rd Generation XMA strategy.
/// Uses two EMAs of different periods to approximate 3rd generation moving average.
/// Opens long when fast EMA crosses above slow EMA, short when crosses below.
/// </summary>
public class Color3RdGenXmaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<decimal> _minSpread;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _isFirst = true;

	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public decimal MinSpread { get => _minSpread.Value; set => _minSpread.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public Color3RdGenXmaStrategy()
	{
		_fastLength = Param(nameof(FastLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "General");

		_slowLength = Param(nameof(SlowLength), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "General");
		_minSpread = Param(nameof(MinSpread), 20m)
			.SetGreaterThanZero()
			.SetDisplay("Min Spread", "Minimum EMA spread in price steps", "General");

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

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevFast = 0m;
		_prevSlow = 0m;
		_isFirst = true;
	}

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

		_prevFast = 0m;
		_prevSlow = 0m;
		_isFirst = true;

		var fastEma = new ExponentialMovingAverage { Length = FastLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowLength };

		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 (_isFirst)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_isFirst = false;
			return;
		}

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

		var step = Security.PriceStep ?? 1m;
		var spread = Math.Abs(fast - slow);
		if (spread < MinSpread * step)
		{
			_prevFast = fast;
			_prevSlow = slow;
			return;
		}

		var prevAbove = _prevFast > _prevSlow;
		var curAbove = fast > slow;

		if (!prevAbove && curAbove && Position <= 0)
			BuyMarket();
		else if (prevAbove && !curAbove && Position >= 0)
			SellMarket();

		_prevFast = fast;
		_prevSlow = slow;
	}
}