Die Gap-Fill-Strategie nutzt Preislücken zwischen aufeinanderfolgenden 15-Minuten-Kerzen aus.
Wenn eine neue Kerze über dem Hoch der vorherigen Kerze um mehr als einen konfigurierbaren Schwellenwert öffnet, verkauft die Strategie und platziert ein Kauflimit am vorherigen Hoch, mit dem Ziel, dass die Lücke geschlossen wird.
Wenn eine Kerze unter dem vorherigen Tief um mehr als den Schwellenwert öffnet, kauft sie und platziert ein Verkaufslimit am vorherigen Tief.
Der Schwellenwert wird als MinGapSize Preisschritte plus dem aktuellen Spread zwischen bestem Geld- und Briefkurs berechnet.
Details
Einstiegskriterien: Lücke zwischen aktuellem Eröffnungskurs und vorherigem Hoch/Tief überschreitet MinGapSize plus Spread.
Long/Short: Beide Richtungen.
Ausstiegskriterien: Limitorder am Extrempunkt der vorherigen Kerze.
Stops: Nein.
Standardwerte:
MinGapSize = 1
Volume = 0.1
CandleType = 15 Minuten
Filter:
Kategorie: Gap
Richtung: Beide
Indikatoren: Keine
Stops: Nein
Komplexität: Grundlegend
Zeitrahmen: Intraday (15m)
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
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>
/// Gap fill strategy using Highest/Lowest channel breakout.
/// </summary>
public class GapFillStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GapFillStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Channel Period", "Highest/Lowest period", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "Data");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevHigh = 0;
_prevLow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
SubscribeCandles(CandleType)
.Bind(highest, lowest, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highVal, decimal lowVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevHigh = highVal;
_prevLow = lowVal;
_hasPrev = true;
return;
}
if (candle.ClosePrice > _prevHigh && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (candle.ClosePrice < _prevLow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevHigh = highVal;
_prevLow = lowVal;
}
}