Puerto del asesor experto de MetaTrader 5 MartingailExpert.mq5.
Usa un cruce de oscilador estocástico con parámetros configurables %K, %D y ralentización para abrir posiciones.
Implementa una cuadrícula de estilo martingala con entradas de promediado y ruptura que escalan el volumen geométricamente.
Diseñado para portafolios de posición neta: la estrategia mantiene una única posición larga o corta agregada.
Lógica de trading
Criterios de entrada
La estrategia procesa velas cerradas del marco temporal CandleType.
Los valores estocásticos se toman de la vela terminada anterior para imitar la llamada MQL iStochastic(..., 1).
Se activa una entrada larga cuando:
El %K anterior es mayor que el %D anterior.
El %D anterior está por encima de BuyLevel.
No existe ninguna posición abierta.
Se activa una entrada corta cuando:
El %K anterior es menor que el %D anterior.
El %D anterior está por debajo de SellLevel.
No existe ninguna posición abierta.
Todas las órdenes de mercado usan el valor Volume normalizado (redondeado al Security.VolumeStep más cercano).
Escalado de posición
ProfitPips define la distancia (en pips) requerida para agregar otra posición base en la dirección de la ganancia.
En largo: si el máximo de la vela alcanza lastEntryPrice + ProfitPips * positionCount, se envía una nueva orden con el Volume base.
En corto: si el mínimo de la vela alcanza lastEntryPrice - ProfitPips * positionCount, se envía una orden base de venta.
StepPips define la distancia de promediado (en pips) para aplicar el multiplicador martingala.
En largo: si el mínimo de la vela toca lastEntryPrice - StepPips, el siguiente volumen de orden es lastVolume * Multiplier.
En corto: si el máximo de la vela toca lastEntryPrice + StepPips, se aplica el mismo dimensionamiento martingala.
Cada operación ejecutada actualiza lastEntryPrice, lastVolume y el recuento interno de posiciones activas.
Lógica de salida
El precio del último trade ejecutado se almacena por dirección.
Si el precio alcanza lastEntryPrice ± ProfitPips (usando máximos de vela para largos y mínimos para cortos), todas las posiciones abiertas se cierran mediante orden de mercado.
Una vez que la posición agregada vuelve a cero, las variables de estado martingala se reinician.
Parámetros
Nombre
Predeterminado
Descripción
Volume
0.03
Tamaño de lote base para la orden inicial y los complementos basados en ganancia.
Multiplier
1.6
Multiplicador martingala para entradas de promediado.
StepPips
25
Distancia en pips que activa órdenes de promediado contra la tendencia.
ProfitPips
9
Distancia en pips usada tanto para salidas de ganancia como para complementos de ruptura.
KPeriod
5
Período de lookback del cálculo estocástico %K.
DPeriod
3
Período de suavizado de la línea estocástica %D.
Slowing
3
Suavizado aplicado a la línea %K (estocástico lento).
BuyLevel
20
Valor mínimo de %D requerido para permitir entradas largas.
SellLevel
55
Valor máximo de %D requerido para permitir entradas cortas.
CandleType
marco temporal de 5 minutos
Marco temporal usado para construir velas e indicadores.
Notas de implementación
La distancia en pips se calcula a partir de Security.PriceStep. Los instrumentos con cotizaciones de 3 o 5 decimales se ajustan automáticamente multiplicando el paso de precio por 10 para coincidir con la lógica de pip MQL original.
Los volúmenes se redondean hacia abajo al Security.VolumeStep más cercano. Los valores que caen por debajo del paso negociable mínimo son ignorados.
La estrategia depende de los máximos y mínimos de las velas para aproximar los disparadores intra-barra porque la API de alto nivel opera sobre velas terminadas.
OnOwnTradeReceived rastrea los precios y volúmenes de ejecución reales para reproducir fielmente la secuencia de escalada martingala.
Consejos de uso
Alinee CandleType con el marco temporal utilizado en la plantilla original de MetaTrader (comúnmente M5) para obtener un comportamiento similar.
Asegúrese de que los metadatos del instrumento (paso de precio, paso de volumen) estén completados; de lo contrario, ajuste Volume, StepPips y ProfitPips manualmente para adaptarse a las especificaciones del bróker.
Considere habilitar gestión de riesgo externa (stops o límites de capital) porque la lógica martingala aumenta intencionalmente la exposición durante movimientos adversos.
Diferencias con el asesor experto original
La versión de StockSharp procesa velas completadas en lugar de cada tick; las verificaciones de umbral usan máximos/mínimos de velas para aproximar el comportamiento intra-barra.
Las verificaciones de margen de cuenta específicas de MetaTrader no están disponibles en las estrategias de alto nivel de StockSharp; asegúrese de que el capital adecuado esté configurado externamente.
La ejecución de órdenes y el seguimiento de posiciones aprovechan el modelo de netting de StockSharp; el modo de cobertura no es compatible.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Martingale Expert strategy (simplified). Uses RSI oscillator with
/// martingale-style position scaling and profit targets.
/// </summary>
public class MartingailExpertStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<decimal> _buyLevel;
private readonly StrategyParam<decimal> _sellLevel;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public decimal BuyLevel
{
get => _buyLevel.Value;
set => _buyLevel.Value = value;
}
public decimal SellLevel
{
get => _sellLevel.Value;
set => _sellLevel.Value = value;
}
public MartingailExpertStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
_buyLevel = Param(nameof(BuyLevel), 35m)
.SetDisplay("Buy Level", "RSI level for longs", "Logic");
_sellLevel = Param(nameof(SellLevel), 65m)
.SetDisplay("Sell Level", "RSI level for shorts", "Logic");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiLength };
decimal prevRsi = 50;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, (ICandleMessage candle, decimal rsiVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevRsi = rsiVal;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevRsi = rsiVal;
return;
}
// RSI crosses up from oversold
if (prevRsi < BuyLevel && rsiVal >= BuyLevel && Position <= 0)
BuyMarket();
// RSI crosses down from overbought
else if (prevRsi > SellLevel && rsiVal <= SellLevel && Position >= 0)
SellMarket();
prevRsi = rsiVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
var rsiArea = CreateChartArea();
if (rsiArea != null)
DrawIndicator(rsiArea, rsi);
}
}
}
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
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class martingail_expert_strategy(Strategy):
def __init__(self):
super(martingail_expert_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period", "Indicators")
self._buy_level = self.Param("BuyLevel", 35.0) \
.SetDisplay("Buy Level", "RSI level for longs", "Logic")
self._sell_level = self.Param("SellLevel", 65.0) \
.SetDisplay("Sell Level", "RSI level for shorts", "Logic")
self._prev_rsi = 50.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def BuyLevel(self):
return self._buy_level.Value
@property
def SellLevel(self):
return self._sell_level.Value
def OnReseted(self):
super(martingail_expert_strategy, self).OnReseted()
self._prev_rsi = 50.0
self._has_prev = False
def OnStarted2(self, time):
super(martingail_expert_strategy, self).OnStarted2(time)
self._prev_rsi = 50.0
self._has_prev = False
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if not self._has_prev:
self._prev_rsi = rv
self._has_prev = True
return
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if self._prev_rsi < self.BuyLevel and rv >= self.BuyLevel and self.Position <= 0:
self.BuyMarket()
elif self._prev_rsi > self.SellLevel and rv <= self.SellLevel and self.Position >= 0:
self.SellMarket()
self._prev_rsi = rv
def CreateClone(self):
return martingail_expert_strategy()