La Estrategia de Estabilización de Órdenes es una conversión del MetaTrader asesor experto hjueiisyx8lp2o379e_www_forex-instruments_info.mq4. El robot original coloca un par de órdenes stop alrededor del precio actual y espera una ruptura. Una vez que se abre una posición, el sistema monitorea los cuerpos de velas recientes para determinar si la acción del precio se ha estancado ("estabilizado") y sale de la operación cuando el mercado pierde impulso o cuando se alcanza un umbral de ganancias predefinido.
Este puerto de C# mantiene la misma lógica utilizando el nivel alto StockSharp API. Se basa en velas completas en lugar de ticks sin procesar, lo que hace que el comportamiento sea determinista durante las pruebas retrospectivas y las operaciones en vivo.
Reglas de trading
Cuando no hay posiciones abiertas ni órdenes activas, la estrategia envía un stop de compra por encima del mercado y un stop de venta por debajo del mercado. La distancia se mide en MetaTrader puntos (generalmente igual a un pip).
Si se ejecuta una orden de parada:
La orden ejecutada abre una posición de OrderVolume lotes.
La orden de stop opuesta sigue pendiente para detectar una ruptura en la otra dirección.
Mientras una posición está abierta, la estrategia verifica el tamaño del cuerpo de las dos velas terminadas más recientes:
Si el último cuerpo de la vela es menor que StabilizationPoints y el beneficio flotante es mayor que ProfitThreshold, la posición se cierra y la orden pendiente opuesta se cancela.
Si dos velas consecutivas son más pequeñas que StabilizationPoints, la operación se cierra independientemente de las ganancias actuales.
Si la ganancia alcanza AbsoluteFixation, la operación se cierra inmediatamente.
Las órdenes pendientes se cancelan y se vuelven a crear después de ExpirationMinutes a menos que el valor se establezca en cero (vida útil infinita).
Parámetros
Nombre
Descripción
Predeterminado
OrderVolume
Volumen comercial en lotes utilizados para ambas entradas de parada.
0.1
OrderDistancePoints
Distancia entre el precio de cierre actual y cada orden stop, expresada en MetaTrader puntos.
20
ProfitThreshold
Beneficio flotante mínimo (moneda de la cuenta) requerido antes de que se permita una salida provocada por la estabilización.
-2
AbsoluteFixation
Nivel de beneficio (moneda de la cuenta) que obliga a una salida inmediata.
30
StabilizationPoints
Tamaño máximo del cuerpo de la vela (puntos) que indica un mercado plano.
25
ExpirationMinutes
Vida útil de las órdenes stop pendientes en minutos. 0 desactiva la caducidad.
20
CandleType
Tipo de vela utilizada para evaluar la estabilización (el valor predeterminado es un período de tiempo de 5 minutos).
TimeFrame(5m)
Notas de conversión
El asesor experto original operaba según los ticks del gráfico. Este puerto evalúa solo velas terminadas, preservando la lógica y garantizando pruebas retrospectivas reproducibles.
MetaTrader "puntos" se asignan a StockSharp PriceStep. Si el instrumento carece de un paso de precio, se supone un paso de 1.
La ganancia se aproxima usando PriceStep y StepPrice para traducir el movimiento de precios a la moneda de la cuenta.
Todos los comentarios del código se reescribieron en inglés y los metadatos de los parámetros incluyen descripciones fáciles de usar con agrupación.
Uso
Agregue la estrategia a su solución StockSharp y asigne la seguridad y el portafolio deseados.
Configure los parámetros, especialmente el período de tiempo de la vela y la distancia en puntos para que coincidan con las características del instrumento.
Inicia la estrategia. Enviará órdenes stop emparejadas y gestionará posiciones de acuerdo con la lógica de estabilización descrita anteriormente.
Más ideas
Experimente con diferentes intervalos de velas para equilibrar la capacidad de respuesta y el filtrado de ruido.
Combine la estrategia con filtros de volatilidad (ATR, Bollinger Bandas) para evitar operar durante sesiones extremadamente tranquilas.
Amplíe la lógica con trailingstops o salidas parciales de posiciones una vez que se acerque al objetivo de beneficio absoluto.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Order stabilization strategy - trades breakouts after periods of low volatility.
/// When candle body is small (stabilization), waits for a directional breakout.
/// Goes long on bullish breakout candle after stabilization, short on bearish.
/// </summary>
public class OrderStabilizationStrategy : Strategy
{
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _stabilizationFactor;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevBody;
private decimal _prevAtr;
private bool _hasPrev;
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public decimal StabilizationFactor { get => _stabilizationFactor.Value; set => _stabilizationFactor.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public OrderStabilizationStrategy()
{
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetDisplay("ATR Period", "ATR period for volatility", "Indicators");
_stabilizationFactor = Param(nameof(StabilizationFactor), 0.5m)
.SetDisplay("Stabilization Factor", "Body must be less than ATR * factor for stabilization", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevBody = 0m;
_prevAtr = 0m;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var atr = new AverageTrueRange { Length = AtrPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var threshold = atrValue * StabilizationFactor;
if (!_hasPrev)
{
_prevBody = body;
_prevAtr = atrValue;
_hasPrev = true;
return;
}
var prevThreshold = _prevAtr * StabilizationFactor;
var wasStabilized = _prevBody < prevThreshold;
// After stabilization, trade breakout candle
if (wasStabilized && body > threshold)
{
var bullish = candle.ClosePrice > candle.OpenPrice;
if (bullish && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (!bullish && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
}
_prevBody = body;
_prevAtr = atrValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class order_stabilization_strategy(Strategy):
"""Trades breakouts after periods of low volatility (stabilization).
When previous candle body is small relative to ATR, waits for directional breakout.
Goes long on bullish breakout candle, short on bearish."""
def __init__(self):
super(order_stabilization_strategy, self).__init__()
self._atr_period = self.Param("AtrPeriod", 14) \
.SetDisplay("ATR Period", "ATR period for volatility", "Indicators")
self._stabilization_factor = self.Param("StabilizationFactor", 0.5) \
.SetDisplay("Stabilization Factor", "Body must be less than ATR * factor for stabilization", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_body = 0.0
self._prev_atr = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def AtrPeriod(self):
return self._atr_period.Value
@property
def StabilizationFactor(self):
return self._stabilization_factor.Value
def OnReseted(self):
super(order_stabilization_strategy, self).OnReseted()
self._prev_body = 0.0
self._prev_atr = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(order_stabilization_strategy, self).OnStarted2(time)
self._has_prev = False
atr = AverageTrueRange()
atr.Length = self.AtrPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(atr, self._process_candle).Start()
def _process_candle(self, candle, atr_value):
if candle.State != CandleStates.Finished:
return
atr_val = float(atr_value)
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
body = abs(close - open_price)
factor = float(self.StabilizationFactor)
threshold = atr_val * factor
if not self._has_prev:
self._prev_body = body
self._prev_atr = atr_val
self._has_prev = True
return
prev_threshold = self._prev_atr * factor
was_stabilized = self._prev_body < prev_threshold
# After stabilization, trade breakout candle
if was_stabilized and body > threshold:
bullish = close > open_price
if bullish and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif not bullish and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_body = body
self._prev_atr = atr_val
def CreateClone(self):
return order_stabilization_strategy()