La Estrategia de prueba de patrones de velas es una StockSharp conversión de alto nivel del MetaTrader 5 asesor experto original CandlePatternsTest EA. La estrategia escanea velas completadas en busca de una lista seleccionada de formaciones de velas japonesas clásicas y reacciona ingresando posiciones largas o cortas cuando aparecen estructuras alcistas o bajistas. La conversión se centra en la lógica de patrón discrecional del robot de origen y al mismo tiempo aprovecha StockSharp los controles de riesgo y la suscripción de datos API.
Lógica de trading
Suscripción de vela: la estrategia se suscribe al tipo de vela configurado y espera las barras terminadas antes de ejecutar el reconocimiento de patrones.
Filtro de cuerpo promedio: un promedio móvil simple de cuerpos de velas actúa como normalización dinámica. Solo los patrones cuyas velas constituyentes superan este promedio se consideran válidos, lo que refleja la función AvgBody de la implementación MQL.
Reconocimiento de patrones: el detector comprueba:
Tres soldados blancos / Tres cuervos negros
Línea perforadora / Cubierta de nubes oscuras
Estrella Doji matutina / Estrella Doji vespertina
Envolvente alcista y bajista
Harami alcista y bajista
Líneas de reunión
Gestión de entrada – una vez que se confirma un patrón alcista, la estrategia abre una orden de compra en el mercado; Los patrones bajistas desencadenan una orden de venta en el mercado. Las señales opuestas invierten automáticamente la posición actual.
Gestión de salida: los niveles protectores de stop-loss y take-profit se derivan del cuerpo promedio de la vela y se rastrean en cada vela terminada. Si el precio toca cualquiera de los umbrales, la posición se cierra.
Parámetros
Parámetro
Descripción
CandleType
Tipo de datos de velas a las que suscribirse (predeterminado: período de 1 hora).
AverageBodyPeriod
Número de velas utilizadas para la longitud corporal promedio. Controla la normalización de patrones.
EnableBullishPatterns
Habilita o deshabilita las entradas largas.
EnableBearishPatterns
Habilita o deshabilita las entradas cortas.
StopLossFactor
Multiplicador aplicado al cuerpo promedio para la distancia de stop-loss.
TakeProfitFactor
Multiplicador aplicado al cuerpo promedio por distancia de obtención de beneficios.
Todos los parámetros están expuestos a través de StrategyParam<T> para admitir la configuración de GUI y las ejecuciones del optimizador.
Trazar
Cuando un área del gráfico está disponible, la estrategia se traza:
Las velas suscritas
El promedio móvil de precio de cierre utilizado para el contexto de tendencia
Operaciones ejecutadas para verificación visual.
Diferencias con el original EA
Los filtros de noticias, las ventanas de tiempo, los conmutadores de cobertura y la gestión de la cuadrícula final presentes en el archivo MQ5 original se omiten intencionalmente para centrarse en el núcleo del patrón de velas.
La gestión de riesgos se simplifica a un modelo simétrico de parada/objetivo derivado de la volatilidad de las velas.
La versión StockSharp utiliza la gestión de posiciones del marco y los ayudantes BuyMarket/SellMarket en lugar de tickets de pedidos manuales.
Notas de uso
Establezca el parámetro CandleType para alinearlo con la sesión de mercado que desea analizar; marcos temporales más altos producen menos señales pero más fuertes.
Ajuste AverageBodyPeriod para que el cuerpo promedio se acerque a la volatilidad reciente. Un valor menor reacciona más rápido pero puede aumentar el ruido.
StopLossFactor y TakeProfitFactor se pueden optimizar para que coincidan con el perfil de riesgo del instrumento.
Requisitos
StockSharp entorno con fuente de datos de mercado capaz de generar el tipo de vela configurado.
La estrategia espera series de velas secuenciales y que no se superpongan. Asegúrese de que el tablero seleccionado admita actualizaciones periódicas de la barra.
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()