Estratégia de Média Móvel Simples em Múltiplos Períodos
Esta estratégia replica a lógica de simple_multiple_time_frame_moving_average.mq4. Ela alinha tendências em dois períodos utilizando médias móveis simples.
Lógica da Estratégia
Calcula SMA com período Length em velas de 1 hora e 4 horas.
Entra comprado quando ambas as SMAs estão subindo.
Entra vendido quando ambas as SMAs estão caindo.
Fecha uma posição comprada quando qualquer SMA vira para baixo.
Fecha uma posição vendida quando qualquer SMA vira para cima.
Apenas uma posição pode estar ativa por vez.
Parâmetros
MA Length (Length): período utilizado para ambas as médias móveis.
Short Time Frame (ShortCandleType): período para a primeira SMA (padrão: 1 hora).
Long Time Frame (LongCandleType): período para a segunda SMA (padrão: 4 horas).
O volume de negociação é obtido da propriedade Volume da estratégia.
Notas
Esta implementação foca nas médias de uma hora e quatro horas usadas na versão MQL original e omite os cálculos de períodos superiores não utilizados.
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 using fast and slow SMA slopes for trade direction.
/// Buys when both SMAs are rising, sells when both are falling.
/// </summary>
public class SimpleMultipleTimeFrameMovingAverageStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevFast;
private decimal? _prevSlow;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public SimpleMultipleTimeFrameMovingAverageStrategy()
{
_fastLength = Param(nameof(FastLength), 5)
.SetDisplay("Fast MA", "Fast moving average period", "General");
_slowLength = Param(nameof(SlowLength), 20)
.SetDisplay("Slow MA", "Slow moving average period", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevFast = _prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastSma = new ExponentialMovingAverage { Length = FastLength };
var slowSma = new ExponentialMovingAverage { Length = SlowLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastSma, slowSma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastSma);
DrawIndicator(area, slowSma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast is decimal pf && _prevSlow is decimal ps)
{
var fastUp = fast > pf;
var fastDown = fast < pf;
var slowUp = slow > ps;
var slowDown = slow < ps;
if (fastUp && slowUp && Position <= 0)
BuyMarket();
else if (fastDown && slowDown && 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 simple_multiple_time_frame_moving_average_strategy(Strategy):
def __init__(self):
super(simple_multiple_time_frame_moving_average_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 5) \
.SetDisplay("Fast MA", "Fast moving average period", "General")
self._slow_length = self.Param("SlowLength", 20) \
.SetDisplay("Slow MA", "Slow moving average period", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for candles", "General")
self._prev_fast = None
self._prev_slow = None
@property
def fast_length(self):
return self._fast_length.Value
@property
def slow_length(self):
return self._slow_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(simple_multiple_time_frame_moving_average_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(simple_multiple_time_frame_moving_average_strategy, self).OnStarted2(time)
fast_sma = ExponentialMovingAverage()
fast_sma.Length = self.fast_length
slow_sma = ExponentialMovingAverage()
slow_sma.Length = self.slow_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_sma, slow_sma, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_sma)
self.DrawIndicator(area, slow_sma)
self.DrawOwnTrades(area)
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
f = float(fast)
s = float(slow)
if self._prev_fast is not None and self._prev_slow is not None:
fast_up = f > self._prev_fast
fast_down = f < self._prev_fast
slow_up = s > self._prev_slow
slow_down = s < self._prev_slow
if fast_up and slow_up and self.Position <= 0:
self.BuyMarket()
elif fast_down and slow_down and self.Position >= 0:
self.SellMarket()
self._prev_fast = f
self._prev_slow = s
def CreateClone(self):
return simple_multiple_time_frame_moving_average_strategy()