La estrategia es una adaptación directa del asesor experto MetaTrader 4 up3x1_Premium_2vM. Opera con un solo símbolo y mantiene como máximo una posición abierta en cualquier momento. Las entradas se basan en una combinación de promedios móviles suavizados, fuertes rangos de velas y un filtro de ruptura diario a medianoche. El riesgo se gestiona a través de distancias fijas de toma de ganancias y stop-loss expresadas en puntos de precio, mientras que un trailing stop opcional reproduce el comportamiento del EA original que ajusta continuamente los stop una vez que el mercado se mueve a favor de la posición.
como funciona
El período de tiempo principal es configurable; el EA utilizó originalmente el período de tiempo del gráfico. Dos medias móviles suavizadas (SMMA) con períodos 12 y 26 están vinculadas a la suscripción de velas utilizando el precio típico.
Un flujo de velas diario separado reconstruye los datos D1 utilizados por la lógica MQL para el filtro de ruptura de medianoche y para el promedio móvil simple diario de 10 períodos.
Cuando es plana, la estrategia evalúa las dos velas terminadas anteriores y los valores SMMA almacenados en caché:
Sesgo largo: o la SMMA rápida cruza por encima de la SMMA lenta mientras ambas aperturas aumentan, o la última vela muestra un cuerpo alcista por encima de los umbrales del rango configurado, o la última vela diaria cierra alcista después de un rango grande. El EA original también comparó el SMA diario con el precio de venta; debido a que la condición siempre se evalúa como verdadera, se conserva por motivos de compatibilidad.
Sesgo corto: condiciones simétricas de las reglas largas utilizando rangos y cruces bajistas.
Si se cumple alguna condición larga, se emite una compra de mercado; de lo contrario, si se mantiene alguna condición corta, se realiza una venta en el mercado. El tamaño del lote solicitado se normaliza según el paso del volumen de seguridad antes de enviar el pedido.
Mientras una posición está abierta, la estrategia monitorea los valores SMMA rápido/lento de la vela anterior. Cuando su diferencia absoluta cae por debajo de ConvergenceTolerance la posición se cierra, reproduciéndose la comprobación de igualdad en el asesor experto.
El módulo de seguimiento rastrea el precio de entrada promedio. Una vez que el precio supera la distancia de seguimiento, el nivel de parada avanza para mantener la brecha configurada. Al tocar ese nivel, la posición se cierra inmediatamente, emulando las repetidas llamadas de OrderModify de MQL.
Parámetros
Nombre
Predeterminado
Descripción
CandleType
TimeFrame(1h)
Plazo principal utilizado para las entradas.
FastMaPeriod
12
Longitud de la media móvil suavizada rápida (precio típico).
SlowMaPeriod
26
Longitud de la media móvil suavizada lenta (precio típico).
RangeThreshold
0.0060
Rango de vela mínimo requerido por el filtro de impulso.
BodyThreshold
0.0050
Tamaño mínimo del cuerpo de la vela para la condición del rango.
DailyRangeThreshold
0.0060
Distancia mínima de apertura y cierre en la última vela diaria para el filtro de ruptura de medianoche.
TakeProfitPoints
150
Distancia de obtención de beneficios expresada en puntos de precio. Establezca en 0 para desactivar.
StopLossPoints
100
Distancia de stop-loss expresada en puntos de precio. Establezca en 0 para desactivar.
TrailingStopPoints
10
Distancia entre el precio y el trailing stop. Establezca en 0 para deshabilitar el seguimiento.
TradeVolume
0.05
Tamaño de lote utilizado para órdenes de mercado antes de la normalización del volumen.
ConvergenceTolerance
0.00001
Diferencia máxima entre las SMMA que desencadena la liquidación de posiciones.
Notas
La estrategia mantiene la peculiaridad original de EA donde la comparación diaria de SMA siempre es cierta, lo que garantiza la paridad de características con la fuente de MQL.
Las órdenes de stop-loss y take-profit se registran a través de StartProtection y, por lo tanto, se adaptan automáticamente al tamaño del paso del corredor cuando esté disponible.
La lógica final requiere un valor TrailingStopPoints positivo y un Security.PriceStep válido. Cuando falta alguno de los datos, la parada no seguirá.
La normalización del volumen respeta las restricciones de intercambio (VolumeStep, VolumeMin, VolumeMax). Los valores negativos para TradeVolume se pueden usar para emular el tamaño basado en porcentaje una vez que se agrega la lógica personalizada.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class Up3x1Premium2VmStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
private int _cooldownRemaining;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Up3x1Premium2VmStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 20).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 80).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 100).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevFast = fast;
_prevSlow = slow;
}
}