Auf GitHub ansehen

Color Zerolag Momentum OSMA-Strategie

Diese Strategie erstellt einen benutzerdefinierten Zero-Lag-Momentum-OSMA-Oszillator aus fünf Momentum-Berechnungen. Wenn der Oszillatorwert vor zwei Balken unter dem Wert vor drei Balken liegt, gilt der Trend als aufwärtsgerichtet. In diesem Fall werden Short-Positionen geschlossen und eine neue Long-Position kann eröffnet werden, wenn der aktuellste Wert über dem Wert vor zwei Balken liegt. Wenn der Wert vor zwei Balken über dem Wert vor drei Balken liegt, ist der Trend abwärtsgerichtet, Long-Positionen werden geschlossen, und eine Short-Position kann eröffnet werden, wenn der letzte Wert unter dem Wert vor zwei Balken liegt.

Parameter

  • Smoothing1 – erster Glättungsfaktor für den langsamen Trend.
  • Smoothing2 – zweiter Glättungsfaktor für die OSMA-Linie.
  • Factor1-5 – Gewichte für jede Momentum-Komponente.
  • MomentumPeriod1-5 – Perioden für die Momentum-Indikatoren.
  • CandleType – Kerzen-Zeitrahmen für Berechnungen.
  • BuyOpen – Long-Positionen eröffnen erlauben.
  • SellOpen – Short-Positionen eröffnen erlauben.
  • BuyClose – Long-Positionen schließen erlauben.
  • SellClose – Short-Positionen schließen erlauben.
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 the zero-lag momentum OSMA indicator.
/// Uses weighted momentum composite with EMA smoothing for trend detection.
/// </summary>
public class ColorZerolagMomentumOsmaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevOsma;
	private decimal _prevPrevOsma;
	private int _count;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public ColorZerolagMomentumOsmaStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "General");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle Type", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevOsma = 0;
		_prevPrevOsma = 0;
		_count = 0;
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType)
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

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

		var osma = fastValue - slowValue;
		_count++;

		if (_count < 3)
		{
			_prevPrevOsma = _prevOsma;
			_prevOsma = osma;
			return;
		}

		// Buy when OSMA turns up (was decreasing, now increasing)
		var turnUp = _prevOsma < _prevPrevOsma && osma > _prevOsma;
		// Sell when OSMA turns down (was increasing, now decreasing)
		var turnDown = _prevOsma > _prevPrevOsma && osma < _prevOsma;

		if (turnUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (turnDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevPrevOsma = _prevOsma;
		_prevOsma = osma;
	}
}