Auf GitHub ansehen

Triple MA

Strategie basierend auf dem Triple Moving Average-Crossover.

Tests zeigen eine durchschnittliche jährliche Rendite von etwa 55%. Die Strategie funktioniert am besten im Aktienmarkt.

Triple MA richtet drei gleitende Durchschnitte aus, um die Richtung zu definieren. Wenn der kürzeste Durchschnitt über dem mittleren und langen Durchschnitt liegt, erfolgt ein Long-Einstieg. Die umgekehrte Ausrichtung öffnet Shorts, und ein Kreuzung der kurzen und mittleren Linien schließt den Trade.

Die Verwendung von drei Durchschnitten hilft, Rauschen zu filtern, das in Einzel-MA-Systemen vorhanden ist. Dieser geschichtete Ansatz versucht, Momentum zu bestätigen, bevor man sich zu einem Trade verpflichtet.

Details

  • Einstiegskriterien: Signale basierend auf MA.
  • Long/Short: Beide Richtungen.
  • Ausstiegskriterien: Gegensätzliches Signal oder Stop.
  • Stops: Ja.
  • Standardwerte:
    • ShortMaPeriod = 5
    • MiddleMaPeriod = 20
    • LongMaPeriod = 50
    • StopLossPercent = 2m
    • CandleType = TimeSpan.FromMinutes(5)
  • Filter:
    • Kategorie: Trend
    • Richtung: Beide
    • Indikatoren: MA
    • Stops: Ja
    • Komplexität: Grundlegend
    • Zeitrahmen: Intraday (5m)
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Mittel
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on Triple Moving Average crossover.
/// It enters long position when short MA > middle MA > long MA and short position when short MA < middle MA < long MA.
/// </summary>
public class TripleMAStrategy : Strategy
{
	private readonly StrategyParam<int> _shortMaPeriod;
	private readonly StrategyParam<int> _middleMaPeriod;
	private readonly StrategyParam<int> _longMaPeriod;
	private readonly StrategyParam<decimal> _stopLossPercent;
	private readonly StrategyParam<DataType> _candleType;

	// Current state
	private bool _prevIsShortAboveMiddle;
	private bool _prevIsBullish;
	private bool _prevIsBearish;

	/// <summary>
	/// Period for short moving average.
	/// </summary>
	public int ShortMaPeriod
	{
		get => _shortMaPeriod.Value;
		set => _shortMaPeriod.Value = value;
	}

	/// <summary>
	/// Period for middle moving average.
	/// </summary>
	public int MiddleMaPeriod
	{
		get => _middleMaPeriod.Value;
		set => _middleMaPeriod.Value = value;
	}

	/// <summary>
	/// Period for long moving average.
	/// </summary>
	public int LongMaPeriod
	{
		get => _longMaPeriod.Value;
		set => _longMaPeriod.Value = value;
	}

	/// <summary>
	/// Stop-loss percentage.
	/// </summary>
	public decimal StopLossPercent
	{
		get => _stopLossPercent.Value;
		set => _stopLossPercent.Value = value;
	}

	/// <summary>
	/// Candle type.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initialize the Triple MA strategy.
	/// </summary>
	public TripleMAStrategy()
	{
		_shortMaPeriod = Param(nameof(ShortMaPeriod), 100)
			.SetDisplay("Short MA Period", "Period for short moving average", "Indicators")

			.SetOptimize(3, 10, 1);

		_middleMaPeriod = Param(nameof(MiddleMaPeriod), 250)
			.SetDisplay("Middle MA Period", "Period for middle moving average", "Indicators")

			.SetOptimize(15, 30, 5);

		_longMaPeriod = Param(nameof(LongMaPeriod), 500)
			.SetDisplay("Long MA Period", "Period for long moving average", "Indicators")

			.SetOptimize(40, 100, 10);

		_stopLossPercent = Param(nameof(StopLossPercent), 2m)
			.SetDisplay("Stop Loss (%)", "Stop loss as a percentage of entry price", "Risk parameters")
			
			.SetOptimize(1, 3, 0.5m);

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevIsShortAboveMiddle = default;
		_prevIsBullish = default;
		_prevIsBearish = default;

	}

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

		// Create indicators
		var shortMa = new ExponentialMovingAverage { Length = ShortMaPeriod };
		var middleMa = new ExponentialMovingAverage { Length = MiddleMaPeriod };
		var longMa = new ExponentialMovingAverage { Length = LongMaPeriod };

		// Create subscription and bind indicators
		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(shortMa, middleMa, longMa, ProcessCandle)
			.Start();

		// Setup chart visualization if available
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, shortMa);
			DrawIndicator(area, middleMa);
			DrawIndicator(area, longMa);
			DrawOwnTrades(area);
		}

	}

	private void ProcessCandle(ICandleMessage candle, decimal shortMaValue, decimal middleMaValue, decimal longMaValue)
	{
		// Skip unfinished candles
		if (candle.State != CandleStates.Finished)
			return;

		// Check if strategy is ready to trade
		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		// Check the MA alignments
		var isShortAboveMiddle = shortMaValue > middleMaValue;
		var isMiddleAboveLong = middleMaValue > longMaValue;

		// Check for MA crossover
		var isShortCrossedMiddle = isShortAboveMiddle != _prevIsShortAboveMiddle;

		// Check for alignment conditions
		var isBullishAlignment = isShortAboveMiddle && isMiddleAboveLong;
		var isBearishAlignment = !isShortAboveMiddle && !isMiddleAboveLong;

		// Entry logic based on three MA alignment change
		if (isBullishAlignment && !_prevIsBullish && Position <= 0)
		{
			BuyMarket(Volume + Math.Abs(Position));
		}
		else if (isBearishAlignment && !_prevIsBearish && Position >= 0)
		{
			SellMarket(Volume + Math.Abs(Position));
		}

		// Update previous state
		_prevIsShortAboveMiddle = isShortAboveMiddle;
		_prevIsBullish = isBullishAlignment;
		_prevIsBearish = isBearishAlignment;
	}
}