Estrategia de gestión de pedidos ARD Stochastic
Descripción general
La estrategia Ard Order Management es una StockSharp conversión del MetaTrader experto ARD_ORDER_MANAGEMENT_EA-BETA_1. El guión original se centraba en cerrar repetidamente posiciones existentes antes de realizar nuevos pedidos y ofrecía rutinas de ayuda para actualizaciones manuales de stop-loss y take-profit. La versión StockSharp mantiene esta disciplina al tiempo que agrega automatización basada en indicadores basada en el oscilador Stochastic.
La configuración predeterminada apunta al comercio de divisas intradía en un gráfico de 5 minutos, pero el tipo de vela es completamente configurable. Toda la lógica comercial se ejecuta en velas terminadas para permanecer fiel al estilo de ejecución de final de barra del experto fuente.
Lógica de trading
- Un oscilador Stochastic con períodos configurables de retrospectiva, señal y desaceleración genera señales direccionales (valor predeterminado: 5/3/3).
- Cuando %K cierra por encima del umbral de compra (80 de forma predeterminada), la estrategia cancela las órdenes pendientes, cierra cualquier exposición corta abierta y entra en una posición larga con el volumen configurado.
- Cuando %K cierra por debajo del umbral de venta (20 por defecto), se cancelan todas las órdenes pendientes, se cierra la exposición larga abierta y se abre una nueva venta corta.
- La estrategia permanece en la nueva posición hasta que se dispara la señal opuesta o se activa una salida protectora.
Gestión de pedidos y riesgos
- Antes de cada nueva entrada, la estrategia emite órdenes de mercado que aplanan completamente la posición actual, replicando el comportamiento
open_order(CLOSE) del EA.
StartProtection envía automáticamente órdenes iniciales de stop-loss y take-profit de acuerdo con los parámetros StopLossPips y TakeProfitPips.
- La lógica de seguimiento opcional emula la rama
MODIFY del EA: cada vela terminada puede actualizar un nivel de parada dinámico (ModifyStopLossPips) y un objetivo de ganancias flotante (ModifyTakeProfitPips). Cuando el precio toca cualquiera de los niveles finales, la posición se cierra para asegurar ganancias o limitar el riesgo.
- La conversión de pips utiliza el
PriceStep del instrumento (con un ajuste de 10× para símbolos de divisas de pip fraccionario) para que los parámetros basados en la distancia se mantengan consistentes en todos los mercados.
Parámetros
- Volumen – volumen de operaciones para nuevas entradas; El tamaño adicional se agrega automáticamente para cerrar posiciones opuestas.
- TakeProfitPips / StopLossPips – distancias de protección iniciales pasadas al módulo de protección incorporado. Establezca en cero para desactivar cualquier orden.
- ModifyTakeProfitPips / ModifyStopLossPips: compensaciones finales (en pips) recalculadas después de cada vela. Establezca en cero para deshabilitar las actualizaciones finales.
- StochasticPeriod / SignalPeriod / SlowingPeriod: configuración del oscilador que refleja la llamada
iStochastic del experto original.
- BuyThreshold / SellThreshold: niveles de sobrecompra/sobreventa que desencadenan reversiones largas/cortas.
- CandleType: período de tiempo o fuente de datos de velas personalizada que alimenta el indicador.
Cada parámetro expone rangos de optimización sensibles para que pueda probar configuraciones alternativas en el optimizador StockSharp.
Notas de uso
- Funciona mejor en instrumentos líquidos donde las paradas basadas en pips son significativas (principales pares de divisas, CFD sobre índices, futuros líquidos).
- Aumente el plazo al operar en mercados más lentos para reducir el ruido y las falsas reversiones.
- Cuando se ejecuta en cuentas reales, verifique que el volumen configurado respete los mínimos del corredor y los tamaños de paso.
- La lógica de seguimiento se puede desactivar dejando los parámetros
Modify* en cero, reproduciendo efectivamente el mantenimiento del orden estático de la fuente EA.
- Combínelo con filtros adicionales (tendencia, volatilidad, sesiones) si desea entradas más selectivas: el código expone propiedades que se pueden ampliar.
Detalles de conversión
- Archivo fuente:
MQL/9041/ARD_ORDER_MANAGEMENT_EA-BETA_1.mq4.
- Se recreó la lógica de activación Stochastic insinuada en la rutina
start() comentada.
- Preservó la disciplina de cierre antes de abrir y la colocación de órdenes de protección a través del alto nivel de StockSharp API.
- Se agregaron salidas finales opcionales para reflejar el bloque manual
MODIFY del EA mientras se mantiene la implementación basada en indicadores y eventos.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Ard Order Management Stochastic: RSI overbought/oversold reversal
/// with EMA trend filter and ATR-based trailing stops.
/// </summary>
public class ArdOrderManagementStochasticStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<decimal> _buyThreshold;
private readonly StrategyParam<decimal> _sellThreshold;
private decimal _prevRsi;
public ArdOrderManagementStochasticStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_rsiLength = Param(nameof(RsiLength), 10)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_emaLength = Param(nameof(EmaLength), 14)
.SetDisplay("EMA Length", "EMA trend filter period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 10)
.SetDisplay("ATR Length", "ATR period for stops.", "Indicators");
_buyThreshold = Param(nameof(BuyThreshold), 30m)
.SetDisplay("Buy Threshold", "RSI oversold level for buy.", "Signals");
_sellThreshold = Param(nameof(SellThreshold), 70m)
.SetDisplay("Sell Threshold", "RSI overbought level for sell.", "Signals");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
public decimal BuyThreshold
{
get => _buyThreshold.Value;
set => _buyThreshold.Value = value;
}
public decimal SellThreshold
{
get => _sellThreshold.Value;
set => _sellThreshold.Value = value;
}
/// <inheritdoc />
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = 0;
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ema, atr, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevRsi == 0)
{
_prevRsi = rsiVal;
return;
}
// Entry: RSI crosses threshold
if (Position == 0)
{
if (rsiVal < BuyThreshold && _prevRsi >= BuyThreshold)
{
BuyMarket();
}
else if (rsiVal > SellThreshold && _prevRsi <= SellThreshold)
{
SellMarket();
}
}
_prevRsi = rsiVal;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Algo.Indicators import RelativeStrengthIndex, ExponentialMovingAverage, AverageTrueRange
class ard_order_management_stochastic_strategy(Strategy):
def __init__(self):
super(ard_order_management_stochastic_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._rsi_length = self.Param("RsiLength", 10) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._ema_length = self.Param("EmaLength", 14) \
.SetDisplay("EMA Length", "EMA trend filter period.", "Indicators")
self._atr_length = self.Param("AtrLength", 10) \
.SetDisplay("ATR Length", "ATR period for stops.", "Indicators")
self._buy_threshold = self.Param("BuyThreshold", 30.0) \
.SetDisplay("Buy Threshold", "RSI oversold level for buy.", "Signals")
self._sell_threshold = self.Param("SellThreshold", 70.0) \
.SetDisplay("Sell Threshold", "RSI overbought level for sell.", "Signals")
self._prev_rsi = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
@property
def BuyThreshold(self):
return self._buy_threshold.Value
@property
def SellThreshold(self):
return self._sell_threshold.Value
def OnStarted2(self, time):
super(ard_order_management_stochastic_strategy, self).OnStarted2(time)
self._prev_rsi = 0.0
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._rsi, self._ema, self._atr, self.ProcessCandle).Start()
self.StartProtection(
takeProfit=Unit(2, UnitTypes.Percent),
stopLoss=Unit(1, UnitTypes.Percent)
)
def ProcessCandle(self, candle, rsi_val, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_val)
if self._prev_rsi == 0:
self._prev_rsi = rv
return
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
# Entry: RSI crosses threshold
if self.Position == 0:
if rv < float(self.BuyThreshold) and self._prev_rsi >= float(self.BuyThreshold):
self.BuyMarket()
elif rv > float(self.SellThreshold) and self._prev_rsi <= float(self.SellThreshold):
self.SellMarket()
self._prev_rsi = rv
def OnReseted(self):
super(ard_order_management_stochastic_strategy, self).OnReseted()
self._prev_rsi = 0.0
def CreateClone(self):
return ard_order_management_stochastic_strategy()