Auf GitHub ansehen

Premarket Gap MomoTrader Strategie

Diese Strategie handelt einen einzelnen Long-Ausbruch während der Vorbörsensitzung, wenn die aktuelle Kerze mindestens einen angegebenen Prozentsatz über dem vorherigen Schlusskurs gewinnt, eine bullishe Kerze mit ausreichend Volumen druckt und der Kerzenkörper einen großen Teil seiner Spanne einnimmt. Die Positionsgröße wird je nach Körpergröße skaliert.

Nach dem Einstieg hält die Strategie die Position, solange die nächsten Kerzen bullish bleiben und ihr Volumen zunimmt. Eine rote Kerze oder nicht zunehmendes Volumen schließt die Position. Pro Tag ist nur ein Trade erlaubt und der Handel kann auf die Sitzung 04:00–09:30 beschränkt werden.

Details

  • Einstiegskriterien:
    • Gewinn der aktuellen Kerze ≥ MinGainPct im Vergleich zum vorherigen Schluss.
    • Kerze ist grün und Volume > MinVolume.
    • Körperprozent definiert Positionsgröße: ≥90% → 100%, ≥85% → 50%, ≥75% → 25%.
    • Optionaler Sitzungsfilter 04:00–09:30 wenn UseSession aktiviert ist.
  • Ausstiegskriterien:
    • Erste rote Kerze oder Kerze mit nicht zunehmendem Volumen nach dem Einstieg.
  • Stops: Nein.
  • Standardwerte:
    • MinGainPct = 5.
    • MinVolume = 15000.
    • UseSession = true.
  • Filter:
    • Kategorie: Momentum
    • Richtung: Long
    • Indikatoren: Keine
    • Stops: Nein
    • Komplexität: Mittel
    • Zeitrahmen: Intraday
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>
/// Premarket Gap MomoTrader strategy using EMA crossover.
/// </summary>
public class PremarketGapMomoTraderStrategy : Strategy
{
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	/// <summary>
	/// Slow EMA period.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

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

	/// <summary>
	/// Initializes a new instance.
	/// </summary>
	public PremarketGapMomoTraderStrategy()
	{
		_slowLength = Param(nameof(SlowLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

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

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

		var fast = new ExponentialMovingAverage { Length = 14 };
		var slow = new ExponentialMovingAverage { Length = SlowLength };

		var prevF = 0m;
		var prevS = 0m;
		var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, (candle, f, s) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!fast.IsFormed || !slow.IsFormed)
					return;

				if (!init)
				{
					prevF = f;
					prevS = s;
					init = true;
					return;
				}

				if (candle.OpenTime - lastSignal >= cooldown)
				{
					if (prevF <= prevS && f > s && Position <= 0)
					{
						BuyMarket();
						lastSignal = candle.OpenTime;
					}
					else if (prevF >= prevS && f < s && Position >= 0)
					{
						SellMarket();
						lastSignal = candle.OpenTime;
					}
				}

				prevF = f;
				prevS = s;
			})
			.Start();

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