Estratégia de Ajuste Fino de MA
Esta estratégia monitora a inclinação de uma média móvel simples. Após duas barras consecutivas em uma direção, uma reversão da média móvel dispara uma entrada. Um giro ascendente após uma queda abre uma posição comprada, enquanto um giro descendente após uma alta abre uma posição vendida. Sinais opostos fecham as operações existentes.
O sistema foi convertido do consultor MQL "Exp_FineTuningMA" e substitui o indicador personalizado original por uma média móvel simples padrão para maior clareza.
Detalhes
- Critérios de entrada: A MA muda de direção após duas barras.
- Comprado/Vendido: Ambos.
- Critérios de saída: Sinal oposto ou stop.
- Stops: Sim, baseados em percentual.
- Valores padrão:
MaLength= 10TakeProfitPercent= 1StopLossPercent= 1CandleType= TimeSpan.FromHours(4)
- Filtros:
- Categoria: Seguidor de tendência
- Direção: Ambos
- Indicadores: SMA
- Stops: Sim
- Complexidade: Intermediário
- Período: Swing / H4
- Sazonalidade: Não
- Redes neurais: Não
- Divergência: Não
- Nível de risco: Médio
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>
/// Fine Tuning MA strategy. Opens positions when the moving average changes direction.
/// </summary>
public class FineTuningMaStrategy : Strategy
{
private readonly StrategyParam<int> _maLength;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private decimal _prev1;
private decimal _prev2;
private int _candleCount;
public int MaLength { get => _maLength.Value; set => _maLength.Value = value; }
public decimal TakeProfitPercent { get => _takeProfitPercent.Value; set => _takeProfitPercent.Value = value; }
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FineTuningMaStrategy()
{
_maLength = Param(nameof(MaLength), 20)
.SetGreaterThanZero()
.SetDisplay("MA Length", "Length of the moving average", "Parameters");
_takeProfitPercent = Param(nameof(TakeProfitPercent), 1m)
.SetDisplay("Take Profit, %", "Take profit level in percent", "Protection");
_stopLossPercent = Param(nameof(StopLossPercent), 1m)
.SetDisplay("Stop Loss, %", "Stop loss level in percent", "Protection");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for calculations", "Parameters");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prev1 = default;
_prev2 = default;
_candleCount = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ma = new ExponentialMovingAverage { Length = MaLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ma, ProcessCandle).Start();
StartProtection(
new Unit(StopLossPercent, UnitTypes.Percent),
new Unit(TakeProfitPercent, UnitTypes.Percent));
}
private void ProcessCandle(ICandleMessage candle, decimal ma)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
_candleCount++;
if (_candleCount <= 2)
{
_prev2 = _prev1;
_prev1 = ma;
return;
}
var wasRising = _prev1 > _prev2;
var wasFalling = _prev1 < _prev2;
if (wasRising && ma > _prev1 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (wasFalling && ma < _prev1 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prev2 = _prev1;
_prev1 = ma;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class fine_tuning_ma_strategy(Strategy):
def __init__(self):
super(fine_tuning_ma_strategy, self).__init__()
self._ma_length = self.Param("MaLength", 20) \
.SetDisplay("MA Length", "Length of the moving average", "Parameters")
self._take_profit_percent = self.Param("TakeProfitPercent", 1.0) \
.SetDisplay("Take Profit, %", "Take profit level in percent", "Protection")
self._stop_loss_percent = self.Param("StopLossPercent", 1.0) \
.SetDisplay("Stop Loss, %", "Stop loss level in percent", "Protection")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles for calculations", "Parameters")
self._prev1 = 0.0
self._prev2 = 0.0
self._candle_count = 0
@property
def MaLength(self):
return self._ma_length.Value
@MaLength.setter
def MaLength(self, value):
self._ma_length.Value = value
@property
def TakeProfitPercent(self):
return self._take_profit_percent.Value
@TakeProfitPercent.setter
def TakeProfitPercent(self, value):
self._take_profit_percent.Value = value
@property
def StopLossPercent(self):
return self._stop_loss_percent.Value
@StopLossPercent.setter
def StopLossPercent(self, value):
self._stop_loss_percent.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(fine_tuning_ma_strategy, self).OnStarted2(time)
ma = ExponentialMovingAverage()
ma.Length = self.MaLength
self.SubscribeCandles(self.CandleType) \
.Bind(ma, self.ProcessCandle) \
.Start()
self.StartProtection(
stopLoss=Unit(self.StopLossPercent, UnitTypes.Percent),
takeProfit=Unit(self.TakeProfitPercent, UnitTypes.Percent)
)
def ProcessCandle(self, candle, ma_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
val = float(ma_value)
self._candle_count += 1
if self._candle_count <= 2:
self._prev2 = self._prev1
self._prev1 = val
return
was_rising = self._prev1 > self._prev2
was_falling = self._prev1 < self._prev2
if was_rising and val > self._prev1 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif was_falling and val < self._prev1 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev2 = self._prev1
self._prev1 = val
def OnReseted(self):
super(fine_tuning_ma_strategy, self).OnReseted()
self._prev1 = 0.0
self._prev2 = 0.0
self._candle_count = 0
def CreateClone(self):
return fine_tuning_ma_strategy()