La Estrategia de entradas potenciales replica la lógica del asesor experto EA_PotentialEntries.mq5 original. Analiza pares de las velas terminadas más recientes y emite operaciones cuando aparecen patrones de impulso o reversión específicos de dos velas. La estrategia funciona en una dirección a la vez (alcista o bajista), seleccionable a través del parámetro Pattern Side. Los niveles de parada de protección se recalculan en cada entrada para reflejar la ubicación de la parada MetaTrader original en el extremo del par de velas analizado.
La implementación utiliza el nivel alto de StockSharp API: se suscribe al tipo de vela configurado, procesa el flujo dentro de ProcessCandle, abre posiciones con BuyMarket/SellMarket y cierra operaciones a través de salidas de mercado cuando se supera el precio de parada rastreado internamente. Los gráficos representan la serie de velas junto con las operaciones de estrategia para una inspección visual rápida.
Datos y parámetros
grupo
Nombre
Descripción
generales
Lado del patrón
Dirección del escaneo del patrón: Bullish busca reversiones alcistas, Bearish busca reversiones bajistas.
Comercio
Volumen comercial
Tamaño de orden de mercado utilizado para cada entrada. La estrategia aplana la exposición opuesta antes de abrir una nueva posición.
generales
Tipo de vela
Serie de velas utilizadas para el reconocimiento de patrones (predeterminado: velas por hora).
Lógica de trading
La estrategia evalúa la vela finalizada más reciente (C1) junto con la vela anterior (C2). Todas las medidas de mecha y cuerpo se calculan en unidades de precio.
Modo alcista
Cuando Pattern Side = Bullish, las siguientes configuraciones activan una entrada larga:
Martillo alcista
C1 cierra por encima de su apertura mientras que C2 es bajista.
La mecha inferior de C1 mide al menos el doble del cuerpo y más del triple de la mecha superior.
Se envía una orden de compra de mercado y el nivel de parada se establece en el menor de los mínimos de C1 y C2.
Martillo invertido alcista
C1 es alcista y C2 es bajista.
La mecha superior de C1 tiene al menos el doble del cuerpo y al menos el triple de la mecha inferior.
Ejecuta la misma orden y lógica de parada que la configuración del martillo.
Creador de impulso alcista
C1 y C2 son ambos alcistas.
El rango de C1 es mayor que el rango de C2 y el cuerpo de C1 es al menos el doble del cuerpo de C2.
Abre una posición larga con el stop por debajo del mínimo mínimo del par.
Modo bajista
Cuando Pattern Side = Bearish, las siguientes configuraciones activan una entrada corta:
Estrella fugaz
C1 cierra por debajo de su apertura mientras que C2 es alcista.
La mecha superior de C1 tiene al menos el doble del cuerpo y al menos el triple de la mecha inferior.
Se envía una orden de venta de mercado con el stop colocado por encima del máximo superior de C1 y C2.
Hombre ahorcado
C1 es bajista y C2 es alcista.
La mecha inferior de C1 mide al menos el doble del cuerpo y más del triple de la mecha superior.
Abre una posición corta y utiliza la misma lógica de parada que la estrella fugaz.
Creador de impulso bajista
C1 y C2 son bajistas.
El cuerpo de C1 es más grande que el cuerpo de C2 y el rango de C1 es al menos el doble del rango de C2.
Entra en corto y almacena el stop por encima del máximo máximo de las velas analizadas.
Gestión de paradas y manejo de posiciones
Sólo un modo direccional está activo a la vez. Antes de iniciar una operación, la estrategia cierra cualquier posición en la dirección opuesta.
Cada entrada registra un precio stop en el extremo del par de velas. Con la llegada de cada nueva vela terminada, la estrategia comprueba si el mínimo (para largos) o el máximo (para cortos) viola el nivel almacenado y cierra la posición con una orden de mercado si se activa.
Cuando no hay ninguna posición abierta, el valor de parada almacenado se borra, lo que garantiza que los niveles obsoletos nunca se reutilicen.
Notas de uso
Elija el modo Bullish o Bearish dependiendo de si desea buscar oportunidades largas o cortas.
Las velas horarias predeterminadas se pueden reemplazar con cualquier otro tipo de datos de vela disponible.
Aún no existe un puerto para Python, tal como se solicitó. Solo se proporciona la implementación de C#.
La estrategia no establece objetivos de ganancias. Las salidas dependen únicamente de la lógica de parada basada en velas o de la intervención manual.
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()