Die Meeting Lines Stochastic-Strategie ist eine StockSharp-Implementierung des MetaTrader-Experten Expert_AML_Stoch. Es kombiniert die Candlestick-Umkehrmuster der Bullish/Bearish Meeting Lines mit einer Bestätigung durch die %D-Signallinie des Stochastic-Oszillators. Die Strategie richtet sich an diskretionäre Händler, die einen regelbasierten Ansatz zur Mustererkennung mit zusätzlicher Momentum-Bestätigung wünschen. Durch die Verwendung des High-Level-Codes StockSharp API bleibt der Code prägnant, testbar und lässt sich für das Portfoliomanagement oder die weitere Automatisierung leicht erweitern.
Handelslogik
Candlestick-Musterfilter
Die Strategie wertet kontinuierlich die letzten beiden abgeschlossenen Kerzen aus, um eine Meeting-Lines-Formation zu erkennen.
Ein bullisches Setup erfordert eine lange schwarze Kerze, gefolgt von einer langen weißen Kerze, deren Schlusskurs innerhalb von 10 % des vorherigen Schlusskurses liegt.
Ein bärisches Setup erfordert eine lange weiße Kerze, gefolgt von einer langen schwarzen Kerze mit der gleichen engen Ausrichtung von 10 %.
Die durchschnittliche Kerzenkörpergröße wird mit einem konfigurierbaren einfachen gleitenden Durchschnitt berechnet, um schwache Körper herauszufiltern.
Stochastic Bestätigung
Die %D-Signalleitung des Stochastic-Oszillators muss das Candlestick-Signal bestätigen.
Bullische Einstiege erfordern, dass %D unter dem konfigurierbaren Überverkaufsschwellenwert liegt (Standard 30).
Für bärische Einträge muss %D über dem konfigurierbaren Überkaufschwellenwert liegen (Standard 70).
Ausgangsregeln
Short-Positionen werden geschlossen, wenn %D entweder das untere Ausstiegsniveau (Standard 20) oder das obere Ausstiegsniveau (Standard 80) nach oben kreuzt.
Long-Positionen werden geschlossen, wenn %D die gleichen Niveaus nach unten kreuzt.
Umkehraufträge schließen automatisch bestehende Engagements und eröffnen eine neue Position in die entgegengesetzte Richtung.
Volumenhandhabung
Die Strategie verwendet die Basiseigenschaft Volume, wenn sie positiv ist; Andernfalls wird aus Kompatibilitätsgründen mit dem Verhalten von MetaTrader bei festen Chargen standardmäßig eine einzelne Charge verwendet.
Parameter
Name
Beschreibung
Standard
Notizen
CandleType
Zur Analyse verwendete primäre Kerzenserie.
15-minütiger Zeitrahmen
Akzeptiert alle DataType, die von StockSharp unterstützt werden.
StochasticLength
Lookback-Zeitraum für die %K-Rohberechnung.
3
Spiegelt den MetaTrader %K period.
StochasticSmoothing
Glättung angewendet auf %K (MetaTrader slowing).
25
Legt die interne Glättungslänge des Oszillators fest.
StochasticSignal
Glättungszeitraum für die %D-Signalleitung.
36
Spiegelt den MetaTrader %D period.
BodyAveragePeriod
Anzahl der Kerzen, anhand derer die Körpergröße der Kerze gemittelt wird.
3
Filtert kleinere Körper beim Erkennen von Begegnungslinien heraus.
LongEntryLevel
Maximaler %D-Wert, der immer noch einen bullischen Einstieg ermöglicht.
30
Entspricht dem Überverkaufsschwellenwert.
ShortEntryLevel
Mindestwert %D für einen rückläufigen Einstieg erforderlich.
70
Entspricht der Überkaufschwelle.
ExitLowerLevel
Untere Grenze, die Ausgänge bei Aufwärtskreuzungen auslöst.
20
Wird sowohl für Long- als auch für Short-Exit-Entscheidungen verwendet.
ExitUpperLevel
Obere Grenze, die Ausgänge bei Abwärtskreuzungen auslöst.
80
Wird sowohl für Long- als auch für Short-Exit-Entscheidungen verwendet.
Alle Parameter werden über StrategyParam<T> verfügbar gemacht und können direkt im StockSharp Designer oder programmgesteuert optimiert werden.
Signalerzeugung
Long-Einstieg: Bullische Begegnungslinien + %D unter LongEntryLevel ohne bestehendes Long-Engagement (Short-Positionen sind umgekehrt).
Short-Einstieg: Bearish Meeting Lines + %D über ShortEntryLevel ohne bestehendes Short-Engagement (Long-Positionen sind umgekehrt).
Langer Ausstieg: %D unterschreitet ExitUpperLevel oder ExitLowerLevel.
Kurzer Ausstieg: %D überschreitet ExitLowerLevel oder ExitUpperLevel.
Implementierungshinweise
Die Indikatordaten werden über BindEx verarbeitet, wodurch eine manuelle Verwaltung der Indikatorsammlung entfällt.
Bei der Mittelung des Kerzenkörpers wird ein SimpleMovingAverage verwendet, der bis DecimalIndicatorValue mit absoluten Körpergrößen gefüttert wird und mit dem MetaTrader-Helfer AvgBody übereinstimmt.
Alle Kommentare innerhalb des Codes sind in Englisch verfasst und die Einrückung basiert auf Tabulatorzeichen gemäß den Projektrichtlinien.
Die Strategie zeichnet automatisch Kerzen und den stochastischen Oszillator, wenn ein Chartbereich verfügbar ist, was die Live-Überwachung vereinfacht.
Nutzungstipps
Optimierung: Verwenden Sie die bereitgestellten Parameter für Walk-Forward-Tests, um die Schwellenwerte an das gehandelte Instrument anzupassen.
Risikomanagement: Layern Sie die Strategie mit den integrierten StartProtection von StockSharp oder externen Risikokontrollen auf Portfolioebene für Produktionsbereitstellungen.
Datenqualität: Meeting-Lines-Muster reagieren empfindlich auf genaue Eröffnungs-/Schlusskurse; Stellen Sie sicher, dass die Feeds ausgerichtet sind und illiquide Sitzungen gefiltert werden.
Zeitrahmen: Obwohl der Standardwert 15 Minuten beträgt, können Intraday- oder Tagesdaten durch Ändern von CandleType verwendet werden.
Die Strategie bietet einen disziplinierten Ansatz für Händler, die sich auf Candlestick-Formationen verlassen, aber eine Oszillatorbestätigung benötigen, um Fehlalarme zu reduzieren.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Meeting Lines + Stochastic strategy.
/// Buys on bullish meeting lines with low stochastic, sells on bearish meeting lines with high stochastic.
/// </summary>
public class MeetingLinesStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stochPeriod;
private readonly StrategyParam<decimal> _stochLow;
private readonly StrategyParam<decimal> _stochHigh;
private ICandleMessage _prevCandle;
private ICandleMessage _prevPrevCandle;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int StochPeriod { get => _stochPeriod.Value; set => _stochPeriod.Value = value; }
public decimal StochLow { get => _stochLow.Value; set => _stochLow.Value = value; }
public decimal StochHigh { get => _stochHigh.Value; set => _stochHigh.Value = value; }
public MeetingLinesStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_stochPeriod = Param(nameof(StochPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Stochastic Period", "Stochastic K period", "Indicators");
_stochLow = Param(nameof(StochLow), 30m)
.SetDisplay("Stoch Low", "Stochastic oversold level", "Signals");
_stochHigh = Param(nameof(StochHigh), 70m)
.SetDisplay("Stoch High", "Stochastic overbought level", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_prevPrevCandle = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_prevPrevCandle = null;
var stoch = new StochasticOscillator { K = { Length = StochPeriod }, D = { Length = 3 } };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(stoch, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
{
if (candle.State != CandleStates.Finished) return;
var stochTyped = stochValue as StochasticOscillatorValue;
if (stochTyped?.K is not decimal kValue) { UpdateState(candle); return; }
if (_prevCandle != null && _prevPrevCandle != null)
{
var avgBody = (Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice) +
Math.Abs(_prevPrevCandle.ClosePrice - _prevPrevCandle.OpenPrice)) / 2m;
if (avgBody > 0)
{
// Bullish meeting lines: prev bearish, current bullish, closes near
var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice &&
(_prevCandle.OpenPrice - _prevCandle.ClosePrice) > avgBody * 0.5m;
var currBullish = candle.ClosePrice > candle.OpenPrice &&
(candle.ClosePrice - candle.OpenPrice) > avgBody * 0.5m;
var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBearish && currBullish && closesNear && kValue < StochLow && Position <= 0)
BuyMarket();
// Bearish meeting lines: prev bullish, current bearish, closes near
var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice &&
(_prevCandle.ClosePrice - _prevCandle.OpenPrice) > avgBody * 0.5m;
var currBearish = candle.OpenPrice > candle.ClosePrice &&
(candle.OpenPrice - candle.ClosePrice) > avgBody * 0.5m;
var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBullish && currBearish && closesNear2 && kValue > StochHigh && Position >= 0)
SellMarket();
}
}
UpdateState(candle);
}
private void UpdateState(ICandleMessage candle)
{
_prevPrevCandle = _prevCandle;
_prevCandle = candle;
}
}
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 meeting_lines_stochastic_strategy(Strategy):
def __init__(self):
super(meeting_lines_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._stoch_period = self.Param("StochPeriod", 14)
self._stoch_low = self.Param("StochLow", 30.0)
self._stoch_high = self.Param("StochHigh", 70.0)
self._prev_candle = None
self._prev_prev_candle = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def StochPeriod(self):
return self._stoch_period.Value
@StochPeriod.setter
def StochPeriod(self, value):
self._stoch_period.Value = value
@property
def StochLow(self):
return self._stoch_low.Value
@StochLow.setter
def StochLow(self, value):
self._stoch_low.Value = value
@property
def StochHigh(self):
return self._stoch_high.Value
@StochHigh.setter
def StochHigh(self, value):
self._stoch_high.Value = value
def OnReseted(self):
super(meeting_lines_stochastic_strategy, self).OnReseted()
self._prev_candle = None
self._prev_prev_candle = None
def OnStarted2(self, time):
super(meeting_lines_stochastic_strategy, self).OnStarted2(time)
self._prev_candle = None
self._prev_prev_candle = None
stoch = StochasticOscillator()
stoch.K.Length = self.StochPeriod
stoch.D.Length = 3
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(stoch, self._process_candle).Start()
def _process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
k_val = stoch_value.K
if k_val is None:
self._update_state(candle)
return
k_value = float(k_val)
if self._prev_candle is not None and self._prev_prev_candle is not None:
avg_body = (abs(float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice))
+ abs(float(self._prev_prev_candle.ClosePrice) - float(self._prev_prev_candle.OpenPrice))) / 2.0
if avg_body > 0:
# Bullish meeting lines
prev_bearish = (float(self._prev_candle.OpenPrice) > float(self._prev_candle.ClosePrice)
and (float(self._prev_candle.OpenPrice) - float(self._prev_candle.ClosePrice)) > avg_body * 0.5)
curr_bullish = (float(candle.ClosePrice) > float(candle.OpenPrice)
and (float(candle.ClosePrice) - float(candle.OpenPrice)) > avg_body * 0.5)
closes_near = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bearish and curr_bullish and closes_near and k_value < self.StochLow and self.Position <= 0:
self.BuyMarket()
# Bearish meeting lines
prev_bullish = (float(self._prev_candle.ClosePrice) > float(self._prev_candle.OpenPrice)
and (float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice)) > avg_body * 0.5)
curr_bearish = (float(candle.OpenPrice) > float(candle.ClosePrice)
and (float(candle.OpenPrice) - float(candle.ClosePrice)) > avg_body * 0.5)
closes_near2 = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bullish and curr_bearish and closes_near2 and k_value > self.StochHigh and self.Position >= 0:
self.SellMarket()
self._update_state(candle)
def _update_state(self, candle):
self._prev_prev_candle = self._prev_candle
self._prev_candle = candle
def CreateClone(self):
return meeting_lines_stochastic_strategy()