Estratégia de Rastreamento de Liquidez MACD
MACD Liquidity Tracker utiliza os estados de cor do MACD para gerar sinais de negociação. Quatro modos (Fast, Normal, Safe, Crossover) ajustam a sensibilidade dos sinais. Stop loss e take profit opcionais são suportados.
Detalhes
- Dados: Velas de preço.
- Critérios de entrada:
- Comprado: Depende de
SystemType(padrãoNormalusa MACD acima da linha de sinal). - Vendido: Depende de
SystemType(padrãoNormalusa MACD abaixo da linha de sinal).
- Comprado: Depende de
- Critérios de saída: Sinal oposto.
- Stops: Stop loss e take profit opcionais.
- Valores padrão:
FastLength= 25SlowLength= 60SignalLength= 220AllowShortTrades= falseSystemType= NormalUseStopLoss= falseStopLossPercent= 3UseTakeProfit= falseTakeProfitPercent= 6StartDate= 2018-01-01EndDate= 2069-12-31CandleType= tf(5)
- Filtros:
- Categoria: Tendência
- Direção: Comprado/Vendido
- Indicadores: MACD
- Stops: Sim
- Complexidade: Básico
- Período: Intradiário (5m)
- 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>
/// MACD Liquidity Tracker strategy.
/// The MACD colour state produces the signals. SystemType selects the sensitivity: "Fast" follows the histogram direction,
/// "Normal" follows MACD above or below its signal line, "Safe" also requires MACD on the same side of zero and "Crossover"
/// signals only on the bar where MACD crosses its signal line. A bullish signal goes long, a bearish signal closes the long and,
/// when AllowShortTrades is enabled, goes short. Trades are taken between StartDate and EndDate, with optional percent stop loss
/// and take profit.
/// </summary>
public class MacdLiquidityTrackerStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _signalLength;
private readonly StrategyParam<bool> _allowShortTrades;
private readonly StrategyParam<string> _systemType;
private readonly StrategyParam<bool> _useStopLoss;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<bool> _useTakeProfit;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<DateTimeOffset> _startDate;
private readonly StrategyParam<DateTimeOffset> _endDate;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevMacd;
private decimal? _prevSignal;
/// <summary>
/// MACD fast EMA length.
/// </summary>
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
/// <summary>
/// MACD slow EMA length.
/// </summary>
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
/// <summary>
/// MACD signal line length.
/// </summary>
public int SignalLength
{
get => _signalLength.Value;
set => _signalLength.Value = value;
}
/// <summary>
/// Allow short positions.
/// </summary>
public bool AllowShortTrades
{
get => _allowShortTrades.Value;
set => _allowShortTrades.Value = value;
}
/// <summary>
/// Signal mode: Fast, Normal, Safe or Crossover.
/// </summary>
public string SystemType
{
get => _systemType.Value;
set => _systemType.Value = value;
}
/// <summary>
/// Enable stop loss.
/// </summary>
public bool UseStopLoss
{
get => _useStopLoss.Value;
set => _useStopLoss.Value = value;
}
/// <summary>
/// Stop loss percentage.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Enable take profit.
/// </summary>
public bool UseTakeProfit
{
get => _useTakeProfit.Value;
set => _useTakeProfit.Value = value;
}
/// <summary>
/// Take profit percentage.
/// </summary>
public decimal TakeProfitPercent
{
get => _takeProfitPercent.Value;
set => _takeProfitPercent.Value = value;
}
/// <summary>
/// First date trades are allowed.
/// </summary>
public DateTimeOffset StartDate
{
get => _startDate.Value;
set => _startDate.Value = value;
}
/// <summary>
/// Last date trades are allowed.
/// </summary>
public DateTimeOffset EndDate
{
get => _endDate.Value;
set => _endDate.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public MacdLiquidityTrackerStrategy()
{
_fastLength = Param(nameof(FastLength), 25)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "MACD fast EMA length", "MACD");
_slowLength = Param(nameof(SlowLength), 60)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "MACD slow EMA length", "MACD");
_signalLength = Param(nameof(SignalLength), 220)
.SetGreaterThanZero()
.SetDisplay("Signal Length", "MACD signal line length", "MACD");
_allowShortTrades = Param(nameof(AllowShortTrades), false)
.SetDisplay("Allow Short Trades", "Allow short positions", "Trading");
_systemType = Param(nameof(SystemType), "Normal")
.SetDisplay("System Type", "Signal mode: Fast, Normal, Safe or Crossover", "Trading");
_useStopLoss = Param(nameof(UseStopLoss), false)
.SetDisplay("Use Stop Loss", "Enable stop loss", "Risk");
_stopLossPercent = Param(nameof(StopLossPercent), 3m)
.SetNotNegative()
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
_useTakeProfit = Param(nameof(UseTakeProfit), false)
.SetDisplay("Use Take Profit", "Enable take profit", "Risk");
_takeProfitPercent = Param(nameof(TakeProfitPercent), 6m)
.SetNotNegative()
.SetDisplay("Take Profit %", "Take profit percentage", "Risk");
_startDate = Param(nameof(StartDate), new DateTimeOffset(2018, 1, 1, 0, 0, 0, TimeSpan.Zero))
.SetDisplay("Start Date", "First date trades are allowed", "Time");
_endDate = Param(nameof(EndDate), new DateTimeOffset(2069, 12, 31, 23, 59, 0, TimeSpan.Zero))
.SetDisplay("End Date", "Last date trades are allowed", "Time");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMacd = null;
_prevSignal = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevMacd = null;
_prevSignal = null;
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd =
{
ShortMa = { Length = FastLength },
LongMa = { Length = SlowLength },
},
SignalMa = { Length = SignalLength }
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(macd, ProcessCandle)
.Start();
if (UseStopLoss || UseTakeProfit)
{
StartProtection(
UseTakeProfit ? new Unit(TakeProfitPercent, UnitTypes.Percent) : new Unit(),
UseStopLoss ? new Unit(StopLossPercent, UnitTypes.Percent) : new Unit(),
useMarketOrders: true);
}
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
var oscillators = CreateChartArea();
if (oscillators != null)
DrawIndicator(oscillators, macd);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!macdValue.IsFormed || macdValue is not IMovingAverageConvergenceDivergenceSignalValue { Macd: decimal macdLine, Signal: decimal signalLine })
return;
var prevMacd = _prevMacd;
var prevSignal = _prevSignal;
_prevMacd = macdLine;
_prevSignal = signalLine;
if (prevMacd is not decimal pm || prevSignal is not decimal ps)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (candle.OpenTime < StartDate.UtcDateTime || candle.OpenTime > EndDate.UtcDateTime)
return;
var histogram = macdLine - signalLine;
var prevHistogram = pm - ps;
bool bullish, bearish;
switch (SystemType?.Trim().ToLowerInvariant())
{
case "fast":
bullish = histogram > prevHistogram;
bearish = histogram < prevHistogram;
break;
case "safe":
bullish = macdLine > signalLine && macdLine > 0;
bearish = macdLine < signalLine && macdLine < 0;
break;
case "crossover":
bullish = pm <= ps && macdLine > signalLine;
bearish = pm >= ps && macdLine < signalLine;
break;
default:
bullish = macdLine > signalLine;
bearish = macdLine < signalLine;
break;
}
if (bullish && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
}
else if (bearish)
{
if (AllowShortTrades && Position >= 0)
SellMarket(Volume + Position);
else if (Position > 0)
SellMarket(Position);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal, DateTimeOffset
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class macd_liquidity_tracker_strategy(Strategy):
"""
MACD Liquidity Tracker strategy.
The MACD colour state produces the signals. SystemType selects the sensitivity: "Fast" follows the histogram direction,
"Normal" follows MACD above or below its signal line, "Safe" also requires MACD on the same side of zero and "Crossover"
signals only on the bar where MACD crosses its signal line. A bullish signal goes long, a bearish signal closes the long and,
when AllowShortTrades is enabled, goes short. Trades are taken between StartDate and EndDate, with optional percent stop loss
and take profit.
"""
def __init__(self):
super(macd_liquidity_tracker_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 25).SetGreaterThanZero().SetDisplay("Fast Length", "MACD fast EMA length", "MACD")
self._slow_length = self.Param("SlowLength", 60).SetGreaterThanZero().SetDisplay("Slow Length", "MACD slow EMA length", "MACD")
self._signal_length = self.Param("SignalLength", 220).SetGreaterThanZero().SetDisplay("Signal Length", "MACD signal line length", "MACD")
self._allow_short_trades = self.Param("AllowShortTrades", False).SetDisplay("Allow Short Trades", "Allow short positions", "Trading")
self._system_type = self.Param("SystemType", "Normal").SetDisplay("System Type", "Signal mode: Fast, Normal, Safe or Crossover", "Trading")
self._use_stop_loss = self.Param("UseStopLoss", False).SetDisplay("Use Stop Loss", "Enable stop loss", "Risk")
self._stop_loss_percent = self.Param("StopLossPercent", 3.0).SetNotNegative().SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._use_take_profit = self.Param("UseTakeProfit", False).SetDisplay("Use Take Profit", "Enable take profit", "Risk")
self._take_profit_percent = self.Param("TakeProfitPercent", 6.0).SetNotNegative().SetDisplay("Take Profit %", "Take profit percentage", "Risk")
self._start_date = self.Param("StartDate", DateTimeOffset(2018, 1, 1, 0, 0, 0, TimeSpan.Zero)).SetDisplay("Start Date", "First date trades are allowed", "Time")
self._end_date = self.Param("EndDate", DateTimeOffset(2069, 12, 31, 23, 59, 0, TimeSpan.Zero)).SetDisplay("End Date", "Last date trades are allowed", "Time")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._reset_state()
@property
def candle_type(self):
return self._candle_type.Value
def _reset_state(self):
self._prev_macd = None
self._prev_signal = None
def OnReseted(self):
super(macd_liquidity_tracker_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(macd_liquidity_tracker_strategy, self).OnStarted2(time)
self._reset_state()
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = self._fast_length.Value
macd.Macd.LongMa.Length = self._slow_length.Value
macd.SignalMa.Length = self._signal_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(macd, self._process_candle).Start()
use_sl = self._use_stop_loss.Value
use_tp = self._use_take_profit.Value
if use_sl or use_tp:
tp = Unit(Decimal(self._take_profit_percent.Value), UnitTypes.Percent) if use_tp else Unit()
sl = Unit(Decimal(self._stop_loss_percent.Value), UnitTypes.Percent) if use_sl else Unit()
self.StartProtection(tp, sl, useMarketOrders=True)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
oscillators = self.CreateChartArea()
if oscillators is not None:
self.DrawIndicator(oscillators, macd)
def _process_candle(self, candle, macd_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFormed:
return
macd_line = macd_value.Macd
signal_line = macd_value.Signal
if macd_line is None or signal_line is None:
return
pm = self._prev_macd
ps = self._prev_signal
self._prev_macd = macd_line
self._prev_signal = signal_line
if pm is None or ps is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if candle.OpenTime < self._start_date.Value.UtcDateTime or candle.OpenTime > self._end_date.Value.UtcDateTime:
return
zero = Decimal(0)
histogram = macd_line - signal_line
prev_histogram = pm - ps
mode = str(self._system_type.Value or "").strip().lower()
if mode == "fast":
bullish = histogram > prev_histogram
bearish = histogram < prev_histogram
elif mode == "safe":
bullish = macd_line > signal_line and macd_line > zero
bearish = macd_line < signal_line and macd_line < zero
elif mode == "crossover":
bullish = pm <= ps and macd_line > signal_line
bearish = pm >= ps and macd_line < signal_line
else:
bullish = macd_line > signal_line
bearish = macd_line < signal_line
if bullish and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif bearish:
if self._allow_short_trades.Value and self.Position >= 0:
self.SellMarket(self.Volume + self.Position)
elif self.Position > 0:
self.SellMarket(self.Position)
def CreateClone(self):
return macd_liquidity_tracker_strategy()