Auf GitHub ansehen

Boring-EA2-Alarm

Überblick

Boring EA2 Alert bildet die Benachrichtigungslogik des MetaTrader-4-Expert-Advisors boring-ea2 nach. Die Strategie hört auf abgeschlossene Kerzen, berechnet drei einfache gleitende Durchschnitte (SMA 3, SMA 20, SMA 150) und gibt informative Logs aus, wenn ein Crossover zwischen den Durchschnitten auftritt. Die Implementierung vermeidet bewusst Orderplatzierung: Ziel ist es, Tradern rechtzeitige Alarme zu geben, die sie mit diskretionärer Ausführung oder anderen automatisierten Strategien kombinieren können.

Strategielogik

Verfolgung gleitender Durchschnitte

  • Kurzfristiger Bias: Eine 3-Perioden-SMA reagiert auf unmittelbare Preisänderungen.
  • Mittlerer Trend: Eine 20-Perioden-SMA glättet den Preis über den kurzfristigen Swing-Horizont.
  • Langer Trend: Eine 150-Perioden-SMA repräsentiert den dominanten Hintergrundtrend.

Crossover-Erkennung

  • SMA3 vs SMA20: meldet "crossed up", wenn SMA3 über SMA20 steigt, und "crossed down", wenn sie darunter fällt. Interne Flags stellen sicher, dass jeder Übergang einmal gemeldet wird.
  • SMA3 vs SMA150: spiegelt dieselbe Logik gegenüber dem langfristigen Durchschnitt, um Momentum-Schübe oder Umkehrungen gegen den vorherrschenden Trend zu erkennen.
  • SMA20 vs SMA150: fügt eine mittel-/langfristige Bestätigungsebene hinzu, sodass Verschiebungen in der höheren Zeitrahmenstruktur eigene Alarme auslösen.
  • Initialisierungsschutz: Die erste abgeschlossene Kerze setzt nur den Anfangszustand. Alarme beginnen mit der zweiten abgeschlossenen Kerze, sobald eine echte Beziehungsänderung beobachtet wird.

Benachrichtigungsformat

  • Alarme spiegeln die ursprüngliche EA-Nachricht: Alert!!! - SYMBOL - TF - description.
  • Der Zeitrahmencode wird aus dem konfigurierten Kerzentyp abgeleitet. Standard-Labels im MetaTrader-Stil (M1, M5, H1 usw.) werden verwendet, wenn verfügbar; andere Zeitrahmen fallen auf kompakte Notation zurück (z. B. M45 oder D2).
  • Nachrichten werden mit AddInfoLog geschrieben und können an Log-Viewer, Skripte oder GUI-Dashboards weitergeleitet werden.

Parameter

  • Short SMA Length: Anzahl Perioden für den schnellen gleitenden Durchschnitt (Standard 3).
  • Medium SMA Length: Anzahl Perioden für den mittleren gleitenden Durchschnitt (Standard 20).
  • Long SMA Length: Anzahl Perioden für den langsamen gleitenden Durchschnitt (Standard 150).
  • Candle Type: Zeitrahmen zur Berechnung der gleitenden Durchschnitte. Standard sind 1-Minuten-Kerzen, passend zu den tickbasierten Prüfungen des EA mit hoher Reaktivität.

Zusätzliche Hinweise

  • Die Strategie sendet, ändert oder storniert keine Orders. Sie ist rein informativ.
  • Da Bind finalisierte Werte liefert, wird jedes Crossover auf abgeschlossenen Kerzen bewertet. Dies vermeidet die lauten Intrabar-Wechsel, die der ursprüngliche EA durch Tick-Zählung abmilderte.
  • Logging-basierte Benachrichtigungen können mit eigenen Handlern integriert werden, indem innerhalb einer Host-Anwendung Strategie-Logereignisse abonniert werden.
  • Derzeit wird keine Python-Übersetzung bereitgestellt; nur die C#-Version ist im API-Paket enthalten.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Boring EA2 strategy: Triple SMA crossover.
/// Buys when fast crosses above medium while medium above slow.
/// Sells when fast crosses below medium while medium below slow.
/// </summary>
public class BoringEa2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;

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

	public BoringEa2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

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

		var fast = new SimpleMovingAverage { Length = 10 };
		var med = new SimpleMovingAverage { Length = 20 };
		var slow = new SimpleMovingAverage { Length = 40 };

		decimal? prevFast = null;
		decimal? prevMed = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, med, slow, (candle, fastVal, medVal, slowVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevFast.HasValue && prevMed.HasValue)
				{
					var fastCrossUp = prevFast.Value <= prevMed.Value && fastVal > medVal;
					var fastCrossDown = prevFast.Value >= prevMed.Value && fastVal < medVal;

					if (fastCrossUp && medVal > slowVal && Position <= 0)
						BuyMarket();
					else if (fastCrossDown && medVal < slowVal && Position >= 0)
						SellMarket();
				}

				prevFast = fastVal;
				prevMed = medVal;
			})
			.Start();

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