Auf GitHub ansehen

Liquidex V1 Strategie

Liquidex V1 ist eine Breakout-Scalping-Strategie, die aus dem ursprünglichen MQL-Experten-Advisor konvertiert wurde. Sie kombiniert einen Bereichsfilter und einen gewichteten gleitenden Durchschnitt (WMA), um kurzfristige Chancen zu identifizieren.

Handelslogik

  1. Für jede abgeschlossene Kerze misst die Strategie deren Bereich (high - low).
  2. Ist der Kerzenbereich kleiner als RangeFilter, wird die Kerze ignoriert.
  3. Ein WMA mit der Periode MaPeriod wird anhand der Schlusskurse berechnet.
  4. Wenn die Kerze unterhalb des WMA öffnet und darüber schließt, wird eine Kauf-Marktorder gesendet.
  5. Wenn die Kerze oberhalb des WMA öffnet und darunter schließt, wird eine Verkauf-Marktorder gesendet.
  6. Jede Position ist durch einen in StopLoss definierten Stop-Loss geschützt.

Parameter

  • RangeFilter – Mindestkerzenbereich in Preiseinheiten, der für den Handel erforderlich ist.
  • MaPeriod – Anzahl der Perioden für den gewichteten gleitenden Durchschnitt.
  • StopLoss – Schutz-Stop-Loss in Punkten.
  • CandleType – Für die Analyse verwendete Kerzenserie.

Die Strategie verwendet Strategy.Volume als Ordergröße und kehrt die Position um, wenn ein entgegengesetztes Signal erscheint.

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;
	}
}