Esta estrategia replica la lógica del experto original X_alert_3.mq4. Monitorea dos medias móviles con parámetros configurables y produce una alerta informativa cuando se produce un cruce.
Cómo funciona
Se calculan dos medias móviles en cada vela completada.
Se genera una alerta alcista cuando:
MA1 está por encima de MA2 en la vela actual.
MA1 está por encima de MA2 en la vela anterior.
MA1 estaba por debajo de MA2 hace dos velas.
Se genera una alerta bajista cuando:
MA1 está por debajo de MA2 en la vela actual.
MA1 está por debajo de MA2 en la vela anterior.
MA1 estaba por encima de MA2 hace dos velas.
La estrategia no abre ni cierra ninguna posición. Solo escribe mensajes en el registro.
Parámetros
Parámetro
Descripción
Predeterminado
Ma1Period
Período de la primera media móvil.
1
Ma1Type
Tipo de la primera media móvil (Simple, Exponential, Smoothed, Weighted).
Simple
Ma2Period
Período de la segunda media móvil.
14
Ma2Type
Tipo de la segunda media móvil.
Simple
PriceType
Precio fuente usado en los cálculos (Close, Open, High, Low, Median, Typical, Weighted).
Median
CandleType
Serie de velas usada para el procesamiento.
marco temporal de 1 minuto
Notas
La implementación rastrea las últimas dos diferencias entre las medias móviles para detectar cruces sin acceder directamente a valores históricos del indicador.
Las alertas se escriben usando AddInfoLog para mantener la estrategia sin efectos secundarios.
El parámetro de MetaTrader RunIntervalSeconds no es necesario en StockSharp y ha sido omitido.
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>
/// Strategy based on crossover of two moving averages.
/// Buys when fast MA crosses above slow MA, sells when crosses below.
/// </summary>
public class XAlert3Strategy : Strategy
{
private readonly StrategyParam<int> _ma1Period;
private readonly StrategyParam<int> _ma2Period;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int Ma1Period { get => _ma1Period.Value; set => _ma1Period.Value = value; }
public int Ma2Period { get => _ma2Period.Value; set => _ma2Period.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public XAlert3Strategy()
{
_ma1Period = Param(nameof(Ma1Period), 10)
.SetGreaterThanZero()
.SetDisplay("MA1 Period", "Fast moving average period", "Indicators");
_ma2Period = Param(nameof(Ma2Period), 30)
.SetGreaterThanZero()
.SetDisplay("MA2 Period", "Slow moving average period", "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 OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = Ma1Period };
var slow = new ExponentialMovingAverage { Length = Ma2Period };
SubscribeCandles(CandleType)
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
if (_prevFast <= _prevSlow && fast > slow)
{
if (Position < 0) BuyMarket();
if (Position <= 0) BuyMarket();
}
else if (_prevFast >= _prevSlow && fast < slow)
{
if (Position > 0) SellMarket();
if (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 x_alert3_strategy(Strategy):
def __init__(self):
super(x_alert3_strategy, self).__init__()
self._ma1_period = self.Param("Ma1Period", 10) \
.SetDisplay("MA1 Period", "Fast moving average period", "Indicators")
self._ma2_period = self.Param("Ma2Period", 30) \
.SetDisplay("MA2 Period", "Slow moving average period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def ma1_period(self):
return self._ma1_period.Value
@property
def ma2_period(self):
return self._ma2_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(x_alert3_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(x_alert3_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self.ma1_period
slow = ExponentialMovingAverage()
slow.Length = self.ma2_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_fast = fast
self._prev_slow = slow
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fast > slow:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast < slow:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return x_alert3_strategy()