Auf GitHub ansehen

PA-Oszillator-Strategie

Diese Strategie ist ein Port des MQL5-Experten Exp_PA_Oscillator.mq5. Sie wendet zwei exponentielle gleitende Durchschnitte (EMAs) auf die Schlusskurse der Kerzen an und analysiert die Ableitung ihrer Differenz.

Logik

  1. Schnellen und langsamen EMA berechnen.
  2. Die Differenz zwischen ihnen berechnen und ihre Änderung gegenüber dem vorherigen Wert verfolgen.
  3. Einen Farbcode für die Ableitung bestimmen:
    • 0 – Ableitung ist positiv und MACD steigt.
    • 1 – Ableitung ist null.
    • 2 – Ableitung ist negativ und MACD fällt.
  4. Die Farben der zwei letzten abgeschlossenen Kerzen verwenden, um Signale zu generieren:
    • Vor zwei Balken war die Farbe 0 und der vorherige Balken wechselte von 0 weg → Long-Position öffnen und Short-Position schließen.
    • Vor zwei Balken war die Farbe 2 und der vorherige Balken wechselte von 2 weg → Short-Position öffnen und Long-Position schließen.

Parameter

Name Beschreibung
FastLength Länge des schnellen EMA.
SlowLength Länge des langsamen EMA.
BuyPosOpen Öffnen von Long-Positionen aktivieren.
SellPosOpen Öffnen von Short-Positionen aktivieren.
BuyPosClose Schließen von Long-Positionen aktivieren.
SellPosClose Schließen von Short-Positionen aktivieren.
CandleType Kerzen-Zeitrahmen für Berechnungen.

Hinweise

  • Es werden nur abgeschlossene Kerzen verarbeitet.
  • Marktorders werden für Ein- und Ausstiege verwendet.
  • Diese Implementierung legt den Fokus auf Verständlichkeit und Lernzwecke, nicht auf Profitabilität.
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 the PA Oscillator indicator.
/// It trades when the derivative of the difference between fast and slow EMAs changes sign.
/// </summary>
public class PaOscillatorStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevMacd;
	private int? _prevColor;
	private int? _prevPrevColor;

	/// <summary>
	/// Length of the fast EMA.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Length of the slow EMA.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

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

	/// <summary>
	/// Initializes a new instance of the strategy.
	/// </summary>
	public PaOscillatorStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA Length", "Fast EMA period", "Indicators");

		_slowLength = Param(nameof(SlowLength), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA Length", "Slow EMA period", "Indicators");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMacd = null;
		_prevColor = null;
		_prevPrevColor = null;
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowLength };

		var subscription = SubscribeCandles(CandleType);

		subscription
			.Bind(fastEma, slowEma, ProcessCandle)
			.Start();

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

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

		var macd = fast - slow;

		if (_prevMacd is null)
		{
			_prevMacd = macd;
			_prevColor = 1;
			_prevPrevColor = 1;
			return;
		}

		var osc = macd - _prevMacd.Value;
		var color = osc > 0 ? 0 : osc < 0 ? 2 : 1;

		if (_prevPrevColor == 0 && _prevColor > 0)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		else if (_prevPrevColor == 2 && _prevColor < 2)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevMacd = macd;
		_prevPrevColor = _prevColor;
		_prevColor = color;
	}
}