Esta estrategia es una implementación en StockSharp inspirada en el Expert Advisor original de MQL5 "Exp_ColorMETRO_XRSX". Utiliza dos medias móviles suavizadas para detectar cambios de tendencia. Se abre una posición larga cuando la media rápida cruza por encima de la media lenta, mientras que se abre una posición corta cuando la media rápida cruza por debajo de la media lenta.
Parámetros
Fast Period – período de la media móvil rápida.
Slow Period – período de la media móvil lenta.
Candle Type – marco temporal de las velas utilizadas para los cálculos.
Cómo Funciona
La estrategia se suscribe a la serie de velas seleccionada.
Se calculan dos indicadores Sma con diferentes períodos sobre el precio de cierre.
Cuando la SMA rápida cruza por encima de la SMA lenta, se cierra cualquier posición corta y se abre una posición larga.
Cuando la SMA rápida cruza por debajo de la SMA lenta, se cierra cualquier posición larga y se abre una posición corta.
Los valores previos de las medias se almacenan para detectar cruces solo una vez.
Notas
La estrategia utiliza la API de alto nivel con Bind para el procesamiento de indicadores.
StartProtection está habilitado para gestionar los mecanismos de protección.
Esta implementación es una traducción simplificada y no utiliza el indicador personalizado original.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on the cross of two smoothed lines inspired by the ColorMETRO XRSX indicator.
/// Opens a long position when the fast line crosses above the slow line and
/// opens a short position when the fast line crosses below the slow line.
/// </summary>
public class ColorMetroXrsxStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevFast;
private decimal? _prevSlow;
/// <summary>
/// Fast moving average period.
/// </summary>
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
/// <summary>
/// Slow moving average period.
/// </summary>
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="ColorMetroXrsxStrategy"/> class.
/// </summary>
public ColorMetroXrsxStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast moving average length", "Parameters")
;
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow moving average length", "Parameters")
;
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to process", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = _prevSlow = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_prevFast is decimal prevFast && _prevSlow is decimal prevSlow)
{
if (prevFast <= prevSlow && fast > slow && Position <= 0)
BuyMarket();
if (prevFast >= prevSlow && fast < slow && Position >= 0)
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class color_metro_xrsx_strategy(Strategy):
def __init__(self):
super(color_metro_xrsx_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast Period", "Fast moving average length", "Parameters")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow Period", "Slow moving average length", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to process", "General")
self._prev_fast = None
self._prev_slow = None
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_metro_xrsx_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(color_metro_xrsx_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
f = float(fast_val)
s = float(slow_val)
if self._prev_fast is not None and self._prev_slow is not None:
if self._prev_fast <= self._prev_slow and f > s and self.Position <= 0:
self.BuyMarket()
if self._prev_fast >= self._prev_slow and f < s and self.Position >= 0:
self.SellMarket()
self._prev_fast = f
self._prev_slow = s
def CreateClone(self):
return color_metro_xrsx_strategy()