Martingail Expert ist eine trendfolgende Martingal-Strategie, die auf dem Stochastic-Oszillator basiert, um neue Handelssequenzen zu timen. Sobald der Indikator eine Richtung generiert, startet die Strategie eine Leiter von Marktaufträgen und verwaltet das Risiko mithilfe eines dynamischen Gewinnziels und eines geometrischen Positionsgrößenschemas.
Handelslogik
Berechnen Sie einen Stochastic-Oszillator für die konfigurierte Kerzenreihe. Die aktuellsten Endwerte von %K und %D werden zur Entscheidungsfindung zwischengespeichert.
Starten Sie eine neue lange Sequenz, wenn %K (previous) > %D (previous) und %D (previous) über dem Schwellenwert BuyLevel liegen.
Starten Sie eine neue kurze Sequenz, wenn %K (previous) < %D (previous) und %D (previous) unter dem Schwellenwert SellLevel liegen.
Nach Eingabe einer Sequenz fügt jede günstige Preisbewegung von ProfitFactor × openOrders Pips eine neue Position mit dem Basisvolumen hinzu.
Jede negative Bewegung von StepPoints Pips multipliziert das zuletzt gefüllte Volumen mit Multiplier und sendet eine durchschnittliche Order in die gleiche Richtung.
Ausgangsregeln
Schließen Sie die gesamte Position, sobald der letzte Füllpreis ein dynamisches Gewinnziel bei ProfitFactor × openOrders Pips in die günstige Richtung erreicht.
Setzen Sie den Martingal-Status zurück, wenn die aggregierte Positionsgröße auf Null zurückkehrt.
Risikomanagement
Die Martingal-Progression erhöht das Engagement schnell, wenn sich der Preis gegen die Position bewegt. Passen Sie Multiplier, StepPoints und ProfitFactor sorgfältig an, um sie an die Kontogröße und die Instrumentenvolatilität anzupassen.
Parameter
Name
Beschreibung
Volume
Basis-Market-Order-Volumen, das für den ersten Trade und alle vorteilhaften Add-Ons verwendet wird.
Multiplier
Faktor, der bei der Mittelung bei ungünstigen Bewegungen auf das zuletzt ausgeführte Volumen angewendet wird.
StepPoints
Entfernung in Punkten, die eine Martingal-Mittelungsreihenfolge auslöst.
ProfitFactor
Gewinnziel pro offener Order, ausgedrückt in Punkten. Die tatsächliche Entfernung beträgt ProfitFactor × number_of_orders.
KPeriod
Lookback-Länge für die %K-Zeile.
DPeriod
Glättungslänge für die %D-Linie.
Slowing
Zusätzliche Glättung wurde auf %K vor dem Vergleich mit %D angewendet.
BuyLevel
Mindestwert %D erforderlich, um eine neue lange Sequenz zu ermöglichen.
SellLevel
Maximaler %D-Wert erforderlich, um eine neue kurze Sequenz zu ermöglichen.
CandleType
Für Berechnungen verwendete Kerzenserie (Standard: 5-Minuten-Zeitrahmen).
Notizen
Funktioniert am besten bei flüssigen FX-Paaren, bei denen Pip-Größe und Volumenschritt eine granulare Skalierung ermöglichen.
Erfordert ausreichend Spielraum, um mehreren Martingalschritten standzuhalten.
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>
/// Martingale strategy driven by stochastic oscillator crossovers.
/// Buy when K crosses above D, sell when K crosses below D.
/// Doubles down on adverse moves with martingale averaging.
/// </summary>
public class MartingailExpertSequenceStrategy : Strategy
{
private readonly StrategyParam<int> _kPeriod;
private readonly StrategyParam<int> _dPeriod;
private readonly StrategyParam<decimal> _stepPoints;
private readonly StrategyParam<decimal> _takeProfitPoints;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevK;
private decimal? _prevD;
private decimal _entryPrice;
public int KPeriod { get => _kPeriod.Value; set => _kPeriod.Value = value; }
public int DPeriod { get => _dPeriod.Value; set => _dPeriod.Value = value; }
public decimal StepPoints { get => _stepPoints.Value; set => _stepPoints.Value = value; }
public decimal TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MartingailExpertSequenceStrategy()
{
_kPeriod = Param(nameof(KPeriod), 14)
.SetDisplay("K Period", "Stochastic K period", "Indicators");
_dPeriod = Param(nameof(DPeriod), 3)
.SetDisplay("D Period", "Stochastic D period", "Indicators");
_stepPoints = Param(nameof(StepPoints), 500m)
.SetDisplay("Step Points", "Distance for martingale averaging", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 200m)
.SetDisplay("Take Profit", "Take profit in price steps", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevK = null;
_prevD = null;
_entryPrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevK = null;
_prevD = null;
var stoch = new StochasticOscillator
{
K = { Length = KPeriod },
D = { Length = DPeriod }
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(stoch, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!stochValue.IsFinal)
return;
if (stochValue is not StochasticOscillatorValue stoch)
return;
if (stoch.K is not decimal k || stoch.D is not decimal d)
return;
var step = Security?.PriceStep ?? 1m;
if (step <= 0) step = 1m;
// Check take profit
if (Position > 0 && candle.ClosePrice >= _entryPrice + TakeProfitPoints * step)
{
SellMarket();
_prevK = k;
_prevD = d;
return;
}
else if (Position < 0 && candle.ClosePrice <= _entryPrice - TakeProfitPoints * step)
{
BuyMarket();
_prevK = k;
_prevD = d;
return;
}
if (_prevK is not decimal prevK || _prevD is not decimal prevD)
{
_prevK = k;
_prevD = d;
return;
}
// Stochastic crossover signals
var bullCross = prevK <= prevD && k > d;
var bearCross = prevK >= prevD && k < d;
if (Position == 0)
{
if (bullCross)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
}
else if (bearCross)
{
SellMarket();
_entryPrice = candle.ClosePrice;
}
}
else if (Position > 0 && bearCross)
{
SellMarket(); // Close long
SellMarket(); // Open short
_entryPrice = candle.ClosePrice;
}
else if (Position < 0 && bullCross)
{
BuyMarket(); // Close short
BuyMarket(); // Open long
_entryPrice = candle.ClosePrice;
}
_prevK = k;
_prevD = d;
}
}
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 StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class martingail_expert_sequence_strategy(Strategy):
"""
Martingale Expert Sequence: stochastic K/D crossover with take profit.
"""
def __init__(self):
super(martingail_expert_sequence_strategy, self).__init__()
self._k_period = self.Param("KPeriod", 14).SetDisplay("K Period", "Stochastic K", "Indicators")
self._d_period = self.Param("DPeriod", 3).SetDisplay("D Period", "Stochastic D", "Indicators")
self._take_profit_points = self.Param("TakeProfitPoints", 200.0).SetDisplay("Take Profit", "TP in price steps", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candles", "General")
self._prev_k = None
self._prev_d = None
self._entry_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(martingail_expert_sequence_strategy, self).OnReseted()
self._prev_k = None
self._prev_d = None
self._entry_price = 0.0
def OnStarted2(self, time):
super(martingail_expert_sequence_strategy, self).OnStarted2(time)
stoch = StochasticOscillator()
stoch.K.Length = self._k_period.Value
stoch.D.Length = self._d_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(stoch, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, stoch)
self.DrawOwnTrades(area)
def _process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
k_val = stoch_value.K
d_val = stoch_value.D
if k_val is None or d_val is None:
return
k = float(k_val)
d = float(d_val)
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
tp = float(self._take_profit_points.Value)
if self.Position > 0 and close >= self._entry_price + tp * step:
self.SellMarket()
self._prev_k = k
self._prev_d = d
return
elif self.Position < 0 and close <= self._entry_price - tp * step:
self.BuyMarket()
self._prev_k = k
self._prev_d = d
return
if self._prev_k is None or self._prev_d is None:
self._prev_k = k
self._prev_d = d
return
bull_cross = self._prev_k <= self._prev_d and k > d
bear_cross = self._prev_k >= self._prev_d and k < d
if self.Position == 0:
if bull_cross:
self.BuyMarket()
self._entry_price = close
elif bear_cross:
self.SellMarket()
self._entry_price = close
elif self.Position > 0 and bear_cross:
self.SellMarket()
self.SellMarket()
self._entry_price = close
elif self.Position < 0 and bull_cross:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._prev_k = k
self._prev_d = d
def CreateClone(self):
return martingail_expert_sequence_strategy()