Die Candle Patterns Test Strategy ist eine StockSharp High-Level-Konvertierung des ursprünglichen MetaTrader 5 Expertenberaters CandlePatternsTest EA. Die Strategie durchsucht abgeschlossene Kerzen nach einer kuratierten Liste klassischer japanischer Kerzenformationen und reagiert, indem sie Long- oder Short-Positionen eingeht, wenn bullische oder bärische Strukturen auftreten. Die Konvertierung konzentriert sich auf die diskretionäre Musterlogik des Quellroboters und nutzt gleichzeitig StockSharp Risikokontrollen und Datenabonnements API.
Handelslogik
Kerzenabonnement – die Strategie abonniert den konfigurierten Kerzentyp und wartet auf fertige Balken, bevor sie die Mustererkennung durchführt.
Durchschnittskörperfilter – ein einfacher gleitender Durchschnitt von Kerzenkörpern dient als dynamische Normalisierung. Nur Muster, deren konstituierende Kerzen diesen Durchschnitt überschreiten, gelten als gültig und spiegeln die Funktion AvgBody der MQL-Implementierung wider.
Mustererkennung – der Detektor prüft auf:
Drei weiße Soldaten / drei schwarze Krähen
Durchdringende Linie / dunkle Wolkendecke
Morgen-Doji-Stern / Abend-Doji-Stern
Bullisches und bärisches Engulfing
Bullisches und bärisches Harami
Besprechungslinien
Eintrittsmanagement – sobald ein bullisches Muster bestätigt ist, eröffnet die Strategie eine Marktkauforder; Abwärtstrends lösen einen Marktverkaufsauftrag aus. Gegenüberliegende Signale kehren automatisch die aktuelle Position um.
Exit-Management – schützende Stop-Loss- und Take-Profit-Werte werden vom durchschnittlichen Kerzenkörper abgeleitet und für jede fertige Kerze verfolgt. Wenn der Preis einen dieser Schwellenwerte erreicht, wird die Position geschlossen.
Parameter
Parameter
Beschreibung
CandleType
Datentyp der zu abonnierenden Kerzen (Standard: 1-Stunden-Zeitrahmen).
AverageBodyPeriod
Anzahl der verwendeten Kerzen für die durchschnittliche Körperlänge. Steuert die Musternormalisierung.
EnableBullishPatterns
Aktiviert oder deaktiviert lange Einträge.
EnableBearishPatterns
Aktiviert oder deaktiviert kurze Einträge.
StopLossFactor
Auf den durchschnittlichen Körper angewendeter Multiplikator für die Stop-Loss-Distanz.
TakeProfitFactor
Auf den durchschnittlichen Körper angewendeter Multiplikator für die Take-Profit-Distanz.
Alle Parameter werden über StrategyParam<T> verfügbar gemacht, um die GUI-Konfiguration und Optimierungsausführungen zu unterstützen.
Diagramme
Wenn ein Diagrammbereich verfügbar ist, wird die Strategie wie folgt dargestellt:
Die abonnierten Kerzen
Der gleitende Schlusskursdurchschnitt, der für den Trendkontext verwendet wird
Ausgeführte Trades zur visuellen Überprüfung
Unterschiede zum Original EA
Nachrichtenfilter, Zeitfenster, Absicherungsschalter und Trailing-Grid-Management, die in der ursprünglichen MQ5-Datei vorhanden sind, wurden absichtlich weggelassen, um sich auf den Kern des Candlestick-Musters zu konzentrieren.
Das Risikomanagement wird auf ein symmetrisches Stop/Ziel-Modell vereinfacht, das aus der Kerzenvolatilität abgeleitet wird.
Die StockSharp-Version nutzt die Positionsverwaltung des Frameworks und BuyMarket/SellMarket-Helfer anstelle manueller Bestelltickets.
Nutzungshinweise
Legen Sie den Parameter CandleType so fest, dass er mit der Marktsitzung übereinstimmt, die Sie analysieren möchten. Höhere Zeitrahmen erzeugen weniger, aber stärkere Signale.
Passen Sie AverageBodyPeriod so an, dass der durchschnittliche Körper in etwa der jüngsten Volatilität entspricht. Ein kleinerer Wert reagiert schneller, kann aber das Rauschen verstärken.
StopLossFactor und TakeProfitFactor können optimiert werden, um dem Risikoprofil des Instruments zu entsprechen.
Anforderungen
StockSharp-Umgebung mit Marktdaten-Feed, der den konfigurierten Kerzentyp generieren kann.
Die Strategie erwartet sequentielle, nicht überlappende Kerzenserien. Stellen Sie sicher, dass das ausgewählte Board regelmäßige Balkenaktualisierungen unterstützt.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Candle Patterns Test strategy: Doji + trend reversal.
/// Buys on doji in downtrend (below EMA), sells on doji in uptrend (above EMA).
/// </summary>
public class CandlePatternsTestStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public CandlePatternsTestStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candlesSinceTrade = SignalCooldownCandles;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var range = candle.HighPrice - candle.LowPrice;
if (range <= 0) return;
// Doji: body is very small relative to range
var isDoji = body < range * 0.05m;
var close = candle.ClosePrice;
if (isDoji && close < emaValue && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (isDoji && close > emaValue && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class candle_patterns_test_strategy(Strategy):
def __init__(self):
super(candle_patterns_test_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 50)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(candle_patterns_test_strategy, self).OnReseted()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(candle_patterns_test_strategy, self).OnStarted2(time)
self._candles_since_trade = self.SignalCooldownCandles
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
body = abs(float(candle.ClosePrice) - float(candle.OpenPrice))
range_val = float(candle.HighPrice) - float(candle.LowPrice)
if range_val <= 0:
return
is_doji = body < range_val * 0.05
close = float(candle.ClosePrice)
ema_val = float(ema_value)
if is_doji and close < ema_val and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif is_doji and close > ema_val and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return candle_patterns_test_strategy()