Auf GitHub ansehen

OsMA Vier-Farben-Pfeilstrategie

Überblick

Diese Strategie bildet das Verhalten des MetaTrader-Expertenberaters „OsMA Four Colors Arrow“ innerhalb des StockSharp-Frameworks nach. Der ursprüngliche EA reagiert auf die farbigen Pfeile, die vom begleitenden Indikator erzeugt werden, wann immer das OsMA (MACD-Histogramm) die Phase ändert. In der StockSharp-Version wird das gleiche Verhalten durch die Überwachung von Nulldurchgängen des MACD-Histogramms modelliert: Ein bullischer Cross (das Histogramm bewegt sich von negativ nach positiv) löst Long-Einstiege aus, während ein bärischer Cross Short-Einstiege auslöst. Der optionale Umkehrmodus stellt die Logik für Absicherungs- oder Mean-Reversion-Tests auf den Kopf.

Die Vorlage funktioniert nur mit fertigen Kerzen und kann eine tägliche Handelssitzung erzwingen, ähnlich dem Zeitfilter, der von der MQL-Version angeboten wird. Das integrierte Geldmanagement umfasst ein konfigurierbares Handelsvolumen, eine Obergrenze für die Anzahl der aggregierten Positionen und einen automatischen Stop-Loss-/Take-Profit-/Trailing-Schutz, ausgedrückt in Pips.

Handelslogik

  1. Abonnieren Sie den ausgewählten Zeitrahmen und berechnen Sie ein MACD-Histogramm (OsMA) mit konfigurierbaren schnellen, langsamen und Signallängen von EMA.
  2. Wenn eine Kerze schließt, überprüfen Sie das Histogrammzeichen:
    • Histogramm kreuzt über Null → bullischer Pfeil → Kaufsignal.
    • Histogramm kreuzt unter Null → rückläufiger Pfeil → Verkaufssignal.
  3. Wenden Sie optionale Funktionen an, bevor Sie eine Bestellung senden:
    • Richtungsfilter (nur lang, nur kurz oder beides).
    • Reverse-Modus zum Invertieren von Signalen.
    • Schließen Sie das bestehende Gegenrisiko, bevor Sie den neuen Trade eröffnen.
    • Beschränken Sie sich auf eine aktive Position oder akkumulieren Sie bis zur konfigurierten maximalen Belichtung.
  4. Marktaufträge werden mit der konfigurierten Losgröße gesendet. StartProtection wandelt Pip-Eingaben in absolute Preis-Offsets um, um Stop-Loss, Take-Profit und Trailing-Management automatisch durchzuführen.
  5. Trades werden außerhalb der zulässigen Intraday-Sitzung ignoriert, wenn der Zeitfilter aktiviert ist.

Parameter

Name Beschreibung
CandleType Zeitrahmen, der für Berechnungen und Signalgenerierung verwendet wird.
FastPeriod / SlowPeriod / SignalPeriod EMA Längen für das MACD Histogramm (OsMA).
StopLossPips / TakeProfitPips Risikoziele in Pips. Zum Deaktivieren auf Null setzen.
TrailingActivatePips Erforderlicher Gewinn (in Pips), bevor sich der Trailing Stop bewegen kann.
TrailingStopPips Nachlaufdistanz in Pips. Null deaktiviert das nachgestellte Modul.
TrailingStepPips Zusätzliche Pips, die gewonnen werden müssen, bevor der Trailing Stop wieder verschärft wird.
MaxPositions Maximale aggregierte Positionseinheiten (TradeVolume Vielfache). Null bedeutet unbegrenzt.
ReverseSignals Einstiegsrichtung umkehren (kaufen ↔ verkaufen).
DirectionMode Beschränken Sie die Signale auf Nur-Long-Signale, Nur-Short-Signale oder beides.
CloseOppositePositions Schließen Sie alle gegenüberliegenden Belichtungen, bevor Sie auf das neue Signal reagieren.
OnlyOnePosition Bei true wird verhindert, dass eine bereits offene Position in die gleiche Richtung erweitert wird.
UseTimeControl Aktivieren Sie den Intraday-Handelssitzungsfilter.
StartHour, StartMinute, EndHour, EndMinute Sitzungsgrenzen (das Ende kann früher als der Beginn liegen, um Nachtsitzungen abzudecken).
TradeVolume Bestellvolumen in Losen.

Notizen

  • Trailing-Stop-Eingaben ahmen den EA nach: Trailing wird erst nach TrailingActivatePips verfügbar und bewegt sich in durch TrailingStepPips definierten Schritten.
  • Die Strategie erfordert, dass das Wertpapier über einen gültigen PriceStep und Decimals verfügt, um Pips in Preis-Offsets umzuwandeln. Sofern das Instrument diese nicht bereitstellt, fallen die Vorgaben auf eine absolute Preiseinheit zurück.
  • Wenn MaxPositions größer als eins ist, kann die Strategie durch wiederholtes Hinzufügen von TradeVolume unter Berücksichtigung des maximalen Expositionslimits schrittweise erweitert werden.
  • Wenn UseTimeControl aktiviert ist und die Start- und Endzeiten übereinstimmen, ist der Handel deaktiviert, um mehrdeutige Sitzungen zu vermeiden.
  • Die Logik wirkt nur auf geschlossene Kerzen; Es erfolgt keine Übermittlung einer Intra-Bar-Order, was dem Verhalten der Vorlage MQL entspricht.
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>
/// Simplified from "OsMA Four Colors Arrow" MetaTrader expert.
/// Uses MACD histogram (OsMA) zero-crossing as entry signal.
/// Buys when histogram crosses above zero, sells when it crosses below.
/// </summary>
public class OsMaFourColorsArrowStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;

	private MovingAverageConvergenceDivergence _macd;
	private readonly Queue<decimal> _macdHistory = new();
	private decimal? _prevHistogram;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public int SignalPeriod
	{
		get => _signalPeriod.Value;
		set => _signalPeriod.Value = value;
	}

	public OsMaFourColorsArrowStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe used for signal generation", "General");

		_fastPeriod = Param(nameof(FastPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA length for MACD", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA length for MACD", "Indicators");

		_signalPeriod = Param(nameof(SignalPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "Signal line smoothing period", "Indicators");
	}

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

		_prevHistogram = null;
		_macdHistory.Clear();

		_macd = new MovingAverageConvergenceDivergence
		{
			ShortMa = { Length = FastPeriod },
			LongMa = { Length = SlowPeriod },
		};

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

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

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

		if (!_macd.IsFormed)
			return;

		// Compute signal line as SMA of MACD values
		_macdHistory.Enqueue(macdValue);
		if (_macdHistory.Count > SignalPeriod)
			_macdHistory.Dequeue();

		if (_macdHistory.Count < SignalPeriod)
		{
			_prevHistogram = null;
			return;
		}

		decimal sum = 0;
		var history = _macdHistory.ToArray();
		foreach (var v in history)
			sum += v;
		var signal = sum / history.Length;

		// OsMA = MACD - Signal (histogram)
		var histogram = macdValue - signal;

		if (_prevHistogram is null)
		{
			_prevHistogram = histogram;
			return;
		}

		var volume = Volume;
		if (volume <= 0)
			volume = 1;

		var crossUp = _prevHistogram.Value <= 0 && histogram > 0;
		var crossDown = _prevHistogram.Value >= 0 && histogram < 0;

		if (crossUp)
		{
			if (Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
		}
		else if (crossDown)
		{
			if (Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
		}

		_prevHistogram = histogram;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_macd = null;
		_prevHistogram = null;
		_macdHistory.Clear();

		base.OnReseted();
	}
}