Ver en GitHub

Estrategia Heiken Ashi Supertrend ADX

Estrategia que combina velas Heiken Ashi, la dirección del Supertrend y un filtro ADX opcional. Una vela Heiken Ashi alcista sin sombra inferior abre un largo en tendencia alcista. Las velas bajistas sin sombra superior abren cortos en tendencia bajista. Las posiciones se cierran ante señales opuestas o un stop trailing basado en ATR.

Las pruebas indican un rendimiento anual promedio de aproximadamente 128%. Funciona mejor en el mercado de criptomonedas.

Heiken Ashi suaviza el ruido mientras que Supertrend y ADX confirman la dirección. El ATR determina los stops dinámicos.

Detalles

  • Criterios de entrada:
    • Largo: vela HA alcista sin sombra inferior con Supertrend alcista y confirmación ADX opcionales
    • Corto: vela HA bajista sin sombra superior con Supertrend bajista y confirmación ADX opcionales
  • Largo/Corto: Ambos
  • Criterios de salida: Vela opuesta o stop trailing ATR
  • Stops: Stop trailing ATR
  • Valores predeterminados:
    • UseSupertrend = true
    • AtrPeriod = 10
    • SupertrendMultiplier = 3m
    • UseAdxFilter = false
    • AdxPeriod = 14
    • AdxThreshold = 25m
    • TrailAtrMultiplier = 2m
    • CandleType = TimeSpan.FromMinutes(15).TimeFrame()
  • Filtros:
    • Categoría: Tendencia
    • Dirección: Ambos
    • Indicadores: Heiken Ashi, Supertrend, ADX, ATR
    • Stops: Sí
    • Complejidad: Intermedio
    • Marco temporal: Medio plazo
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
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;

public class HeikenAshiSupertrendAdxStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<DataType> _candleType;
	private decimal _prevFastEma;
	private decimal _prevSlowEma;

	public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
	public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public HeikenAshiSupertrendAdxStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFastEma = 0m;
		_prevSlowEma = 0m;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
		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 fastEmaValue, decimal slowEmaValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFastEma == 0m || _prevSlowEma == 0m)
		{
			_prevFastEma = fastEmaValue;
			_prevSlowEma = slowEmaValue;
			return;
		}
		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
			BuyMarket();
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
			SellMarket();
		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}