Auf GitHub ansehen

Strategie zum Schließen bei MA-Kreuzung

Diese Strategie überwacht einen einfachen gleitenden Durchschnitt (MA) und schließt automatisch alle offenen Positionen, wenn der Kerzenschluss die MA-Linie kreuzt. Sie ist für Trader konzipiert, die Einstiege manuell oder mit anderen Systemen verwalten, aber einen automatischen Ausstieg wünschen, wenn sich der Trend umkehrt.

Die Logik verfolgt die Beziehung zwischen dem Schlusskurs und dem MA. Wenn eine neue abgeschlossene Kerze von einer Seite des MA zur anderen wechselt, sendet die Strategie eine Marktorder, um die Position zu schließen. Keine neuen Positionen werden eröffnet.

Details

  • Einstiegskriterien: Keine. Positionen müssen extern eröffnet werden.
  • Ausstiegskriterien:
    • Long: Vorheriger Schluss über MA und aktueller Schluss unter MA löst einen Verkauf zum Schließen aus.
    • Short: Vorheriger Schluss unter MA und aktueller Schluss über MA löst einen Kauf zum Schließen aus.
  • Long/Short: Beide Richtungen werden unterstützt.
  • Stops: Nicht verwendet. Der MA-Crossover dient als Ausstiegssignal.
  • Standardwerte:
    • MA Period = 50.
    • Candle Type = Zeitrahmen von 1 Minute.
  • Filter:
    • Kategorie: Trendfolge
    • Richtung: Beide
    • Indikatoren: Einzeln
    • Stops: Nein
    • Komplexität: Einfach
    • Zeitrahmen: Beliebig
    • Saisonalität: Nein
    • Neuronale Netze: Nein
    • Divergenz: Nein
    • Risikolevel: Moderat
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>
/// Price cross MA strategy.
/// </summary>
public class CloseCrossMaStrategy : Strategy
{
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevDiff;
	private bool _hasPrev;

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

	public CloseCrossMaStrategy()
	{
		_maPeriod = Param(nameof(MaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "EMA period", "Parameters");
		_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();
		_prevDiff = 0;
		_hasPrev = false;
	}

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

		var ema = new ExponentialMovingAverage { Length = MaPeriod };

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

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

		var diff = candle.ClosePrice - emaVal;

		if (!_hasPrev)
		{
			_prevDiff = diff;
			_hasPrev = true;
			return;
		}

		// Price crosses above EMA
		if (_prevDiff <= 0 && diff > 0 && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		// Price crosses below EMA
		else if (_prevDiff >= 0 && diff < 0 && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevDiff = diff;
	}
}