Ver en GitHub

Estrategia Exp 3XMA Ichimoku

Esta estrategia es una conversión del experto MQL exp_3xma_ishimoku. Utiliza el indicador Ichimoku con periodos reducidos y actúa de manera contraria a las rupturas de la nube.

La línea Kijun se compara con los límites de la nube Ichimoku. Cuando Kijun cae desde arriba de la nube hacia su interior, la estrategia cierra posiciones cortas y abre una posición larga si está permitido comprar. Cuando Kijun sube desde abajo de la nube hacia su interior, las posiciones largas se cierran y se puede abrir una posición corta.

El marco temporal predeterminado para el análisis son velas de 4 horas.

Parámetros

  • Tenkan Period – longitud de la línea Tenkan-sen.
  • Kijun Period – longitud de la línea Kijun-sen.
  • Senkou Span B Period – periodo del segundo tramo Senkou.
  • Allow Buy – habilitar la apertura de posiciones largas.
  • Allow Sell – habilitar la apertura de posiciones cortas.
  • Candle Type – serie de velas utilizada para el cálculo del indicador.

Cómo funciona

  1. Se suscribe a la serie de velas seleccionada y vincula el indicador Ichimoku.
  2. Procesa únicamente velas finalizadas.
  3. Detecta cuándo la línea Kijun cruza los bordes de la nube.
  4. Cierra posiciones opuestas y abre una nueva en la dirección de la señal si está permitido.

Descargo de responsabilidad

Este ejemplo es con fines educativos y no constituye asesoramiento financiero. Úselo bajo su propio riesgo.

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>
/// Ichimoku cloud strategy.
/// Buys when Kijun crosses down into cloud, sells on opposite.
/// </summary>
public class Exp3XmaIshimokuStrategy : Strategy
{
	private readonly StrategyParam<int> _tenkanPeriod;
	private readonly StrategyParam<int> _kijunPeriod;
	private readonly StrategyParam<int> _senkouSpanPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevKijun;
	private decimal? _prevUpper;
	private decimal? _prevLower;

	public int TenkanPeriod { get => _tenkanPeriod.Value; set => _tenkanPeriod.Value = value; }
	public int KijunPeriod { get => _kijunPeriod.Value; set => _kijunPeriod.Value = value; }
	public int SenkouSpanPeriod { get => _senkouSpanPeriod.Value; set => _senkouSpanPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public Exp3XmaIshimokuStrategy()
	{
		_tenkanPeriod = Param(nameof(TenkanPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("Tenkan Period", "Tenkan-sen period", "Ichimoku");

		_kijunPeriod = Param(nameof(KijunPeriod), 6)
			.SetGreaterThanZero()
			.SetDisplay("Kijun Period", "Kijun-sen period", "Ichimoku");

		_senkouSpanPeriod = Param(nameof(SenkouSpanPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Senkou B Period", "Senkou Span B period", "Ichimoku");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevKijun = null;
		_prevUpper = null;
		_prevLower = null;
	}

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

		var ichimoku = new Ichimoku();
		ichimoku.Tenkan.Length = TenkanPeriod;
		ichimoku.Kijun.Length = KijunPeriod;
		ichimoku.SenkouB.Length = SenkouSpanPeriod;

		SubscribeCandles(CandleType)
			.BindEx(ichimoku, ProcessCandle)
			.Start();
	}

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

		var ich = (IIchimokuValue)ichimokuValue;

		if (ich.Kijun is not decimal kijun ||
			ich.SenkouA is not decimal senkouA ||
			ich.SenkouB is not decimal senkouB)
			return;

		var upper = Math.Max(senkouA, senkouB);
		var lower = Math.Min(senkouA, senkouB);

		if (_prevKijun is null)
		{
			_prevKijun = kijun;
			_prevUpper = upper;
			_prevLower = lower;
			return;
		}

		// Buy when Kijun crosses down into cloud
		var crossDown = _prevKijun > _prevUpper && kijun <= upper;
		// Sell when Kijun crosses up out of cloud
		var crossUp = _prevKijun < _prevLower && kijun >= lower;

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

		_prevKijun = kijun;
		_prevUpper = upper;
		_prevLower = lower;
	}
}