Auf GitHub ansehen

CAi Standardabweichungs-Strategie

Diese Strategie ist eine StockSharp-Portierung des ursprünglichen MQL5-Experten Exp_i-CAi_StDev. Sie kombiniert einen gleitenden Durchschnitt mit Standardabweichungsbändern, um Ausbrüche und anschließende Umkehrungen zu erkennen.

Strategielogik

  1. Einen einfachen gleitenden Durchschnitt (SMA) über den angegebenen Zeitraum berechnen.
  2. Die Standardabweichung der Schlusskurse über denselben Zeitraum berechnen.
  3. Zwei Bandsets um den SMA aufbauen:
    • Eintrittsbänder: SMA ± OpenMultiplier × StdDev.
    • Ausstiegsbänder: SMA ± CloseMultiplier × StdDev.
  4. Eine Long-Position eröffnen, wenn der Kurs über das obere Eintrittsband schließt.
  5. Eine Short-Position eröffnen, wenn der Kurs unter das untere Eintrittsband schließt.
  6. Eine bestehende Long-Position schließen, wenn der Kurs unter das obere Ausstiegsband fällt.
  7. Eine bestehende Short-Position schließen, wenn der Kurs über das untere Ausstiegsband steigt.

Parameter

Name Beschreibung Standard
MaLength Länge der Berechnung für gleitenden Durchschnitt und Standardabweichung 12
StdDevPeriod Periode für den Standardabweichungsindikator 9
OpenMultiplier Multiplikator für Eintrittsbänder 2.5
CloseMultiplier Multiplikator für Ausstiegsbänder 1.5
CandleType Von der Strategie verwendeter Kerzentyp 5-Minuten-Kerzen

Hinweise

  • Die Strategie verwendet die High-Level-API mit Bind, um Indikatorwerte zu empfangen.
  • Nur abgeschlossene Kerzen werden verarbeitet, um vorzeitige Signale zu vermeiden.
  • Alle Kommentare im Quellcode sind auf Englisch.
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>
/// Strategy based on moving average and standard deviation bands.
/// Opens positions when price breaks outside a wide band
/// and closes them when price returns inside a narrower band.
/// </summary>
public class CaiStandardDeviationStrategy : Strategy
{
	private readonly StrategyParam<int> _maLength;
	private readonly StrategyParam<int> _stdDevPeriod;
	private readonly StrategyParam<decimal> _openMultiplier;
	private readonly StrategyParam<decimal> _closeMultiplier;
	private readonly StrategyParam<DataType> _candleType;

	public int MaLength { get => _maLength.Value; set => _maLength.Value = value; }
	public int StdDevPeriod { get => _stdDevPeriod.Value; set => _stdDevPeriod.Value = value; }
	public decimal OpenMultiplier { get => _openMultiplier.Value; set => _openMultiplier.Value = value; }
	public decimal CloseMultiplier { get => _closeMultiplier.Value; set => _closeMultiplier.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public CaiStandardDeviationStrategy()
	{
		_maLength = Param(nameof(MaLength), 12)
			.SetDisplay("MA Length", "Moving average length", "Parameters")
			.SetOptimize(5, 50, 5);

		_stdDevPeriod = Param(nameof(StdDevPeriod), 9)
			.SetDisplay("StdDev Period", "Standard deviation period", "Parameters")
			.SetOptimize(5, 50, 5);

		_openMultiplier = Param(nameof(OpenMultiplier), 2.5m)
			.SetDisplay("Open Multiplier", "StdDev multiplier for entries", "Parameters")
			.SetOptimize(1m, 3m, 0.5m);

		_closeMultiplier = Param(nameof(CloseMultiplier), 1.5m)
			.SetDisplay("Close Multiplier", "StdDev multiplier for exits", "Parameters")
			.SetOptimize(0.5m, 2m, 0.5m);

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles used", "Parameters");
	}

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

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

		var sma = new SimpleMovingAverage { Length = MaLength };
		var stdDev = new StandardDeviation { Length = StdDevPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, stdDev, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var upperOpen = smaValue + OpenMultiplier * stdDevValue;
		var lowerOpen = smaValue - OpenMultiplier * stdDevValue;
		var upperClose = smaValue + CloseMultiplier * stdDevValue;
		var lowerClose = smaValue - CloseMultiplier * stdDevValue;

		if (Position <= 0 && candle.ClosePrice > upperOpen)
			BuyMarket();

		if (Position >= 0 && candle.ClosePrice < lowerOpen)
			SellMarket();

		if (Position > 0 && candle.ClosePrice < upperClose)
			SellMarket();

		if (Position < 0 && candle.ClosePrice > lowerClose)
			BuyMarket();
	}
}