Williams Estrategia de índice direccional porcentual
Descripción general
La Williams estrategia de índice direccional porcentual recrea el MetaTrader 5 experto "Mt5 Williams % índice direccional EA" utilizando el nivel alto de StockSharp API. Combina el oscilador Williams %R con el índice direccional promedio (ADX) para identificar cambios de impulso y luego se basa en el índice de flujo de dinero (MFI) y el oscilador Stochastic para salir de las operaciones. La implementación procesa solo velas terminadas y utiliza vinculaciones de indicadores, por lo que cada decisión se basa en la última barra completada.
Lógica de trading
Alineación de tendencias
Williams %R debe estar aumentando para operaciones largas o cayendo para operaciones cortas. La estrategia compara los valores de las dos barras previamente terminadas para evaluar la pendiente del impulso.
El componente de movimiento direccional del ADX (+DI - -DI) debe haber cruzado cero en la última barra cerrada: una transición de negativo a positivo confirma el impulso alcista, mientras que una transición de positivo a negativo confirma el impulso bajista.
Reglas de entrada
Si se cumplen ambas condiciones alcistas y la posición actual es plana o corta, la estrategia abre una orden de compra de mercado.
Si se cumplen ambas condiciones bajistas y la posición actual es plana o larga, la estrategia abre una orden de venta de mercado.
Cuando aparecen simultáneamente señales largas y cortas (raro, pero posible en valores idénticos), la operación se omite para evitar instrucciones contradictorias.
Reglas de salida
Las posiciones largas se cierran cuando el valor MFI de hace dos barras excede el nivel de sobrecompra o la línea principal Stochastic forma un patrón de valle local (K[−2] > K[−1] < K[0]).
Las posiciones cortas se cierran cuando el valor MFI de hace dos barras cae por debajo del nivel de sobreventa reflejado (100 - level) o la línea principal Stochastic forma un patrón de pico local (K[−2] < K[−1] > K[0]).
Manejo de riesgos
La conversión mantiene la mecánica de entrada y salida del asesor experto original. Las funciones de stop-loss y trailing de la fuente MQL no se reproducen; El control de riesgos debe gestionarse externamente o agregarse mediante protecciones StockSharp si es necesario.
Parámetros
Nombre
Descripción
Predeterminado
Candle Type
Plazo para todos los cálculos de los indicadores.
plazo de 15 minutos
Williams %R Period
Período retrospectivo utilizado en el oscilador Williams %R.
42
Directional Period
Periodo para los cálculos de ADX (afecta a +DI/−DI).
20
MFI Period
Longitud del índice de flujo de dinero.
19
MFI Level
Umbral de sobrecompra utilizado para activar salidas. El nivel de sobreventa se calcula como 100 - value.
79
Stochastic %K
Periodo %K del oscilador estocástico.
22
Stochastic %D
Periodo %D del oscilador estocástico.
16
Stochastic Smoothing
Suavizado adicional ("desaceleración") aplicado al oscilador estocástico.
21
Todos los parámetros están expuestos como valores StrategyParam, por lo que se pueden optimizar o ajustar a través de la GUI StockSharp.
Notas de uso
Vincule la estrategia a cualquier instrumento y establezca un volumen adecuado antes de comenzar.
La estrategia procesa solo velas completadas (CandleStates.Finished), lo que garantiza que los valores del indicador sean definitivos.
La representación de gráficos está habilitada: Williams %R, ADX, MFI, Stochastic y las operaciones ejecutadas se trazan cuando hay un área de gráfico disponible.
Para recrear el comportamiento original de MT5 con respecto a la gestión de paradas, considere agregar StartProtection o una lógica de riesgo personalizada según sea necesario.
Diferencias con la versión MQL
La conversión StockSharp utiliza enlaces de indicadores en lugar de la copia manual del búfer, pero las comprobaciones lógicas, incluida la validación de cruce por cero y los patrones de barras múltiples, siguen el asesor experto de MT5.
Los filtros de sesión, la lógica de reintento y la gestión de paradas finales del código MQL se omiten intencionalmente para centrarse en el motor de señales principal solicitado para esta conversión.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Williams %R Directional Index strategy: Williams %R crossover.
/// Buys when Williams %R crosses above -80, sells when crosses below -20.
/// </summary>
public class WilliamsPercentDirectionalIndexStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevWr;
private int _candlesSinceTrade;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int Period { get => _period.Value; set => _period.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public WilliamsPercentDirectionalIndexStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_period = Param(nameof(Period), 14)
.SetGreaterThanZero()
.SetDisplay("Period", "Williams %R period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevWr = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevWr = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var wr = new RelativeStrengthIndex { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(wr, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal wrValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_hasPrev)
{
if (_prevWr < 35 && wrValue >= 35 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevWr > 65 && wrValue <= 65 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevWr = wrValue;
_hasPrev = true;
}
}