Ver en GitHub

Estrategia Liquidex V1

Liquidex V1 es una estrategia de scalping por ruptura convertida del asesor experto MQL original. Combina un filtro de rango y una media móvil ponderada (WMA) para identificar oportunidades a corto plazo.

Lógica de trading

  1. Para cada vela completada, la estrategia mide su rango (high - low).
  2. Si el rango de la vela es menor que RangeFilter, la vela se ignora.
  3. Se calcula una WMA con período MaPeriod usando precios de cierre.
  4. Cuando la vela abre por debajo de la WMA y cierra por encima, se envía una orden de compra a mercado.
  5. Cuando la vela abre por encima de la WMA y cierra por debajo, se envía una orden de venta a mercado.
  6. Cada posición está protegida por un stop-loss definido en StopLoss.

Parámetros

  • RangeFilter – rango mínimo de la vela en unidades de precio requerido para operar.
  • MaPeriod – número de períodos para la media móvil ponderada.
  • StopLoss – stop-loss de protección en puntos.
  • CandleType – serie de velas utilizada para el análisis.

La estrategia usa Strategy.Volume como tamaño de la orden e invierte la posición cuando aparece una señal opuesta.

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>
/// WMA crossover strategy with range filter.
/// </summary>
public class LiquidexV1Strategy : Strategy
{
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevWma;
	private bool _hasPrev;

	public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public LiquidexV1Strategy()
	{
		_maPeriod = Param(nameof(MaPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "WMA period", "Indicators");
		_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();
		_prevClose = 0;
		_prevWma = 0;
		_hasPrev = false;
	}

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

		var wma = new WeightedMovingAverage { Length = MaPeriod };

		SubscribeCandles(CandleType)
			.Bind(wma, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevClose = candle.ClosePrice;
			_prevWma = wmaVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevClose <= _prevWma && candle.ClosePrice > wmaVal;
		var crossDown = _prevClose >= _prevWma && candle.ClosePrice < wmaVal;

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

		_prevClose = candle.ClosePrice;
		_prevWma = wmaVal;
	}
}