La Estrategia de Líneas de Reunión Stochastic es una implementación StockSharp del experto MetaTrader Expert_AML_Stoch. Combina los patrones de inversión de velas alcistas/bajistas con la confirmación de la línea de señal %D del oscilador Stochastic. La estrategia está diseñada para traders discrecionales que desean un enfoque basado en reglas para el reconocimiento de patrones con confirmación de impulso adicional. Al utilizar StockSharp API de alto nivel, el código sigue siendo conciso, comprobable y fácil de ampliar para la gestión de cartera o una mayor automatización.
Lógica de trading
Filtro de patrón de velas
La estrategia evalúa continuamente las dos últimas velas completadas para detectar una formación de Líneas de Encuentro.
Una configuración alcista requiere una vela negra larga seguida de una vela blanca larga cuyo precio de cierre esté dentro del 10% del cierre anterior.
Una configuración bajista requiere una vela blanca larga seguida de una vela negra larga con la misma alineación cercana del 10%.
El tamaño medio del cuerpo de la vela se calcula con una media móvil simple configurable para filtrar los cuerpos débiles.
Stochastic Confirmación
La línea de señal %D del oscilador Stochastic debe confirmar la señal de la vela.
Las entradas alcistas exigen que %D esté por debajo del umbral de sobreventa configurable (predeterminado 30).
Las entradas bajistas requieren que %D esté por encima del umbral de sobrecompra configurable (predeterminado 70).
Reglas de salida
Las posiciones cortas se cierran cuando %D cruza hacia arriba a través del nivel de salida inferior (predeterminado 20) o el nivel de salida superior (predeterminado 80).
Las posiciones largas se cierran cuando %D cruza hacia abajo por los mismos niveles.
Las órdenes de reversión cierran automáticamente la exposición existente y abren una nueva posición en la dirección opuesta.
Manejo de volumen
La estrategia utiliza la propiedad base Volume cuando es positiva; de lo contrario, el valor predeterminado es un lote único por compatibilidad con el comportamiento de lote fijo de MetaTrader.
Parámetros
Nombre
Descripción
Predeterminado
Notas
CandleType
Serie de velas primarias utilizadas para el análisis.
plazo de 15 minutos
Acepta cualquier DataType compatible con StockSharp.
StochasticLength
Período retrospectivo para el cálculo de %K sin procesar.
3
Refleja el MetaTrader %K period.
StochasticSmoothing
Suavizado aplicado a %K (MetaTrader slowing).
25
Establece la longitud de suavizado interno del oscilador.
StochasticSignal
Período de suavizado para la línea de señal %D.
36
Refleja el MetaTrader %D period.
BodyAveragePeriod
Número de velas utilizadas para promediar el tamaño del cuerpo de la vela.
3
Filtra cuerpos menores al detectar líneas de encuentro.
LongEntryLevel
Valor máximo de %D que aún permite una entrada alcista.
30
Equivale al umbral de sobreventa.
ShortEntryLevel
Valor mínimo de %D requerido para una entrada bajista.
70
Equivale al umbral de sobrecompra.
ExitLowerLevel
Límite inferior que desencadena salidas en cruces alcistas.
20
Se utiliza para decisiones de salida tanto largas como cortas.
ExitUpperLevel
Límite superior que desencadena salidas en cruces descendentes.
80
Se utiliza para decisiones de salida tanto largas como cortas.
Todos los parámetros se exponen a través de StrategyParam<T> y se pueden optimizar directamente en StockSharp Designer o mediante programación.
Generación de señal
Entrada larga: Líneas de reunión alcistas + %D por debajo de LongEntryLevel sin exposición larga existente (las posiciones cortas se revierten).
Entrada corta: Líneas de encuentro bajistas + %D por encima de ShortEntryLevel sin exposición corta existente (las posiciones largas se invierten).
Salida larga: %D cruza por debajo de ExitUpperLevel o ExitLowerLevel.
Salida corta: %D cruza por encima de ExitLowerLevel o ExitUpperLevel.
Notas de implementación
Los datos de los indicadores se manejan a través de BindEx, evitando la gestión manual de recopilación de indicadores.
El promedio del cuerpo de la vela utiliza un SimpleMovingAverage alimentado con tamaños de cuerpo absolutos hasta el DecimalIndicatorValue, que coincide con el MetaTrader auxiliar AvgBody.
Todos los comentarios dentro del código están escritos en inglés y la sangría se basa en caracteres de tabulación de acuerdo con las pautas del proyecto.
La estrategia dibuja automáticamente velas y el oscilador estocástico cuando hay un área del gráfico disponible, lo que simplifica el monitoreo en vivo.
Consejos de uso
Optimización: Utilice los parámetros expuestos para las pruebas de avance para alinear los umbrales con el instrumento negociado.
Gestión de riesgos: superponga la estrategia con los controles de riesgo integrados StartProtection o externos a nivel de cartera de StockSharp para implementaciones de producción.
Calidad de los datos: Los patrones de las líneas de reunión son sensibles a los precios precisos de apertura y cierre; garantizar la alineación del feed y el filtrado de sesiones sin liquidez.
Marcos de tiempo: aunque el valor predeterminado es 15 minutos, se pueden usar datos intradiarios o diarios modificando CandleType.
La estrategia ofrece un enfoque disciplinado para los operadores que dependen de formaciones de velas pero requieren la confirmación del oscilador para reducir los falsos positivos.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Meeting Lines + Stochastic strategy.
/// Buys on bullish meeting lines with low stochastic, sells on bearish meeting lines with high stochastic.
/// </summary>
public class MeetingLinesStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stochPeriod;
private readonly StrategyParam<decimal> _stochLow;
private readonly StrategyParam<decimal> _stochHigh;
private ICandleMessage _prevCandle;
private ICandleMessage _prevPrevCandle;
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 MeetingLinesStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_stochPeriod = Param(nameof(StochPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Stochastic Period", "Stochastic K period", "Indicators");
_stochLow = Param(nameof(StochLow), 30m)
.SetDisplay("Stoch Low", "Stochastic oversold level", "Signals");
_stochHigh = Param(nameof(StochHigh), 70m)
.SetDisplay("Stoch High", "Stochastic overbought level", "Signals");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_prevPrevCandle = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_prevPrevCandle = null;
var stoch = new StochasticOscillator { K = { Length = StochPeriod }, D = { Length = 3 } };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(stoch, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
{
if (candle.State != CandleStates.Finished) return;
var stochTyped = stochValue as StochasticOscillatorValue;
if (stochTyped?.K is not decimal kValue) { UpdateState(candle); return; }
if (_prevCandle != null && _prevPrevCandle != null)
{
var avgBody = (Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice) +
Math.Abs(_prevPrevCandle.ClosePrice - _prevPrevCandle.OpenPrice)) / 2m;
if (avgBody > 0)
{
// Bullish meeting lines: prev bearish, current bullish, closes near
var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice &&
(_prevCandle.OpenPrice - _prevCandle.ClosePrice) > avgBody * 0.5m;
var currBullish = candle.ClosePrice > candle.OpenPrice &&
(candle.ClosePrice - candle.OpenPrice) > avgBody * 0.5m;
var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBearish && currBullish && closesNear && kValue < StochLow && Position <= 0)
BuyMarket();
// Bearish meeting lines: prev bullish, current bearish, closes near
var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice &&
(_prevCandle.ClosePrice - _prevCandle.OpenPrice) > avgBody * 0.5m;
var currBearish = candle.OpenPrice > candle.ClosePrice &&
(candle.OpenPrice - candle.ClosePrice) > avgBody * 0.5m;
var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;
if (prevBullish && currBearish && closesNear2 && kValue > StochHigh && Position >= 0)
SellMarket();
}
}
UpdateState(candle);
}
private void UpdateState(ICandleMessage candle)
{
_prevPrevCandle = _prevCandle;
_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 StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class meeting_lines_stochastic_strategy(Strategy):
def __init__(self):
super(meeting_lines_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._stoch_period = self.Param("StochPeriod", 14)
self._stoch_low = self.Param("StochLow", 30.0)
self._stoch_high = self.Param("StochHigh", 70.0)
self._prev_candle = None
self._prev_prev_candle = None
@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
def OnReseted(self):
super(meeting_lines_stochastic_strategy, self).OnReseted()
self._prev_candle = None
self._prev_prev_candle = None
def OnStarted2(self, time):
super(meeting_lines_stochastic_strategy, self).OnStarted2(time)
self._prev_candle = None
self._prev_prev_candle = None
stoch = StochasticOscillator()
stoch.K.Length = self.StochPeriod
stoch.D.Length = 3
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(stoch, self._process_candle).Start()
def _process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
k_val = stoch_value.K
if k_val is None:
self._update_state(candle)
return
k_value = float(k_val)
if self._prev_candle is not None and self._prev_prev_candle is not None:
avg_body = (abs(float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice))
+ abs(float(self._prev_prev_candle.ClosePrice) - float(self._prev_prev_candle.OpenPrice))) / 2.0
if avg_body > 0:
# Bullish meeting lines
prev_bearish = (float(self._prev_candle.OpenPrice) > float(self._prev_candle.ClosePrice)
and (float(self._prev_candle.OpenPrice) - float(self._prev_candle.ClosePrice)) > avg_body * 0.5)
curr_bullish = (float(candle.ClosePrice) > float(candle.OpenPrice)
and (float(candle.ClosePrice) - float(candle.OpenPrice)) > avg_body * 0.5)
closes_near = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bearish and curr_bullish and closes_near and k_value < self.StochLow and self.Position <= 0:
self.BuyMarket()
# Bearish meeting lines
prev_bullish = (float(self._prev_candle.ClosePrice) > float(self._prev_candle.OpenPrice)
and (float(self._prev_candle.ClosePrice) - float(self._prev_candle.OpenPrice)) > avg_body * 0.5)
curr_bearish = (float(candle.OpenPrice) > float(candle.ClosePrice)
and (float(candle.OpenPrice) - float(candle.ClosePrice)) > avg_body * 0.5)
closes_near2 = abs(float(candle.ClosePrice) - float(self._prev_candle.ClosePrice)) < avg_body * 0.3
if prev_bullish and curr_bearish and closes_near2 and k_value > self.StochHigh and self.Position >= 0:
self.SellMarket()
self._update_state(candle)
def _update_state(self, candle):
self._prev_prev_candle = self._prev_candle
self._prev_candle = candle
def CreateClone(self):
return meeting_lines_stochastic_strategy()