Estratégia MA MACD BB BackTester
Estratégia que combina três indicadores selecionáveis: cruzamento de média móvel simples, cruzamento de MACD ou rompimento de Bandas de Bollinger. Apenas um modo de indicador fica ativo por vez, e a direção da operação pode ser comprada ou vendida.
Parâmetros
CandleType— período de tempo das velas.Indicator— indicador a utilizar (MA, MACD, BB).Direction— direção da operação (Long ou Short).MaLength— período da média móvel.FastLength— comprimento da EMA rápida do MACD.SlowLength— comprimento da EMA lenta do MACD.SignalLength— comprimento do sinal do MACD.BbLength— período das Bandas de Bollinger.BbMultiplier— multiplicador das Bandas de Bollinger.StartDate— data de início.EndDate— data de fim.
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 using MA crossover with price for entry/exit.
/// </summary>
public class MaMacdBbBackTesterStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maLength;
private ExponentialMovingAverage _ma;
private decimal _prevClose;
private decimal _prevMa;
private bool _initialized;
private int _cooldown;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int MaLength { get => _maLength.Value; set => _maLength.Value = value; }
public MaMacdBbBackTesterStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_maLength = Param(nameof(MaLength), 20)
.SetDisplay("MA Length", "MA period", "Indicators");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = default;
_prevMa = default;
_initialized = false;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_ma = new ExponentialMovingAverage { Length = MaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal maVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!_ma.IsFormed)
return;
if (!_initialized)
{
_prevClose = candle.ClosePrice;
_prevMa = maVal;
_initialized = true;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevClose = candle.ClosePrice;
_prevMa = maVal;
return;
}
var crossUp = _prevClose <= _prevMa && candle.ClosePrice > maVal;
var crossDown = _prevClose >= _prevMa && candle.ClosePrice < maVal;
if (crossUp && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_cooldown = 10;
}
else if (crossDown && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_cooldown = 10;
}
_prevClose = candle.ClosePrice;
_prevMa = maVal;
}
}
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 ma_macd_bb_back_tester_strategy(Strategy):
def __init__(self):
super(ma_macd_bb_back_tester_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._ma_length = self.Param("MaLength", 20) \
.SetDisplay("MA Length", "MA period", "Indicators")
self._prev_close = 0.0
self._prev_ma = 0.0
self._initialized = False
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(ma_macd_bb_back_tester_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_ma = 0.0
self._initialized = False
self._cooldown = 0
def OnStarted2(self, time):
super(ma_macd_bb_back_tester_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_ma = 0.0
self._initialized = False
self._cooldown = 0
self._ma = ExponentialMovingAverage()
self._ma.Length = self._ma_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._ma, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._ma)
self.DrawOwnTrades(area)
def OnProcess(self, candle, ma_val):
if candle.State != CandleStates.Finished:
return
if not self._ma.IsFormed:
return
mv = float(ma_val)
close = float(candle.ClosePrice)
if not self._initialized:
self._prev_close = close
self._prev_ma = mv
self._initialized = True
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_close = close
self._prev_ma = mv
return
cross_up = self._prev_close <= self._prev_ma and close > mv
cross_down = self._prev_close >= self._prev_ma and close < mv
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown = 10
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown = 10
self._prev_close = close
self._prev_ma = mv
def CreateClone(self):
return ma_macd_bb_back_tester_strategy()