Auf GitHub ansehen

Crypto-Analysis-Strategie

Überblick

Diese Strategie ist ein StockSharp-Port des MetaTrader-4-Expert-Advisors "Crypto Analysis". Sie sucht nach Ausbrüchen, die auftreten, nachdem der Preis das äußere Bollinger-Band im Haupt-Handelszeitrahmen berührt, während die Marktstruktur bärisch bleibt (schnelle LWMA unter der langsamen LWMA). Das System erlaubt Trades nur, wenn ein Momentum-Schub im höheren Zeitrahmen und ein monatlicher MACD-Filter mit der gewünschten Richtung übereinstimmen. Nach dem Einstieg wird die Position durch einen mehrschichtigen Schutzblock verwaltet, der den ursprünglichen EA nachbildet: pipbasierte Stops, geldbasierter Trail, Break-even-Verschiebung und Portfolio-Drawdown-Kontrollen.

Handelslogik

  • Signalzeitrahmen: konfigurierbar (standardmäßig M15). Alle Ein-/Ausstiegsregeln werden auf diesen Kerzen ausgewertet.
  • Volatilitätsauslöser: Das Tief der vorherigen Kerze muss das untere Bollinger-Band (20, 2) berühren oder durchstoßen, um ein Long-Setup vorzubereiten; eine Berührung des oberen Bands bereitet ein Short-Setup vor.
  • Trendfilter: Beide Szenarien verlangen, dass die schnelle linear gewichtete gleitende Durchschnittslinie (LWMA, Standard 6) unter der langsamen LWMA (Standard 85) bleibt, wodurch der bärische Bias des EA repliziert wird.
  • RSI-Bestätigung: RSI(14) muss für Longs über 50 und für Shorts unter 50 liegen.
  • Momentum-Schub: Die maximale absolute Abweichung der letzten drei Momentum(14)-Werte des höheren Zeitrahmens von der 100-Basislinie muss die Kauf-/Verkaufsschwellen überschreiten. Dies erfasst die Momentum-Spitzen des MQL-Codes.
  • Monatlicher MACD-Filter: Ein separater monatlicher MACD (standardmäßig 30-Tage-Kerzen) (12, 26, 9) bestätigt die Richtung; Longs erfordern MACD-Hauptlinie über Signal, Shorts das Gegenteil.
  • Einstiegsausführung: Sobald alle Filter übereinstimmen, eröffnet die Strategie eine Marktorder. Gegenpositionen werden vor einer Umkehr glattgestellt, um eine einzelne Nettoposition zu behalten, was dem Verhalten des EA beim Schließen entgegengesetzter Trades entspricht.

Positionsverwaltung

  • Anfänglicher Stop und Ziel: Konfigurierbare Distanzen in Pips werden aus der Tick-Größe des Instruments mit derselben 5-/3-stelligen Behandlung wie im EA umgerechnet (0.00001- und 0.001-Schritte werden mit 10 multipliziert).
  • Trailing Stop: Nach einem neuen Hoch (Long) oder Tief (Short) wird der Stop um TrailingStopPips hinter dem Preis nachgezogen, wobei immer das beste erreichte Niveau respektiert wird.
  • Break-even: Wenn der Gewinn BreakEvenTriggerPips erreicht, wird der Stop auf den Einstiegspreis plus BreakEvenOffsetPips (Long) oder minus den Offset (Short) verschoben.
  • Geldziele: Optionale absolute oder prozentbasierte Gewinnobergrenzen schließen die Position, sobald der schwebende PnL das angeforderte Niveau erreicht.
  • Geldbasierter Trail: Sobald der nicht realisierte Gewinn MoneyTrailTarget überschreitet, verfolgt die Strategie den Spitzenwert und schließt die Position, wenn die Rückgabe MoneyTrailStop erreicht oder überschreitet.
  • Equity-Stop: Die schwebende Equity (aktueller Portfoliowert plus nicht realisierter PnL) wird überwacht; wenn der Drawdown vom Höchstwert EquityRiskPercent überschreitet, wird die Position glattgestellt.

Multi-Zeitrahmen-Daten

Drei Abonnements werden automatisch registriert:

  1. Primäre Kerzenserie für Bollinger-/LWMA-/RSI-Regeln.
  2. Kerzen des höheren Zeitrahmens für den Momentum-Filter (standardmäßig H1).
  3. Monatskerzen für die MACD-Bestätigung (standardmäßig 30-Tage-Bars).

Parameter

Parameter Beschreibung
OrderVolume Basisordergröße. Gegenpositionen werden vor dem Öffnen einer neuen Position geschlossen.
UseMoneyTakeProfit Aktiviert das absolute monetäre Take-Profit-Ziel.
MoneyTakeProfit Gewinn in Portfoliowährung, der einen Ausstieg auslöst, wenn UseMoneyTakeProfit wahr ist.
UsePercentTakeProfit Aktiviert das prozentbasierte Take-Profit-Ziel, berechnet aus der Anfangsequity.
PercentTakeProfit Gewinnprozentsatz, der zum Schließen der Position erforderlich ist, wenn das Prozentziel aktiv ist.
EnableMoneyTrailing Aktiviert den geldbasierten Trailing-Block.
MoneyTrailTarget Gewinnniveau, ab dem der Geld-Trail startet.
MoneyTrailStop Maximal erlaubte Gewinnrückgabe nach Erreichen von MoneyTrailTarget.
StopLossPips Anfängliche Stop-Loss-Distanz in Pips.
TakeProfitPips Anfängliche Take-Profit-Distanz in Pips.
TrailingStopPips Trailing-Stop-Distanz in Pips.
UseBreakEven Aktiviert die Break-even-Verschiebung des Stops.
BreakEvenTriggerPips Pip-Gewinn, der vor Aktivierung des Break-even-Schutzes erforderlich ist.
BreakEvenOffsetPips Zusätzliche Pips zum Einstiegspreis beim Setzen des Break-even-Stops.
FastMaPeriod Länge der schnellen LWMA auf typischem Preis.
SlowMaPeriod Länge der langsamen LWMA auf typischem Preis.
MomentumPeriod Periode des Momentum-Indikators im höheren Zeitrahmen.
MomentumBuyThreshold Minimale Momentum-Abweichung für Long-Einstiege.
MomentumSellThreshold Minimale Momentum-Abweichung für Short-Einstiege.
MacdFastLength Schnelle EMA-Länge für den MACD-Filter des höheren Zeitrahmens.
MacdSlowLength Langsame EMA-Länge für den MACD-Filter des höheren Zeitrahmens.
MacdSignalLength Signallänge für den MACD-Filter des höheren Zeitrahmens.
UseEquityStop Aktiviert den Portfolio-Drawdown-Schutz.
EquityRiskPercent Erlaubter Equity-Drawdown-Prozentsatz, bevor die Position zwangsweise geschlossen wird.
CandleType Primärer Zeitrahmen für Einstiege.
MomentumCandleType Höherer Zeitrahmen für die Momentum-Bestätigung.
MacdCandleType Höherer Zeitrahmen für die MACD-Bestätigung.

Hinweise

  • Der StockSharp-Port behält eine einzelne Nettoposition bei und entspricht damit dem EA, der Gegenorders vor einem neuen Trade schließt.
  • Alle Schutzregeln arbeiten auf geschlossenen Kerzen, um die "neue Kerze"-Verarbeitung des ursprünglichen Skripts nachzubilden.
  • Bei synthetischen Symbolen oder Instrumenten ohne Standard-Pip-Größe passen Sie StopLossPips und verwandte Parameter an den Tick-Wert der Börse an.
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;

public class CryptoAnalysisStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public CryptoAnalysisStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}