Auf GitHub ansehen

ColorXdinMA mit Standardabweichung-Strategie

Diese Strategie ist ein StockSharp-Port des MQL5-Experten Exp_ColorXdinMA_StDev. Sie kombiniert zwei gleitende Durchschnitte zu einer einzigen Linie namens XdinMA und verfolgt deren Änderung im Laufe der Zeit. Die Differenz zwischen dem aktuellen und dem vorherigen XdinMA-Wert wird mit einem Vielfachen seiner jüngsten Standardabweichung verglichen. Wenn die Änderung den positiven Schwellenwert überschreitet, wird eine Long-Position eröffnet, während ein Rückgang unter den negativen Schwellenwert eine Short-Position eröffnet.

Funktionsweise

  1. Zwei einfache gleitende Durchschnitte werden berechnet:
    • Main MA – Periode definiert durch MainLength.
    • Plus MA – Periode definiert durch PlusLength.
  2. Die benutzerdefinierte Linie XdinMA = 2 * MainMA - PlusMA wird erstellt.
  3. Die Änderung von XdinMA zwischen aufeinanderfolgenden Kerzen wird an einen Standardabweichungsindikator mit der Länge StdPeriod übergeben.
  4. Wenn die Änderung größer als K1 * StdDev ist, wird eine Kauforder platziert. Wenn sie kleiner als -K1 * StdDev ist, wird eine Verkaufsorder platziert. Vorhandene entgegengesetzte Positionen werden vor dem Öffnen einer neuen geschlossen.

Parameter

Parameter Beschreibung
MainLength Periode für den primären gleitenden Durchschnitt.
PlusLength Periode für den sekundären gleitenden Durchschnitt.
StdPeriod Anzahl der Balken für die Standardabweichung.
K1 Multiplikator für den Abweichungsschwellenwert.
K2 Reserviert für zukünftige Erweiterung des zweiten Filters.

Alle Parameter werden über StrategyParam bereitgestellt, sodass sie optimiert oder über die Benutzeroberfläche geändert werden können.

Hinweise

  • Es werden nur abgeschlossene Kerzen verarbeitet.
  • Die Strategie verwendet Marktorders und implementiert keine Stop-Loss- oder Take-Profit-Logik.
  • Die Chart-Darstellung enthält beide gleitenden Durchschnitte und ausgeführte Trades für die visuelle Analyse.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
using StockSharp.Algo;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on difference of two moving averages with standard deviation filter.
/// Buys when xdin change exceeds K1*StdDev, sells when below -K1*StdDev.
/// </summary>
public class ColorXdinMAStDevStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _mainLength;
	private readonly StrategyParam<int> _plusLength;
	private readonly StrategyParam<int> _stdPeriod;
	private readonly StrategyParam<decimal> _k1;

	private StandardDeviation _stdDev;
	private decimal? _prevXdin;

	public ColorXdinMAStDevStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle type", "Type of candles", "General");

		_mainLength = Param(nameof(MainLength), 10)
			.SetDisplay("Main MA Length", "Length of primary moving average", "Parameters");

		_plusLength = Param(nameof(PlusLength), 20)
			.SetDisplay("Plus MA Length", "Length of secondary moving average", "Parameters");

		_stdPeriod = Param(nameof(StdPeriod), 9)
			.SetDisplay("StdDev Period", "Period for standard deviation of MA changes", "Parameters");

		_k1 = Param(nameof(K1), 0.5m)
			.SetDisplay("Filter K1", "Multiplier for standard deviation filter", "Parameters");
	}

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

	public int MainLength
	{
		get => _mainLength.Value;
		set => _mainLength.Value = value;
	}

	public int PlusLength
	{
		get => _plusLength.Value;
		set => _plusLength.Value = value;
	}

	public int StdPeriod
	{
		get => _stdPeriod.Value;
		set => _stdPeriod.Value = value;
	}

	public decimal K1
	{
		get => _k1.Value;
		set => _k1.Value = value;
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevXdin = null;
		_stdDev = null;
	}

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

		_prevXdin = null;
		_stdDev = new StandardDeviation { Length = StdPeriod };
		Indicators.Add(_stdDev);

		var mainMa = new ExponentialMovingAverage { Length = MainLength };
		var plusMa = new ExponentialMovingAverage { Length = PlusLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(mainMa, plusMa, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, mainMa);
			DrawIndicator(area, plusMa);
			DrawOwnTrades(area);
		}
	}

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

		// xdin = extrapolated price using MA difference
		var xdin = mainValue * 2m - plusValue;

		if (_prevXdin is null)
		{
			_prevXdin = xdin;
			return;
		}

		var change = xdin - _prevXdin.Value;
		_prevXdin = xdin;

		var stdResult = _stdDev.Process(new DecimalIndicatorValue(_stdDev, change, candle.ServerTime) { IsFinal = true });
		if (!_stdDev.IsFormed)
			return;

		var stDev = stdResult.ToDecimal();
		if (stDev == 0)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var filter = K1 * stDev;

		if (change > filter && Position <= 0)
			BuyMarket();
		else if (change < -filter && Position >= 0)
			SellMarket();
	}
}