Martingail Expert es una estrategia de martingala que sigue tendencias y se basa en el oscilador Stochastic para cronometrar nuevas secuencias de operaciones. Una vez que el indicador genera una dirección, la estrategia inicia una escalera de órdenes de mercado y gestiona la exposición utilizando un objetivo de ganancias dinámico y un esquema de tamaño de posición geométrico.
Lógica de trading
Calcule un oscilador Stochastic en la serie de velas configurada. Los valores finales más recientes de %K y %D se almacenan en caché para la toma de decisiones.
Inicie una nueva secuencia larga cuando %K (previous) > %D (previous) y %D (previous) estén por encima del umbral BuyLevel.
Inicie una nueva secuencia corta cuando %K (previous) < %D (previous) y %D (previous) estén por debajo del umbral SellLevel.
Después de ingresar una secuencia, cada movimiento de precio favorable igual a ProfitFactor × openOrders pips agrega una nueva posición con el volumen base.
Cada movimiento adverso de StepPoints pips multiplica el último volumen llenado por Multiplier y envía una orden promedio en la misma dirección.
Reglas de salida
Cierre toda la posición tan pronto como el último precio de ejecución alcance un objetivo de beneficio dinámico de ProfitFactor × openOrders pips en la dirección favorable.
Restablezca el estado de martingala cada vez que el tamaño de la posición agregada vuelva a cero.
Gestión del riesgo
La progresión de martingala aumenta la exposición rápidamente cuando el precio se mueve en contra de la posición. Ajuste Multiplier, StepPoints y ProfitFactor cuidadosamente para que coincidan con el tamaño de la cuenta y la volatilidad del instrumento.
Parámetros
Nombre
Descripción
Volume
Volumen de orden de mercado base utilizado para la primera operación y cada complemento favorable.
Multiplier
Factor aplicado al último volumen ejecutado al promediar durante movimientos adversos.
StepPoints
Distancia en puntos que desencadena un orden de promediación de martingala.
ProfitFactor
Objetivo de beneficio por orden abierta expresado en puntos. La distancia real es ProfitFactor × number_of_orders.
KPeriod
Longitud retrospectiva para la línea %K.
DPeriod
Longitud de suavizado para la línea %D.
Slowing
Suavizado adicional aplicado a %K antes de comparar con %D.
BuyLevel
Valor mínimo de %D requerido para permitir una nueva secuencia larga.
SellLevel
Valor máximo de %D requerido para permitir una nueva secuencia corta.
CandleType
Serie de velas utilizadas para los cálculos (predeterminado: período de 5 minutos).
Notas
Funciona mejor en pares de divisas líquidos donde el tamaño del pip y el paso de volumen permiten un escalado granular.
Requiere margen suficiente para soportar varios pasos de martingala.
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>
/// Martingale strategy driven by stochastic oscillator crossovers.
/// Buy when K crosses above D, sell when K crosses below D.
/// Doubles down on adverse moves with martingale averaging.
/// </summary>
public class MartingailExpertSequenceStrategy : Strategy
{
private readonly StrategyParam<int> _kPeriod;
private readonly StrategyParam<int> _dPeriod;
private readonly StrategyParam<decimal> _stepPoints;
private readonly StrategyParam<decimal> _takeProfitPoints;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevK;
private decimal? _prevD;
private decimal _entryPrice;
public int KPeriod { get => _kPeriod.Value; set => _kPeriod.Value = value; }
public int DPeriod { get => _dPeriod.Value; set => _dPeriod.Value = value; }
public decimal StepPoints { get => _stepPoints.Value; set => _stepPoints.Value = value; }
public decimal TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MartingailExpertSequenceStrategy()
{
_kPeriod = Param(nameof(KPeriod), 14)
.SetDisplay("K Period", "Stochastic K period", "Indicators");
_dPeriod = Param(nameof(DPeriod), 3)
.SetDisplay("D Period", "Stochastic D period", "Indicators");
_stepPoints = Param(nameof(StepPoints), 500m)
.SetDisplay("Step Points", "Distance for martingale averaging", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 200m)
.SetDisplay("Take Profit", "Take profit in price steps", "Risk");
_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();
_prevK = null;
_prevD = null;
_entryPrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevK = null;
_prevD = null;
var stoch = new StochasticOscillator
{
K = { Length = KPeriod },
D = { Length = DPeriod }
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(stoch, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!stochValue.IsFinal)
return;
if (stochValue is not StochasticOscillatorValue stoch)
return;
if (stoch.K is not decimal k || stoch.D is not decimal d)
return;
var step = Security?.PriceStep ?? 1m;
if (step <= 0) step = 1m;
// Check take profit
if (Position > 0 && candle.ClosePrice >= _entryPrice + TakeProfitPoints * step)
{
SellMarket();
_prevK = k;
_prevD = d;
return;
}
else if (Position < 0 && candle.ClosePrice <= _entryPrice - TakeProfitPoints * step)
{
BuyMarket();
_prevK = k;
_prevD = d;
return;
}
if (_prevK is not decimal prevK || _prevD is not decimal prevD)
{
_prevK = k;
_prevD = d;
return;
}
// Stochastic crossover signals
var bullCross = prevK <= prevD && k > d;
var bearCross = prevK >= prevD && k < d;
if (Position == 0)
{
if (bullCross)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
}
else if (bearCross)
{
SellMarket();
_entryPrice = candle.ClosePrice;
}
}
else if (Position > 0 && bearCross)
{
SellMarket(); // Close long
SellMarket(); // Open short
_entryPrice = candle.ClosePrice;
}
else if (Position < 0 && bullCross)
{
BuyMarket(); // Close short
BuyMarket(); // Open long
_entryPrice = candle.ClosePrice;
}
_prevK = k;
_prevD = d;
}
}
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 StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
class martingail_expert_sequence_strategy(Strategy):
"""
Martingale Expert Sequence: stochastic K/D crossover with take profit.
"""
def __init__(self):
super(martingail_expert_sequence_strategy, self).__init__()
self._k_period = self.Param("KPeriod", 14).SetDisplay("K Period", "Stochastic K", "Indicators")
self._d_period = self.Param("DPeriod", 3).SetDisplay("D Period", "Stochastic D", "Indicators")
self._take_profit_points = self.Param("TakeProfitPoints", 200.0).SetDisplay("Take Profit", "TP in price steps", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candles", "General")
self._prev_k = None
self._prev_d = None
self._entry_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(martingail_expert_sequence_strategy, self).OnReseted()
self._prev_k = None
self._prev_d = None
self._entry_price = 0.0
def OnStarted2(self, time):
super(martingail_expert_sequence_strategy, self).OnStarted2(time)
stoch = StochasticOscillator()
stoch.K.Length = self._k_period.Value
stoch.D.Length = self._d_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(stoch, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, stoch)
self.DrawOwnTrades(area)
def _process_candle(self, candle, stoch_value):
if candle.State != CandleStates.Finished:
return
k_val = stoch_value.K
d_val = stoch_value.D
if k_val is None or d_val is None:
return
k = float(k_val)
d = float(d_val)
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
tp = float(self._take_profit_points.Value)
if self.Position > 0 and close >= self._entry_price + tp * step:
self.SellMarket()
self._prev_k = k
self._prev_d = d
return
elif self.Position < 0 and close <= self._entry_price - tp * step:
self.BuyMarket()
self._prev_k = k
self._prev_d = d
return
if self._prev_k is None or self._prev_d is None:
self._prev_k = k
self._prev_d = d
return
bull_cross = self._prev_k <= self._prev_d and k > d
bear_cross = self._prev_k >= self._prev_d and k < d
if self.Position == 0:
if bull_cross:
self.BuyMarket()
self._entry_price = close
elif bear_cross:
self.SellMarket()
self._entry_price = close
elif self.Position > 0 and bear_cross:
self.SellMarket()
self.SellMarket()
self._entry_price = close
elif self.Position < 0 and bull_cross:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._prev_k = k
self._prev_d = d
def CreateClone(self):
return martingail_expert_sequence_strategy()