Esta estrategia implementa una cuadrícula de martingala con cobertura. Comienza colocando órdenes stop en ambos lados del precio actual y duplica el tamaño de la posición en la dirección opuesta siempre que el mercado se mueva contra la exposición actual en un paso especificado. Todas las operaciones se cierran una vez que el beneficio acumulado supera el objetivo.
Detalles
Criterios de entrada:
Colocar un buy stop por encima y un sell stop por debajo del mercado a distancia Step.
Cuando se activa una orden, cancelar el stop opuesto.
Gestión de la posición:
Rastrear el precio de la última orden ejecutada.
Si el precio se mueve contra la posición abierta en Step * orderCount, enviar una orden de mercado en la dirección opuesta con el doble del volumen anterior.
Criterios de salida:
Cerrar todas las posiciones cuando el beneficio no realizado alcanza ProfitClose.
Largo/Corto: Ambos.
Stops: Usa órdenes stop para entradas iniciales; sin stop-loss.
Indicadores: Ninguno.
Filtros: Ninguno.
Parámetros
Step – paso de precio en unidades absolutas.
ProfitClose – umbral de beneficio para cerrar todas las operaciones.
InitialVolume – volumen inicial para la primera orden.
CandleType – serie de velas usada para actualizaciones de precio.
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>
/// Mean reversion strategy inspired by martingale.
/// Enters on RSI extremes, exits when price returns to SMA.
/// </summary>
public class MartiniMartingaleStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<DataType> _candleType;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MartiniMartingaleStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 7)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA for mean reversion target", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var sma = new SimpleMovingAverage { Length = SmaPeriod };
SubscribeCandles(CandleType).Bind(rsi, sma, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsi, decimal sma)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
// RSI oversold => buy
if (rsi < 30 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// RSI overbought => sell
else if (rsi > 70 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
// Exit long at SMA
else if (Position > 0 && close >= sma && rsi > 50)
{
SellMarket();
}
// Exit short at SMA
else if (Position < 0 && close <= sma && rsi < 50)
{
BuyMarket();
}
}
}
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, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class martini_martingale_strategy(Strategy):
def __init__(self):
super(martini_martingale_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 7) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._sma_period = self.Param("SmaPeriod", 20) \
.SetDisplay("SMA Period", "SMA for mean reversion target", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def sma_period(self):
return self._sma_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(martini_martingale_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
sma = SimpleMovingAverage()
sma.Length = self.sma_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, sma, 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, sma):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
# RSI oversold => buy
if rsi < 30 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# RSI overbought => sell
elif rsi > 70 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Exit long at SMA
elif self.Position > 0 and close >= sma and rsi > 50:
self.SellMarket()
# Exit short at SMA
elif self.Position < 0 and close <= sma and rsi < 50:
self.BuyMarket()
def CreateClone(self):
return martini_martingale_strategy()