La estrategia Wedge Pattern es una conversión del asesor experto de MetaTrader Wedge pattern.mq4 a la API de alto nivel de StockSharp. Busca consolidaciones de cuña simétricas derivadas de fractales de Bill Williams y opera las rupturas cuando los filtros de tendencia y momentum se alinean.
La implementación de alto nivel reemplaza la gestión manual de órdenes original con funciones StockSharp, conservando la lógica de decisión:
Filtro de tendencia: compara una media móvil ponderada lineal (LWMA) rápida y una lenta calculadas sobre precios típicos.
Filtro de momentum: evalúa la distancia absoluta del indicador momentum de 14 periodos respecto a su nivel neutral (100). Las tres últimas lecturas de momentum deben superar un umbral configurable.
Confirmación MACD: requiere que la línea principal MACD esté por encima de la línea de señal para largos (o por debajo para cortos).
Detección de cuña fractal: recopila puntos fractales superiores e inferiores para construir líneas de tendencia convergentes. Las señales se producen cuando el precio cierra más allá de esas líneas más un búfer de confirmación configurable.
Gestión de riesgo: imita la implementación MQL con distancias fijas de stop-loss y take-profit, movimiento automático a break-even y ajustes de trailing stop.
Funcionamiento
Suscribirse a un único marco temporal definido por CandleType.
Actualizar indicadores con cada vela completada y mantener búferes móviles de máximos y mínimos para detectar nuevos fractales.
Construir líneas de tendencia de cuña desde los dos fractales altos y bajos más recientes. Solo las cuñas convergentes (máximos descendentes y mínimos ascendentes) se consideran configuraciones válidas.
Se abre un largo cuando:
LWMA rápida > LWMA lenta.
Línea MACD > línea de señal.
Cualquiera de las tres últimas lecturas de momentum supera el umbral configurado.
La vela actual cierra por encima de la línea de tendencia superior proyectada al menos por el búfer de ruptura.
Un corto refleja las condiciones con líneas y umbrales invertidos.
Después de la entrada, la estrategia coloca inmediatamente órdenes de stop-loss y take-profit. Luego puede mover el stop a break-even y trailarlo cuando la posición se vuelve rentable.
Parámetros
Parámetro
Descripción
CandleType
Marco usado para análisis y órdenes.
FastMaPeriod
Longitud del filtro LWMA rápido.
SlowMaPeriod
Longitud del filtro LWMA lento.
MomentumPeriod
Periodo de retrospección del indicador momentum (14 por defecto).
MomentumThreshold
Distancia mínima desde 100 requerida para considerar impulsivo al mercado.
Activa y configura el comportamiento del trailing-stop.
BreakoutBufferPips
Búfer extra aplicado a la confirmación de ruptura de la cuña.
Todos los ajustes basados en pips se convierten a distancias de precio usando el tamaño de tick del instrumento. El cálculo de pips predeterminado considera precios fraccionarios (3 o 5 decimales) exactamente como el asesor experto original.
Guías de uso
Adjunte la estrategia al instrumento deseado y seleccione el marco de velas que coincida con la configuración original (por ejemplo, velas de 15 minutos).
Configure el tamaño de posición mediante la propiedad base Strategy.Volume.
Opcionalmente ajuste filtros y parámetros de riesgo para coincidir con la volatilidad del mercado objetivo.
Inicie la estrategia; se suscribirá a velas, dibujará datos de gráfico y operará automáticamente cuando ocurran rupturas de cuña.
Diferencias frente a la versión MQL
La versión StockSharp usa SubscribeCandles de alto nivel y APIs de binding de indicadores, evitando procesamiento manual de ticks.
La gestión de trailing stop y break-even depende de SetStopLoss/SetTakeProfit, integrándose con el comportamiento protector integrado.
Se mantiene solo una posición a la vez; el script MetaTrader admitía piramidación hasta un número máximo de operaciones.
Se omiten funciones de alerta, correo y notificación; el manejo de eventos debe implementarse externamente si se necesita.
A pesar de estas adaptaciones, la lógica central de entrada y las reglas protectoras siguen de cerca al experto MetaTrader original usando patrones idiomáticos de StockSharp.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Wedge Pattern strategy: WMA crossover + Momentum.
/// Buys when fast WMA crosses above slow WMA and momentum > 100.
/// Sells on cross below with momentum < 100.
/// </summary>
public class WedgePatternStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _momPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public int MomPeriod
{
get => _momPeriod.Value;
set => _momPeriod.Value = value;
}
public WedgePatternStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 40)
.SetGreaterThanZero()
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
_momPeriod = Param(nameof(MomPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Momentum", "Momentum period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new WeightedMovingAverage { Length = FastPeriod };
var slow = new WeightedMovingAverage { Length = SlowPeriod };
var mom = new Momentum { Length = MomPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, mom, (candle, fastVal, slowVal, momVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;
if (crossUp && momVal > 100m && Position <= 0)
BuyMarket();
else if (crossDown && momVal < 100m && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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 WeightedMovingAverage, Momentum
from StockSharp.Algo.Strategies import Strategy
class wedge_pattern_strategy(Strategy):
def __init__(self):
super(wedge_pattern_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 40) \
.SetGreaterThanZero() \
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators")
self._mom_period = self.Param("MomPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("Momentum", "Momentum period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(wedge_pattern_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(wedge_pattern_strategy, self).OnStarted2(time)
self._fast_ind = WeightedMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = WeightedMovingAverage()
self._slow_ind.Length = self._slow_period.Value
self._mom_ind = Momentum()
self._mom_ind.Length = self._mom_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._mom_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value, mom_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
mom_val = float(mom_value)
if self._prev_fast is not None and self._prev_slow is not None:
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and mom_val > 100.0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and mom_val < 100.0 and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return wedge_pattern_strategy()