Auf GitHub ansehen

Crypto Scalper-Strategie

Die Crypto Scalper-Strategie reproduziert die ursprüngliche MetaTrader-Expertenlogik mit StockSharp-High-Level-Komponenten. Sie überwacht einen bullischen oder bärischen Crossover eines schnellen linear gewichteten gleitenden Durchschnitts auf dem primären Zeitrahmen und bestätigt das Setup mit Trendfiltern, die auf einem höheren Zeitrahmen berechnet werden. Sobald die Bedingungen übereinstimmen, steigt die Strategie mit Market-Orders ein und verwaltet Ausstiege durch Stop-Loss- und Take-Profit-Abstände in MetaTrader-Pips.

Parameter

Name Beschreibung Standard
Primary Candle Kerzentyp auf dem Haupt-Zeitrahmen verarbeitet. 1-Minuten-Zeitrahmen
Higher Candle Höherer Zeitrahmen-Kerzentyp für Bestätigung. 15-Minuten-Zeitrahmen
Fast LWMA Länge des primären linear gewichteten gleitenden Durchschnitts. 8
Higher Fast MA Schnelle LWMA-Länge auf dem Bestätigungs-Zeitrahmen. 6
Higher Slow MA Langsame LWMA-Länge auf dem Bestätigungs-Zeitrahmen. 85
Momentum Period Momentum-Indikatorlänge auf höheren Zeitrahmen-Kerzen. 14
Momentum Threshold Minimale Abweichung vom Referenz-Momentum (MetaTrader-Basislinie 100) für den Handel. 0.3
Momentum Reference Referenzniveau zur Emulation des MetaTrader-Momentum-Skalierens. 100
Stop Loss (pips) Schutz-Stop-Distanz in MetaTrader-Pips. 20
Take Profit (pips) Schutz-Gewinn-Distanz in MetaTrader-Pips. 50
Volume Ordervolumen in Lots. 0.01
MACD Fast Schnelle EMA-Periode für MACD-Bestätigung. 12
MACD Slow Langsame EMA-Periode für MACD-Bestätigung. 26
MACD Signal Signal-EMA-Periode für MACD-Bestätigung. 9

Trading-Logik

  1. Den primären Zeitrahmen abonnieren und eine LWMA berechnen, die schnell auf den Preis reagiert.
  2. Einen Einstieg erkennen, wenn die vorherige Kerze die LWMA nach oben (Long) oder nach unten (Short) kreuzt.
  3. Den Crossover mit den höheren Zeitrahmen-Filtern bestätigen:
    • Höherer schneller LWMA muss über dem höheren langsamen LWMA für Long-Einstiege und darunter für Short-Einstiege bleiben.
    • MACD-Histogramm (Haupt minus Signal) muss für Longs positiv und für Shorts negativ sein.
    • Momentum muss vom Referenzniveau um mindestens Momentum Threshold abweichen.
  4. Eine Market-Order in der erkannten Richtung senden, wenn keine anderen Orders aktiv sind und die aktuelle Position es erlaubt.
  5. Folgekerzen überwachen und die Position schließen, wenn der Stop-Loss- oder Take-Profit-Preis berührt wird.

Hinweise

  • Die Strategie verwendet StockSharp-High-Level-Subscriptions mit Bind und vermeidet manuelle Indikatorbuffer.
  • Schutzlevel werden bei jeder Kerze unter Verwendung des Wertpapier-Preisschritts neu berechnet. Ein Fallback-Schritt von 0.0001 wird angewendet, wenn das Instrument keinen konfigurierten Preisschritt aufweist.
  • Es ist nur eine Position gleichzeitig erlaubt. Nachfolgende Signale werden ignoriert, bis der bestehende Trade abgeschlossen ist.
  • Alle Inline-Kommentare innerhalb der C#-Implementierung sind gemäß den Repository-Richtlinien auf Englisch geschrieben.
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 CryptoScalperStrategy : 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 CryptoScalperStrategy()
	{
		_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;
	}
}