La estrategia DoubleUp2 Martingale reproduce el experto original MetaTrader combinando el índice del canal de productos básicos (CCI) y el oscilador MACD. Las operaciones se abren sólo cuando ambos indicadores alcanzan niveles extremos en la misma dirección. El tamaño de la posición sigue un esquema de martingala en el que el volumen se duplica después de una operación perdedora. Las operaciones rentables se bloquean parcialmente cerrando la posición una vez que el precio recorre una distancia configurable a favor de la posición.
Cómo funciona
Suscríbase a una única serie de velas (por defecto, 1 minuto) y calcule CCI y MACD en cada barra completa.
Detectar impulso extremo:
Ingrese short cuando tanto CCI como MACD excedan el umbral positivo.
Ingrese largo cuando ambos caigan por debajo del umbral negativo.
Antes de revertir, la posición actual se cierra y el paso de martingala se actualiza en función del beneficio simulado de la última operación.
El volumen comercial es igual al volumen base derivado del capital de la cuenta dividido por un divisor de saldo, multiplicado por el factor martingala elevado al paso actual.
Consiga ganancias cerrando cualquier posición abierta una vez que el precio avance una cantidad predefinida de puntos desde la última entrada. Las salidas ganadoras aumentan el paso de martingala en dos para igualar el comportamiento original de EA.
Parámetros
Nombre
Descripción
Predeterminado
CciPeriod
Período retroactivo para el indicador CCI.
8
MacdFastPeriod
Longitud rápida de EMA para MACD.
13
MacdSlowPeriod
Longitud lenta de EMA para MACD.
33
MacdSignalPeriod
Longitud de la señal EMA para el suavizado MACD.
2
Threshold
Umbral absoluto del indicador que debe superarse para activar las entradas.
230
ExitDistancePoints
Distancia de ganancia en puntos que desencadena el cierre de posición.
120
BalanceDivisor
Divisor aplicado al capital de la cartera para obtener el volumen base.
50001
MinimumVolume
Límite inferior para el volumen comercial calculado.
0.1
MartingaleMultiplier
Multiplicador aplicado al tamaño de la posición después de cada cierre perdedor.
2
CandleType
Periodo de velas utilizado para todos los cálculos.
1 minuto
Notas
La lógica de martingala aumenta el tamaño de la posición después de pérdidas y se reinicia después de reversiones rentables, reflejando la lógica fuente MQL.
La información del paso del precio se utiliza para convertir la distancia de salida (puntos) en unidades de precio absoluto. Si el instrumento no proporciona un escalón de precio, se utiliza un valor de 1.
La estrategia espera un único instrumento y no coloca posiciones largas y cortas simultáneas.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class DoubleUp2MartingaleStrategy : 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 DoubleUp2MartingaleStrategy()
{
_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;
}
}