Vela japonesa Stochastic Estrategia de confirmación
Esta estrategia reproduce el Expert Advisor de MetaTrader Expert_CP_Stoch dentro del nivel alto de StockSharp API. Combina patrones de reversión de velas japonesas con un filtro de oscilador estocástico %D para confirmar entradas y salidas de tiempo. El sistema escanea cada vela completa, mira hacia atrás tres barras para detectar formaciones alcistas o bajistas y requiere que la línea de señal estocástica esté en una zona de sobreventa o sobrecompra antes de abrir operaciones. Las posiciones se cierran cada vez que aparece el patrón opuesto o cuando la línea estocástica cruza un límite de salida configurable.
La configuración predeterminada refleja el experto original: %K período 33, %D período 37, desaceleración 30, sobreventa en 30, sobrecompra en 70 y niveles de cruce de salida en 20/80. Debido a que el oscilador estocástico de StockSharp utiliza datos altos/bajos/cerrados, el comportamiento corresponde a la configuración original de STO_LOWHIGH. El reconocimiento de patrones de velas se basa en los últimos doce cuerpos (de forma predeterminada) para calcular el tamaño promedio de vela utilizado en el filtrado de patrones.
Detalles
Criterios de entrada:
Largo: Se detecta uno de los patrones alcistas (Tres soldados blancos, Línea perforadora, Doji matutino, Envolvente alcista, Harami alcista, Estrella de la mañana, Líneas de encuentro alcistas) y el valor estocástico %D en la barra previamente cerrada está por debajo del umbral de sobreventa (predeterminado 30).
Corto: Se detecta uno de los patrones bajistas (Tres cuervos negros, Cubierta de nubes oscuras, Doji vespertino, Envolvente bajista, Harami bajista, Estrella vespertina, Líneas de encuentro bajista) y el valor estocástico %D en la barra previamente cerrada está por encima del umbral de sobrecompra (predeterminado 70).
Criterios de salida:
Largo: Salga inmediatamente cuando aparezca un patrón bajista o cuando %D cruce por debajo del límite de salida superior (predeterminado 80) o por debajo del límite inferior (predeterminado 20).
Corto: Salga inmediatamente cuando aparezca un patrón alcista o cuando %D cruce por encima del límite de salida inferior (predeterminado 20) o por encima del límite superior (predeterminado 80).
Largo/Corto: opera en ambas direcciones con reglas simétricas.
Stops: Sin stop-loss/objetivo fijo; las salidas se basan en cambios de patrón y cruces estocásticos. Puede agregar protección de cartera en el iniciador si es necesario.
Valores predeterminados:
Body Average Period = 12 velas utilizadas para calcular el tamaño del cuerpo de referencia para la calificación del patrón.
Categoría: Reconocimiento de patrones + confirmación de oscilador.
Dirección: Larga y corta.
Indicadores: oscilador Stochastic, múltiples patrones de velas.
Paradas: Solo salidas de patrón/oscilador (sin parada/objetivo mecánico).
Complejidad: Alta (detección de patrones de múltiples condiciones con promedios históricos).
Plazo: Funciona en cualquier plazo; por defecto son velas por hora.
Estacionalidad: Ninguna.
Redes neuronales: No.
Divergencia: No hay divergencia explícita; confirmación a través de niveles del oscilador.
Nivel de riesgo: Medio-alto por ausencia de paradas bruscas.
Cómo funciona
Se suscribe a la serie de velas seleccionada y vincula un oscilador estocástico (%K, %D, desaceleración).
Mantiene las últimas tres velas completadas y los promedios móviles de los cuerpos/cierres de las velas para replicar la lógica de la biblioteca de patrones de MetaTrader.
Evalúa grupos de patrones alcistas/bajistas en cada vela terminada. Cada patrón sigue estrictamente las definiciones matemáticas originales (verificaciones corporales promedio, relaciones de puntos medios, requisitos de espacio, etc.).
Recupera los valores estocásticos de %D de las dos velas anteriores para detectar cruces y condiciones de sobreventa/sobrecompra.
Abre o cierra posiciones de mercado utilizando los métodos BuyMarket/SellMarket de alto nivel de StockSharp cuando las condiciones del patrón y del oscilador se alinean.
Opcionalmente, puede habilitar módulos de riesgo externos (por ejemplo, StartProtection) desde el iniciador si necesita una gestión de stop-loss.
Notas prácticas
Asegúrese de alimentar la estrategia con al menos Body Average Period + 3 velas históricas antes de esperar señales; de lo contrario, las comprobaciones de patrones devolverán falso porque el cuerpo promedio no está definido.
El filtro estocástico utiliza el valor %D de la vela anterior, replicando la forma en que la señal de MetaTrader evaluó StochSignal(1).
Debido a que el reconocimiento del patrón de velas es sensible a las brechas y los tamaños relativos de las velas, los resultados pueden variar en instrumentos con poca liquidez o datos sintéticos.
Para acelerar la optimización, puede ajustar los umbrales de sobreventa/sobrecompra y los períodos estocásticos manteniendo intactas las definiciones de las velas.
Si necesita un comportamiento de STO_CLOSECLOSE (cierre/estocástico de cierre), reemplace el oscilador de StockSharp por uno configurado para cálculos de solo cierre en una mejora futura.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Candlestick + Stochastic strategy.
/// Buys on bullish engulfing with low stochastic, sells on bearish engulfing with high stochastic.
/// </summary>
public class CandlestickStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stochPeriod;
private readonly StrategyParam<decimal> _stochLow;
private readonly StrategyParam<decimal> _stochHigh;
private readonly StrategyParam<int> _signalCooldownCandles;
private ICandleMessage _prevCandle;
private int _candlesSinceTrade;
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 int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public CandlestickStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_stochPeriod = Param(nameof(StochPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Stoch Period", "Stochastic K period", "Indicators");
_stochLow = Param(nameof(StochLow), 40m)
.SetDisplay("Stoch Low", "Stochastic oversold level", "Signals");
_stochHigh = Param(nameof(StochHigh), 60m)
.SetDisplay("Stoch High", "Stochastic overbought level", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_candlesSinceTrade = SignalCooldownCandles;
var rsi = new RelativeStrengthIndex { Length = StochPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal stochValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_prevCandle != null)
{
var bullishEngulf = _prevCandle.OpenPrice > _prevCandle.ClosePrice &&
candle.ClosePrice > candle.OpenPrice &&
candle.ClosePrice > _prevCandle.OpenPrice &&
candle.OpenPrice < _prevCandle.ClosePrice;
var bearishEngulf = _prevCandle.ClosePrice > _prevCandle.OpenPrice &&
candle.OpenPrice > candle.ClosePrice &&
candle.OpenPrice > _prevCandle.ClosePrice &&
candle.ClosePrice < _prevCandle.OpenPrice;
if (bullishEngulf && stochValue < StochLow && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (bearishEngulf && stochValue > StochHigh && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class candlestick_stochastic_strategy(Strategy):
def __init__(self):
super(candlestick_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._stoch_period = self.Param("StochPeriod", 14)
self._stoch_low = self.Param("StochLow", 40.0)
self._stoch_high = self.Param("StochHigh", 60.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_candle = None
self._candles_since_trade = 4
@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
@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(candlestick_stochastic_strategy, self).OnReseted()
self._prev_candle = None
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(candlestick_stochastic_strategy, self).OnStarted2(time)
self._prev_candle = None
self._candles_since_trade = self.SignalCooldownCandles
rsi = RelativeStrengthIndex()
rsi.Length = self.StochPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
stoch_val = float(stoch_value)
if self._prev_candle is not None:
bullish_engulf = (float(self._prev_candle.OpenPrice) > float(self._prev_candle.ClosePrice) and
float(candle.ClosePrice) > float(candle.OpenPrice) and
float(candle.ClosePrice) > float(self._prev_candle.OpenPrice) and
float(candle.OpenPrice) < float(self._prev_candle.ClosePrice))
bearish_engulf = (float(self._prev_candle.ClosePrice) > float(self._prev_candle.OpenPrice) and
float(candle.OpenPrice) > float(candle.ClosePrice) and
float(candle.OpenPrice) > float(self._prev_candle.ClosePrice) and
float(candle.ClosePrice) < float(self._prev_candle.OpenPrice))
if bullish_engulf and stoch_val < self.StochLow and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif bearish_engulf and stoch_val > self.StochHigh and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_candle = candle
def CreateClone(self):
return candlestick_stochastic_strategy()