Auf GitHub ansehen

BandOsMaCustom-Strategie

Überblick

Diese Strategie ist eine direkte Portierung des MetaTrader 5-Expertenberaters unter MQL/45596/mql5/Experts/MQL5Book/p7/BandOsMACustom.mq5. Der ursprüngliche Roboter kombiniert das MACD-Histogramm (auch bekannt als OsMA) mit Bollinger-Bändern und a gleitender Durchschnitt, der auf die Histogrammwerte anstelle der Rohpreise angewendet wird. Immer wenn das Histogramm das untere Band durchbricht, eröffnet der Experte einen Long-Trade. während Berührungen des oberen Bandes kurze Eingaben auslösen. Das Histogramm kreuzt a Ein separater gleitender Durchschnitt schließt die Position. Ein Schutzstopp und a Trailing-Stop-Schritte (entspricht einem Fünfzigstel des Stops) halten das Risiko unter Kontrolle.

Die StockSharp-Implementierung behält dieses Verhalten mithilfe der übergeordneten API bei. So bleibt die Handelslogik innerhalb des Frameworks lesbar und debuggbar.

Conversion-Highlights

  • Das MACD-Histogramm wird implementiert durch MovingAverageConvergenceDivergenceHistogram, gefüttert mit dem Kerzenpreis, der entspricht dem vom AppliedPrice ausgewählten Modus MetaTrader PRICE_* Parameter.
  • Bollinger Bänder und der gleitende Ausstiegsdurchschnitt verarbeiten eher die OsMA-Ausgabe als Preisdaten. Ein kompakter Verlaufspuffer reproduziert die MetaTrader shift Argumente für beide Indikatoren.
  • Die Strategie behält die ursprüngliche Long/Short-Signalisierung bei: Kreuzungen unterhalb der Start-Longs des unteren Bandes, Kreuzungen über dem Start-Shorts des oberen Bandes und die OsMA überschreitet seinen gleitenden Durchschnitt und schließt den Handel.
  • StartProtection spiegelt den Stop-Loss-Plus-Trailing-Stop-Block MetaTrader wider. Der abschließende Schritt wird als StopLossPoints / 50 berechnet, genau wie der MQL Klasse TrailingStop hat es getan.

Indikatoren

Indikator Zweck
MovingAverageConvergenceDivergenceHistogram Erstellt die iOsMA-Ausgabe von MetaTrader neu.
BollingerBands Berechnet die oberen und unteren Schwellenwerte für das Histogramm.
Gleitender Durchschnitt (SMA/EMA/SMMA/LWMA) Der Filter wird beendet, wenn das Histogramm ihn überschreitet.

Parameter

Name Standard Beschreibung
CandleType 1-stündiger Zeitrahmen Primärer Zeitrahmen, der für alle Indikatorberechnungen verwendet wird.
FastOsmaPeriod 12 Schnelle EMA-Länge aus der OsMA-Berechnung.
SlowOsmaPeriod 26 Langsame EMA-Länge aus der OsMA-Berechnung.
SignalPeriod 9 Signallänge SMA aus der OsMA-Berechnung.
AppliedPrice Typisch Angewandter Preis im MetaTrader-Stil, der das Histogramm speist.
BandsPeriod 26 Länge der Bollinger-Bänder, die auf den Histogrammwerten gezeichnet werden.
BandsShift 0 Rechtsverschiebung (in Balken), angewendet auf die Bollinger-Werte.
BandsDeviation 2,0 Standardabweichungsmultiplikator für die Bänder.
MaPeriod 10 Länge des im Histogramm berechneten gleitenden Ausgangsdurchschnitts.
MaShift 0 Rechtsverschiebung (in Balken), angewendet auf den gleitenden Ausgangsdurchschnitt.
MaMethod Einfach Methode des gleitenden Durchschnitts (SMA, EMA, SMMA, LWMA).
StopLossPoints 1000 Schutzstoppabstand, ausgedrückt in Preisschritten.
OrderVolume 0,01 Handelsvolumen, identisch mit der Eingabe MetaTrader „Lots“.

Handelsregeln

  1. Abonnieren Sie die ausgewählte Kerzenserie und füttern Sie den gewählten Preis in das MACD-Histogramm ein.
  2. Übergeben Sie jeden Histogrammwert an die Bollinger-Bänder und den gleitenden Ausgangsdurchschnitt.
  3. Erkennen Sie Signale mithilfe der verschobenen Puffer:
    • Wenn das Histogramm durch das untere Band fällt, setzen Sie ein bullisches Signal.
    • Wenn das Histogramm durch das obere Band steigt, setzen Sie ein bärisches Signal.
    • Wenn das Histogramm den gleitenden Ausgangsdurchschnitt kreuzt, löschen Sie den aktiven Wert Signal, das das Schließen der Position ermöglicht.
  4. Positionen verwalten:
    • Schließen Sie bestehende Long-Positionen, wenn das bullische Signal verschwindet; enge Shorts wenn das bärische Signal verschwindet.
    • Eröffnen Sie eine Long-Position, wenn das bullische Signal aktiv ist und es keine Eröffnung gibt Position; Eröffnen Sie einen Short, wenn das rückläufige Signal aktiv ist und die Position aktiv ist flach.
  5. Wenden Sie StartProtection mit der konfigurierten Stop-Loss-Distanz und einem Trailing an Schritt entspricht StopLossPoints / 50 Preisschritten.

Notizen

  • Alle Kommentare im Quellcode sind auf Englisch, um dem Repository zu entsprechen Richtlinien.
  • Die Verlaufspuffer garantieren, dass die Version StockSharp MetaTrader berücksichtigt Parameter BandsShift und MaShift, ohne Indikatorwerte anzufordern Index.
  • Die Strategie entspricht den allgemeinen API-Konventionen: SubscribeCandles fördert die Aktualisierung von Indikatoren und direkte Aufrufe zur Nachahmung von BuyMarket/SellMarket die Auftragserteilung des ursprünglichen Sachverständigen.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy combining the MACD histogram (OsMA) with Bollinger Bands to trade reversals.
/// Similar to BandOsMa but with customizable moving average filter for exit signals.
/// </summary>
public class BandOsMaCustomStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<int> _macdSignalPeriod;
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<int> _maPeriod;

	private BollingerBands _bollinger;
	private SMA _osmaMA;

	private decimal _prevOsma;
	private decimal _prevUpper;
	private decimal _prevLower;
	private decimal _prevMa;
	private bool _hasPrev;

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

	public int MacdFastPeriod
	{
		get => _macdFastPeriod.Value;
		set => _macdFastPeriod.Value = value;
	}

	public int MacdSlowPeriod
	{
		get => _macdSlowPeriod.Value;
		set => _macdSlowPeriod.Value = value;
	}

	public int MacdSignalPeriod
	{
		get => _macdSignalPeriod.Value;
		set => _macdSignalPeriod.Value = value;
	}

	public int BollingerPeriod
	{
		get => _bollingerPeriod.Value;
		set => _bollingerPeriod.Value = value;
	}

	public decimal BollingerDeviation
	{
		get => _bollingerDeviation.Value;
		set => _bollingerDeviation.Value = value;
	}

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

	public BandOsMaCustomStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Primary timeframe", "General");

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 20)
			.SetDisplay("MACD Fast", "Fast EMA length", "Indicators");

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 50)
			.SetDisplay("MACD Slow", "Slow EMA length", "Indicators");

		_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 12)
			.SetDisplay("MACD Signal", "Signal EMA length", "Indicators");

		_bollingerPeriod = Param(nameof(BollingerPeriod), 14)
			.SetDisplay("Bollinger Period", "OsMA Bollinger Bands period", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetDisplay("Bollinger Deviation", "Bollinger Bands deviation", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 10)
			.SetDisplay("MA Period", "OsMA moving average period for exit filter", "Indicators");
	}

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

		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFastPeriod },
				LongMa = { Length = MacdSlowPeriod }
			},
			SignalMa = { Length = MacdSignalPeriod }
		};

		_bollinger = new BollingerBands
		{
			Length = BollingerPeriod,
			Width = BollingerDeviation
		};

		_osmaMA = new SMA { Length = MaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, ProcessCandle)
			.Start();

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

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

		var val = (IMovingAverageConvergenceDivergenceSignalValue)macdValue;
		if (val.Macd is not decimal macdLine || val.Signal is not decimal signalLine)
			return;

		var osma = macdLine - signalLine;

		var bbResult = (BollingerBandsValue)_bollinger.Process(new DecimalIndicatorValue(_bollinger, osma, candle.CloseTime));
		if (bbResult.UpBand is not decimal upper || bbResult.LowBand is not decimal lower)
			return;

		var maResult = _osmaMA.Process(new DecimalIndicatorValue(_osmaMA, osma, candle.CloseTime));
		if (maResult.IsEmpty)
			return;

		var ma = maResult.GetValue<decimal>();

		if (_hasPrev)
		{
			var buySignal = _prevOsma > _prevLower && osma <= lower && osma < ma;
			var sellSignal = _prevOsma < _prevUpper && osma >= upper && osma > ma;

			if (buySignal && Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + 1 : 1);
			else if (sellSignal && Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + 1 : 1);
		}

		_prevOsma = osma;
		_prevUpper = upper;
		_prevLower = lower;
		_prevMa = ma;
		_hasPrev = true;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_bollinger = null;
		_osmaMA = null;
		_prevOsma = 0;
		_prevUpper = 0;
		_prevLower = 0;
		_prevMa = 0;
		_hasPrev = false;

		base.OnReseted();
	}
}