Auf GitHub ansehen

MA Rounding Candle-Strategie

Überblick

Diese Strategie ist eine Interpretation des originalen MQL5-Expertenberaters "MA Rounding Candle". Sie verwendet zwei geglättete gleitende Durchschnitte, die auf die Eröffnungs- und Schlusskurse der Kerzen angewendet werden. Die relative Position dieser Durchschnitte definiert die Farbe einer synthetischen Kerze: grün, wenn der geglättete Schlusskurs über der Eröffnung liegt, rot, wenn der Schluss unterhalb der Eröffnung liegt, und grau, wenn beide gleich sind. Ein Farbwechsel gegenüber dem vorherigen Balken erzeugt Handelssignale.

Algorithmus

  1. Für jede abgeschlossene Kerze werden die Eröffnungs- und Schlusswerte mit einem einfachen gleitenden Durchschnitt konfigurierbarer Länge geglättet.
  2. Die Kerzenfarbe wird durch den Vergleich der geglätteten Werte definiert:
    • Aufwärtskerze – der geglättete Schlusskurs ist höher als die geglättete Eröffnung.
    • Abwärtskerze – der geglättete Schlusskurs ist niedriger als die geglättete Eröffnung.
    • Neutral – beide Werte sind gleich.
  3. War die vorherige Kerze eine Aufwärtskerze und ist die aktuelle keine Aufwärtskerze, eröffnet die Strategie eine Long-Position und schließt alle Short-Positionen.
  4. War die vorherige Kerze eine Abwärtskerze und ist die aktuelle keine Abwärtskerze, eröffnet die Strategie eine Short-Position und schließt alle Long-Positionen.

Parameter

  • MaLength – Periode der glättenden gleitenden Durchschnitte (Standard 12).
  • CandleType – Zeitrahmen der verarbeiteten Kerzen.

Hinweise

Die Strategie zeigt, wie Signale eines benutzerdefinierten Indikators ausschließlich mit integrierten StockSharp-Tools nachgebildet werden können. Es wird kein Stop-Loss oder Take-Profit verwendet; Positionen werden sofort umgekehrt, wenn das gegenteilige Signal erscheint.

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>
/// MA Rounding Candle strategy.
/// Opens a long position when a smoothed candle is bullish and a short position when it is bearish.
/// </summary>
public class MaRoundingCandleStrategy : Strategy
{
	private readonly StrategyParam<int> _maLength;
	private readonly StrategyParam<DataType> _candleType;

	private ExponentialMovingAverage _openMa;
	private ExponentialMovingAverage _closeMa;
	private int _prevColor = 1;

	public MaRoundingCandleStrategy()
	{
		_maLength = Param(nameof(MaLength), 12)
			.SetDisplay("MA Length", "Moving average length", "Parameters");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame());
	}

	public int MaLength { get => _maLength.Value; set => _maLength.Value = value; }

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_openMa = default;
		_closeMa = default;
		_prevColor = 1;
	}

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

		_openMa = new ExponentialMovingAverage { Length = MaLength };
		_closeMa = new ExponentialMovingAverage { Length = MaLength };

		Indicators.Add(_openMa);
		Indicators.Add(_closeMa);

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

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

		StartProtection(null, null);
	}

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

		var openVal = _openMa.Process(candle.OpenPrice, candle.OpenTime, true).ToDecimal();
		var closeVal = _closeMa.Process(candle.ClosePrice, candle.OpenTime, true).ToDecimal();

		if (!_openMa.IsFormed || !_closeMa.IsFormed)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var color = openVal < closeVal ? 2 : openVal > closeVal ? 0 : 1;

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

		_prevColor = color;
	}
}