Gselector-Musterwahrscheinlichkeitsstrategie
Überblick
Die Gselector Pattern Probability-Strategie ist eine StockSharp-Portierung des MetaTrader 4 „Gselector“-Experten. Es untersucht Richtungsänderungen synthetischer Preisreihen, die aus mehreren Schrittgrößen erstellt wurden, führt Wahrscheinlichkeitsstatistiken für jedes beobachtete Muster und handelt, wenn die Wahrscheinlichkeit einer Fortsetzungsbewegung hoch genug ist. Stop-Loss- und Take-Profit-Abstände werden in der Software simuliert, um das ursprüngliche Expertenverhalten widerzuspiegeln.
Lernprozess
- Synthetische Leitern – Für jedes konfigurierte Delta-Vielfache erstellt die Strategie eine stufenbasierte Reihe, indem der letzte Schlusskurs jedes Mal aufgezeichnet wird, wenn sich der Markt um die erforderliche Distanz bewegt.
- Musterkodierung – Eine Bitmaske wird erstellt, indem jedes Paar benachbarter Werte innerhalb der Leiter verglichen wird. Steigende Schritte erhalten das Bit
0, fallende Schritte erhalten das Bit 1, das die Ncomb-Codierung aus der MQL-Implementierung reproduziert.
- Ereignisverfolgung – Wenn ein neues Muster auftritt, startet die Strategie Beobachter für jedes konfigurierte Stoppniveau. Ein Beobachter speichert den Ursprungspreis und wartet, bis sich der Preis um den Schwellenwert nach oben oder unten bewegt.
- Wahrscheinlichkeitsaktualisierung – Sobald ein Beobachter fertig ist, erhöhen Aufwärtsbewegungen die „Wachstums“-Statistik, Abwärtsbewegungen erhöhen die „Abnahme“-Statistik. Ein Vergessensfaktor emuliert die Zerfallslogik (
forg) des ursprünglichen Experten.
- Persistenz im Speicher – Alle Statistiken werden im Speicher gehalten und beim Start der Strategie zurückgesetzt, was dem Verhalten der MQL-Version entspricht, wenn
ReadHistory deaktiviert ist.
Handelslogik
- Für das aktuelle Muster werden auf jeder Delta-Leiter Fortsetzungswahrscheinlichkeiten berechnet.
- Ein Kaufsignal erfordert:
- Wahrscheinlichkeit ≥
ProbabilityThreshold.
- Beobachtungen ≥
MinSamples.
- Die Abklingzeit seit dem letzten Kauf ist abgelaufen.
- Wenn eine Short-Position besteht, muss die neue Wahrscheinlichkeit die gespeicherte Verkaufswahrscheinlichkeit plus
ProbabilityBuffer überschreiten.
- Ein Verkaufssignal spiegelt die Kaufregeln mit vertauschten Wachstums-/Rückgangsrollen wider.
- Einträge verwenden
BuyMarket / SellMarket, um OrderSend zu emulieren. Wenn die entgegengesetzte Position offen ist, schließt die Strategie diese zuerst und reproduziert so das Umkehrverhalten des Expertenberaters.
- Schutzausstiege werden intern abgewickelt: Stops und Takes werden in Preiseinheiten ausgedrückt, die aus dem Punktwert und dem Stop-Level abgeleitet werden.
Parameter
| Name |
Beschreibung |
Standard |
CandleType |
Kerzendatentyp, der für den Backtest/die Live-Sitzung verwendet wird. |
Zeitrahmen von 1 Minute |
ProbabilityThreshold |
Mindestfortsetzungswahrscheinlichkeit, die zur Eröffnung eines Handels erforderlich ist. |
0,8 |
BaseDeltaPoints |
Basispunktabstand, der die erste synthetische Leiter definiert. |
1 |
DeltaSteps |
Anzahl der auszuwertenden Deltaleitern. |
20 |
PatternLength |
Anzahl der Elemente im Leiterverlauf. |
10 |
StopLevels |
Anzahl der Stop/Take-Levels. |
1 |
StopDistancePoints |
Basis-Stopp/Take-Distanz in Punkten. |
25 |
ForgetFactor |
Der Rückgang wird nach jeder Beobachtung auf die Wachstums-/Abnahmezähler angewendet. |
1.05 |
MinSamples |
Mindestanzahl abgeschlossener Beobachtungen. |
10 |
ProbabilityBuffer |
Zusätzliche Wahrscheinlichkeit erforderlich, um die Gegenposition zu schließen. |
0,05 |
FixedVolume |
Basishandelsvolumen. |
1 Los |
UseReinvest |
Ermöglicht eine Balance-proportionale Lautstärkeanpassung. |
wahr |
VolumeMode |
0 – fest, 1 – Prozent pro 10.000, 2 – Leiter, 3 – linear. |
1 |
PercentPer10k |
Prozentsatz pro 10.000 Einheiten im Modus 1. |
3 |
BaseDeposit |
Grundeinzahlung für die Modi 2 und 3. |
500 |
DepositStep |
Einzahlungserhöhung für die Modi 2 und 3. |
500 |
MaxVolume |
Maximale Lautstärkebegrenzung. |
10000 |
CooldownFactor |
Anzahl der Kerzenintervalle, die als Reaktivierungs-Cooldown verwendet werden. |
2 |
Unterschiede zum MQL Expert
- Die dateibasierte Persistenz wurde entfernt; Statistiken werden bei jedem Start der Strategie von Grund auf neu erstellt.
- Bestellungen werden durch
BuyMarket/SellMarket und Software-Stopp-Management anstelle von MT4 ausstehenden Bestellungen simuliert.
- Die Positionsgrößen-Helfer wurden an StockSharp Portfoliodaten angepasst. Liegen keine Eigenkapitalwerte vor, greift die Strategie auf das Fixvolumen zurück.
- Trailing-Stop-Eingaben aus dem Originalcode werden ignoriert, da sie in der MT4-Version nie angewendet wurden.
Nutzungshinweise
- Hängen Sie die Strategie mit einem gültigen
PriceStep an ein Wertpapier an. Wenn der Schritt unbekannt ist, fällt die Strategie auf 0,0001 zurück.
- Der Lernprozess erfordert eine Mindestanzahl an Leiteraktivierungen; Erwarten Sie eine Aufwärmphase, bevor der Handel beginnt.
- Durch Erhöhen von
DeltaSteps oder PatternLength steigt die Speichernutzung exponentiell, da das Musterwörterbuch schnell wächst.
- Der Standardwahrscheinlichkeitsschwellenwert (0,8) ist sehr streng. Senken Sie den Wert für häufigere Trades.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Gselector Pattern Probability strategy - SMA crossover with RSI filter.
/// Buys when fast SMA crosses above slow SMA and RSI is below overbought.
/// Sells when fast SMA crosses below slow SMA and RSI is above oversold.
/// </summary>
public class GselectorPatternProbabilityStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _overbought;
private readonly StrategyParam<decimal> _oversold;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GselectorPatternProbabilityStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI lookback", "Indicators");
_overbought = Param(nameof(Overbought), 75m)
.SetDisplay("Overbought", "RSI overbought level", "Levels");
_oversold = Param(nameof(Oversold), 25m)
.SetDisplay("Oversold", "RSI oversold level", "Levels");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
// Fast crosses above slow = buy
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Fast crosses below slow = sell
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class gselector_pattern_probability_strategy(Strategy):
def __init__(self):
super(gselector_pattern_probability_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10).SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30).SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14).SetDisplay("RSI Period", "RSI lookback", "Indicators")
self._overbought = self.Param("Overbought", 75.0).SetDisplay("Overbought", "RSI overbought level", "Levels")
self._oversold = self.Param("Oversold", 25.0).SetDisplay("Oversold", "RSI oversold level", "Levels")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def fast_period(self): return self._fast_period.Value
@property
def slow_period(self): return self._slow_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(gselector_pattern_probability_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(gselector_pattern_probability_strategy, self).OnStarted2(time)
self._has_prev = False
fast = SimpleMovingAverage()
fast.Length = self.fast_period
slow = SimpleMovingAverage()
slow.Length = self.slow_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.process_candle).Start()
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast)
slow_val = float(slow)
if not self._has_prev:
self._prev_fast = fast_val
self._prev_slow = slow_val
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return gselector_pattern_probability_strategy()