Estrategia Color Zerolag X10 Ma
Esta estrategia es un port simplificado del ejemplo de MetaTrader Exp_ColorZerolagX10MA.mq5. Utiliza una media móvil exponencial de cero rezago para detectar cambios de pendiente. Cuando la media móvil gira hacia arriba después de decrecer durante dos barras, la estrategia abre o revierte a una posición larga. Por el contrario, cuando la media móvil gira hacia abajo después de aumentar, abre o revierte a una posición corta.
La lógica imita la idea original donde un conjunto combinado de diez medias móviles suavizadas produce una única línea codificada por colores. Aquí reemplazamos ese indicador complejo con el ZeroLagExponentialMovingAverage integrado de StockSharp para mantener la implementación compacta y reutilizable. El sistema trabaja en el marco temporal de velas seleccionado y puede habilitar o deshabilitar acciones individuales (abrir/cerrar largo/corto) mediante parámetros.
Detalles
- Criterios de entrada:
- Largo:
ZLEMA[t-2] > ZLEMA[t-1] y ZLEMA[t] > ZLEMA[t-1].
- Corto:
ZLEMA[t-2] < ZLEMA[t-1] y ZLEMA[t] < ZLEMA[t-1].
- Largo/Corto: Ambas direcciones soportadas.
- Criterios de salida:
- Las posiciones largas se cierran cuando aparece una señal corta y
BuyPosClose está habilitado.
- Las posiciones cortas se cierran cuando aparece una señal larga y
SellPosClose está habilitado.
- Stops: Ninguno por defecto; las salidas dependen de señales opuestas.
- Valores predeterminados:
Length = 20.
CandleType = marco temporal de 4 horas.
- Todos los indicadores de acción (
BuyPosOpen, SellPosOpen, BuyPosClose, SellPosClose) habilitados.
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: Único
- Stops: No
- Complejidad: Simple
- Marco temporal: Medio plazo
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// Trades ZLEMA slope reversals with independent long/short entry/exit switches.
/// </summary>
public class ColorZerolagX10MaStrategy : Strategy
{
private readonly StrategyParam<int> _length;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<bool> _openBuy;
private readonly StrategyParam<bool> _openSell;
private readonly StrategyParam<bool> _closeBuy;
private readonly StrategyParam<bool> _closeSell;
private decimal? _previous;
private decimal? _beforePrevious;
private Order _pendingOrder;
public int Length { get => _length.Value; set => _length.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public bool BuyPosOpen { get => _openBuy.Value; set => _openBuy.Value = value; }
public bool SellPosOpen { get => _openSell.Value; set => _openSell.Value = value; }
public bool BuyPosClose { get => _closeBuy.Value; set => _closeBuy.Value = value; }
public bool SellPosClose { get => _closeSell.Value; set => _closeSell.Value = value; }
public ColorZerolagX10MaStrategy()
{
_length = Param(nameof(Length), 20).SetGreaterThanZero()
.SetDisplay("Length", "ZLEMA length", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_openBuy = Param(nameof(BuyPosOpen), true).SetDisplay("Open Buy", "Allow long entries", "Trading");
_openSell = Param(nameof(SellPosOpen), true).SetDisplay("Open Sell", "Allow short entries", "Trading");
_closeBuy = Param(nameof(BuyPosClose), true).SetDisplay("Close Buy", "Allow long exits", "Trading");
_closeSell = Param(nameof(SellPosClose), true).SetDisplay("Close Sell", "Allow short exits", "Trading");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_previous = _beforePrevious = null;
_pendingOrder = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_previous = _beforePrevious = null;
_pendingOrder = null;
var zlma = new ZeroLagExponentialMovingAverage { Length = Length };
SubscribeCandles(CandleType).Bind(zlma, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal current)
{
if (candle.State != CandleStates.Finished)
return;
var turnUp = _beforePrevious is decimal older && _previous is decimal previous
&& previous < older && current > previous;
var turnDown = _beforePrevious is decimal olderDown && _previous is decimal previousDown
&& previousDown > olderDown && current < previousDown;
_beforePrevious = _previous;
_previous = current;
if (!IsFormedAndOnlineAndAllowTrading()
|| (_pendingOrder is not null && _pendingOrder.State is not (OrderStates.Done or OrderStates.Failed)))
return;
if (turnUp)
{
if (Position < 0m && SellPosClose)
_pendingOrder = BuyMarket(-Position + (BuyPosOpen ? Volume : 0m));
else if (Position == 0m && BuyPosOpen)
_pendingOrder = BuyMarket(Volume);
}
else if (turnDown)
{
if (Position > 0m && BuyPosClose)
_pendingOrder = SellMarket(Position + (SellPosOpen ? Volume : 0m));
else if (Position == 0m && SellPosOpen)
_pendingOrder = SellMarket(Volume);
}
}
}
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, OrderStates
from StockSharp.Algo.Indicators import ZeroLagExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class color_zerolag_x10_ma_strategy(Strategy):
"""ZLEMA slope reversals with independent entry and exit permissions."""
def __init__(self):
super(color_zerolag_x10_ma_strategy, self).__init__()
self._length = self.Param("Length", 20).SetDisplay("Length", "ZLEMA length", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._open_buy = self.Param("BuyPosOpen", True).SetDisplay("Open Buy", "Allow long entries", "Trading")
self._open_sell = self.Param("SellPosOpen", True).SetDisplay("Open Sell", "Allow short entries", "Trading")
self._close_buy = self.Param("BuyPosClose", True).SetDisplay("Close Buy", "Allow long exits", "Trading")
self._close_sell = self.Param("SellPosClose", True).SetDisplay("Close Sell", "Allow short exits", "Trading")
self._previous = None
self._before_previous = None
self._pending_order = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(color_zerolag_x10_ma_strategy, self).OnReseted()
self._previous = self._before_previous = None
self._pending_order = None
def OnStarted2(self, time):
super(color_zerolag_x10_ma_strategy, self).OnStarted2(time)
self._previous = self._before_previous = None
self._pending_order = None
zlma = ZeroLagExponentialMovingAverage()
zlma.Length = self._length.Value
self.SubscribeCandles(self.CandleType).Bind(zlma, self.on_process).Start()
def on_process(self, candle, value):
if candle.State != CandleStates.Finished:
return
current = float(value)
up = self._before_previous is not None and self._previous < self._before_previous and current > self._previous
down = self._before_previous is not None and self._previous > self._before_previous and current < self._previous
self._before_previous, self._previous = self._previous, current
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self._pending_order is not None and self._pending_order.State not in (OrderStates.Done, OrderStates.Failed):
return
if up:
if self.Position < 0 and self._close_sell.Value:
amount = -self.Position + (self.Volume if self._open_buy.Value else 0)
self._pending_order = self.BuyMarket(amount)
elif self.Position == 0 and self._open_buy.Value:
self._pending_order = self.BuyMarket(self.Volume)
elif down:
if self.Position > 0 and self._close_buy.Value:
amount = self.Position + (self.Volume if self._open_sell.Value else 0)
self._pending_order = self.SellMarket(amount)
elif self.Position == 0 and self._open_sell.Value:
self._pending_order = self.SellMarket(self.Volume)
def CreateClone(self):
return color_zerolag_x10_ma_strategy()