Die Potential Entries Strategy repliziert die Logik des ursprünglichen EA_PotentialEntries.mq5-Expertenberaters. Es analysiert Paare der zuletzt abgeschlossenen Kerzen und gibt Geschäfte aus, wenn bestimmte Zwei-Kerzen-Umkehr- oder Momentummuster auftreten. Die Strategie arbeitet jeweils in eine Richtung (bullisch oder bärisch), wählbar über den Parameter Pattern Side. Schutzstoppniveaus werden bei jedem Einstieg neu berechnet, um die ursprüngliche MetaTrader-Stoppplatzierung am äußersten Ende des analysierten Kerzenpaars widerzuspiegeln.
Die Implementierung verwendet StockSharps High-Level-API: Sie abonniert den konfigurierten Kerzentyp, verarbeitet den Stream innerhalb von ProcessCandle, eröffnet Positionen mit BuyMarket/SellMarket und schließt Trades durch Marktausgänge, wenn der intern verfolgte Stop-Preis verletzt wird. Diagramme stellen die Kerzenserien zusammen mit den Strategiegeschäften dar, um eine schnelle visuelle Überprüfung zu ermöglichen.
Daten und Parameter
Gruppe
Name
Beschreibung
Allgemein
Musterseite
Richtung des Musterscans: Bullish sucht nach bullischen Umkehrungen, Bearish sucht nach bärischen Umkehrungen.
Handel
Handelsvolumen
Marktauftragsgröße, die für jeden Eintrag verwendet wird. Die Strategie reduziert das entgegengesetzte Risiko, bevor eine neue Position eröffnet wird.
Allgemein
Kerzentyp
Zur Mustererkennung verwendete Kerzenserie (Standard: stündliche Kerzen).
Handelslogik
Die Strategie wertet die zuletzt abgeschlossene Kerze (C1) zusammen mit der vorherigen Kerze (C2) aus. Alle Docht- und Körpermaße werden in Preiseinheiten berechnet.
Bullischer Modus
Bei Pattern Side = Bullish lösen die folgenden Setups einen langen Eintrag aus:
Bullischer Hammer
C1 schließt über seinem Eröffnungskurs, während C2 bärisch ist.
Der untere Docht von C1 ist mindestens doppelt so groß wie der Körper und mehr als dreimal so groß wie der obere Docht.
Es wird eine Market-Buy-Order gesendet und der Stop-Level auf den niedrigeren der Tiefststände von C1 und C2 gesetzt.
Bullischer umgekehrter Hammer
C1 ist bullisch und C2 ist bärisch.
Der obere Docht von C1 ist mindestens doppelt so groß wie der Körper und mindestens dreimal so groß wie der untere Docht.
Führt den gleichen Befehl und die gleiche Stopplogik aus wie beim Hammer-Setup.
Aufwärtsgerichteter Momentum-Builder
C1 und C2 sind beide bullisch.
Der Bereich von C1 ist größer als der Bereich von C2 und der Hauptteil von C1 ist mindestens doppelt so groß wie der Hauptteil von C2.
Eröffnet eine Long-Position, wobei der Stopp unter dem Mindesttief des Paares liegt.
Bärischer Modus
Bei Pattern Side = Bearish lösen die folgenden Setups einen kurzen Eintrag aus:
Sternschnuppe
C1 schließt unter seinem Eröffnungskurs, während C2 bullisch ist.
Der obere Docht von C1 ist mindestens doppelt so groß wie der Körper und mindestens dreimal so groß wie der untere Docht.
Eine Marktverkaufsorder wird gesendet, wobei der Stop über dem höheren Hoch von C1 und C2 platziert wird.
Hängender Mann
C1 ist bärisch und C2 ist bullisch.
Der untere Docht von C1 ist mindestens doppelt so groß wie der Körper und mehr als dreimal so groß wie der obere Docht.
Eröffnet eine Short-Position und verwendet die gleiche Stopplogik wie der Shooting Star.
Bearish Momentum Builder
C1 und C2 sind bärisch.
Der Hauptteil von C1 ist größer als der Hauptteil von C2 und der Bereich von C1 ist mindestens doppelt so groß wie der Bereich von C2.
Geht Short ein und speichert den Stop über dem maximalen Hoch der analysierten Kerzen.
Stoppmanagement und Positionsverwaltung
Es ist jeweils nur ein Richtungsmodus aktiv. Vor dem Eingehen eines Handels schließt die Strategie jede Position in die entgegengesetzte Richtung.
Jeder Eintrag zeichnet einen Stop-Preis am äußersten Ende des Kerzenpaares auf. Beim Eintreffen jeder neuen fertigen Kerze prüft die Strategie, ob das Tief (für Long-Positionen) oder das Hoch (für Short-Positionen) das gespeicherte Niveau verletzt und schließt die Position bei Auslösung mit einer Marktorder.
Wenn keine Position offen ist, wird der gespeicherte Stoppwert gelöscht, wodurch sichergestellt wird, dass veraltete Level nie wieder verwendet werden.
Nutzungshinweise
Wählen Sie den Modus Bullish oder Bearish, je nachdem, ob Sie nach langen oder kurzen Gelegenheiten suchen möchten.
Die standardmäßigen stündlichen Kerzen können durch jeden anderen verfügbaren Kerzendatentyp ersetzt werden.
Wie gewünscht gibt es noch keinen Python-Port. Es wird nur die C#-Implementierung bereitgestellt.
Die Strategie sieht keine Gewinnziele vor. Exits basieren ausschließlich auf der kerzenbasierten Stopplogik oder manuellen Eingriffen.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Potential Entries strategy: two-candle reversal patterns with RSI confirmation.
/// Detects bullish/bearish reversals and trades with RSI filter.
/// </summary>
public class PotentialEntriesStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private readonly List<ICandleMessage> _candles = new();
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public PotentialEntriesStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candles.Clear();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_candlesSinceTrade = SignalCooldownCandles;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
_candles.Add(candle);
if (_candles.Count > 5)
_candles.RemoveAt(0);
if (_candles.Count >= 2)
{
var curr = _candles[^1];
var prev = _candles[^2];
// Bullish reversal: prev bearish, curr bullish with higher close
var bullish = prev.OpenPrice > prev.ClosePrice
&& curr.ClosePrice > curr.OpenPrice
&& curr.ClosePrice > prev.OpenPrice;
// Bearish reversal: prev bullish, curr bearish with lower close
var bearish = prev.ClosePrice > prev.OpenPrice
&& curr.OpenPrice > curr.ClosePrice
&& curr.ClosePrice < prev.OpenPrice;
if (bullish && rsiValue < 50 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (bearish && rsiValue > 50 && 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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class potential_entries_strategy(Strategy):
def __init__(self):
super(potential_entries_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles = []
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 RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_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(potential_entries_strategy, self).OnReseted()
self._candles.clear()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(potential_entries_strategy, self).OnStarted2(time)
self._candles.clear()
self._candles_since_trade = self.SignalCooldownCandles
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2:
curr = self._candles[-1]
prev = self._candles[-2]
bullish = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.ClosePrice) > float(prev.OpenPrice))
bearish = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.ClosePrice) < float(prev.OpenPrice))
if bullish and float(rsi_value) < 50 and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif bearish and float(rsi_value) > 50 and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return potential_entries_strategy()