Ver en GitHub

Estrategia Market Slayer

Esta estrategia utiliza un cruce de medias móviles ponderadas con confirmación de tendencia SSL en un marco temporal superior. Se abre una posición larga cuando la WMA corta cruza por encima de la WMA larga con tendencia alcista; se abre una posición corta en condiciones opuestas. Se puede habilitar opcionalmente un take profit y stop loss absolutos.

Detalles

  • Criterios de entrada:
    • Largo: la WMA corta cruza por encima de la WMA larga y el SSL del marco temporal superior es alcista.
    • Corto: la WMA corta cruza por debajo de la WMA larga y el SSL del marco temporal superior es bajista.
  • Largo/Corto: Ambos lados.
  • Criterios de salida:
    • El filtro de tendencia cambia al lado opuesto.
    • Stop loss o take profit opcionales cuando están habilitados.
  • Stops: Opcional.
  • Valores predeterminados:
    • ShortLength = 10.
    • LongLength = 20.
    • ConfirmationTrendValue = 2.
    • CandleType = TimeSpan.FromMinutes(5).TimeFrame().
    • TrendCandleType = TimeSpan.FromMinutes(240).TimeFrame().
    • TakeProfitEnabled = false.
    • TakeProfitValue = 20.
    • StopLossEnabled = false.
    • StopLossValue = 50.
  • Filtros:
    • Categoría: Seguimiento de tendencia
    • Dirección: Ambos
    • Indicadores: WMA, SSL
    • Stops: Opcional
    • Complejidad: Básico
    • Marco temporal: Intradía
    • 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 MarketSlayerStrategy : Strategy
{
	private readonly StrategyParam<int> _shortLength;
	private readonly StrategyParam<int> _longLength;
	private readonly StrategyParam<int> _confirmationTrendValue;
	private readonly StrategyParam<DataType> _candleType;

	private WeightedMovingAverage _trendWmaHigh;
	private WeightedMovingAverage _trendWmaLow;
	private WeightedMovingAverage _shortWma;
	private WeightedMovingAverage _longWma;
	private int _trendHlv;
	private bool _isTrendBullish;
	private decimal? _prevShort;
	private decimal? _prevLong;

	public int ShortLength { get => _shortLength.Value; set => _shortLength.Value = value; }
	public int LongLength { get => _longLength.Value; set => _longLength.Value = value; }
	public int ConfirmationTrendValue { get => _confirmationTrendValue.Value; set => _confirmationTrendValue.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public MarketSlayerStrategy()
	{
		_shortLength = Param(nameof(ShortLength), 10);
		_longLength = Param(nameof(LongLength), 20);
		_confirmationTrendValue = Param(nameof(ConfirmationTrendValue), 2);
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
	}

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

		_trendWmaHigh = null;
		_trendWmaLow = null;
		_shortWma = null;
		_longWma = null;
		_trendHlv = 0;
		_isTrendBullish = false;
		_prevShort = null;
		_prevLong = null;
	}

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

		_shortWma = new WeightedMovingAverage { Length = ShortLength };
		_longWma = new WeightedMovingAverage { Length = LongLength };
		_trendWmaHigh = new WeightedMovingAverage { Length = ConfirmationTrendValue };
		_trendWmaLow = new WeightedMovingAverage { Length = ConfirmationTrendValue };

		_prevShort = _prevLong = null;
		_trendHlv = 0;
		_isTrendBullish = false;

		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(_shortWma, _longWma, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal shortWma, decimal longWma)
	{
		if (candle.State != CandleStates.Finished)
			return;

		// Update trend using candle high/low
		var t = candle.ServerTime;
		var highVal = _trendWmaHigh.Process(new DecimalIndicatorValue(_trendWmaHigh, candle.HighPrice, t));
		var lowVal = _trendWmaLow.Process(new DecimalIndicatorValue(_trendWmaLow, candle.LowPrice, t));

		if (_trendWmaHigh.IsFormed && _trendWmaLow.IsFormed)
		{
			var high = highVal.ToDecimal();
			var low = lowVal.ToDecimal();

			if (candle.ClosePrice > high)
				_trendHlv = 1;
			else if (candle.ClosePrice < low)
				_trendHlv = -1;

			var sslDown = _trendHlv < 0 ? high : low;
			var sslUp = _trendHlv < 0 ? low : high;
			_isTrendBullish = sslUp > sslDown;
		}

		if (!_shortWma.IsFormed || !_longWma.IsFormed)
		{
			_prevShort = shortWma;
			_prevLong = longWma;
			return;
		}

		if (_prevShort.HasValue && _prevLong.HasValue)
		{
			var crossUp = _prevShort <= _prevLong && shortWma > longWma;
			var crossDown = _prevShort >= _prevLong && shortWma < longWma;

			if (crossUp && _isTrendBullish && Position <= 0)
				BuyMarket();

			if (crossDown && !_isTrendBullish && Position >= 0)
				SellMarket();

			if (Position > 0 && !_isTrendBullish)
				SellMarket();

			if (Position < 0 && _isTrendBullish)
				BuyMarket();
		}

		_prevShort = shortWma;
		_prevLong = longWma;
	}
}