Reversión de Momentum MACD
La estrategia usa el histograma MACD para detectar reversiones de momentum. Vende en corto cuando la vela alcista crece pero el histograma MACD declina. Compra cuando la vela bajista crece pero el histograma MACD sube.
Detalles
- Criterios de entrada: Mayor cuerpo de vela con momentum MACD decreciente.
- Largo/Corto: Ambos.
- Criterios de salida: Señal opuesta.
- Stops: No.
- Valores predeterminados:
FastLength= 12SlowLength= 26SignalLength= 9CandleType= TimeSpan.FromMinutes(1)
- Filtros:
- Categoría: Momentum
- Dirección: Ambos
- Indicadores: MACD
- Stops: No
- Complejidad: Básico
- Marco temporal: Intradía (1m)
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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 momentum reversal strategy.
/// A bullish candle with a larger body than the previous candle while the MACD histogram declines goes short; a bearish candle with a
/// larger body than the previous candle while the histogram rises goes long. An opposite signal reverses the position.
/// </summary>
public class MacdMomentumReversalStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _signalLength;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevBody;
private decimal? _prevHist;
/// <summary>
/// Fast EMA length of MACD.
/// </summary>
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
/// <summary>
/// Slow EMA length of MACD.
/// </summary>
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
/// <summary>
/// Signal line length of MACD.
/// </summary>
public int SignalLength
{
get => _signalLength.Value;
set => _signalLength.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public MacdMomentumReversalStrategy()
{
_fastLength = Param(nameof(FastLength), 12)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "Fast EMA length of MACD", "MACD");
_slowLength = Param(nameof(SlowLength), 26)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "Slow EMA length of MACD", "MACD");
_signalLength = Param(nameof(SignalLength), 9)
.SetGreaterThanZero()
.SetDisplay("Signal Length", "Signal line length of MACD", "MACD");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).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();
_prevBody = null;
_prevHist = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevBody = null;
_prevHist = null;
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd =
{
ShortMa = { Length = FastLength },
LongMa = { Length = SlowLength },
},
SignalMa = { Length = SignalLength }
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(macd, ProcessCandle)
.Start();
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;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var prevBody = _prevBody;
_prevBody = body;
if (!macdValue.IsFormed || macdValue is not MovingAverageConvergenceDivergenceSignalValue { Macd: decimal macd, Signal: decimal signal })
return;
var hist = macd - signal;
var prevHist = _prevHist;
_prevHist = hist;
if (prevBody is not decimal pb || prevHist is not decimal ph)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var grows = body > pb;
if (grows && candle.ClosePrice > candle.OpenPrice && hist < ph && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (grows && candle.ClosePrice < candle.OpenPrice && hist > ph && Position <= 0)
BuyMarket(Volume + Math.Abs(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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class macd_momentum_reversal_strategy(Strategy):
"""
MACD momentum reversal strategy.
A bullish candle with a larger body than the previous candle while the MACD histogram declines goes short; a bearish candle with a
larger body than the previous candle while the histogram rises goes long. An opposite signal reverses the position.
"""
def __init__(self):
super(macd_momentum_reversal_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 12).SetGreaterThanZero().SetDisplay("Fast Length", "Fast EMA length of MACD", "MACD")
self._slow_length = self.Param("SlowLength", 26).SetGreaterThanZero().SetDisplay("Slow Length", "Slow EMA length of MACD", "MACD")
self._signal_length = self.Param("SignalLength", 9).SetGreaterThanZero().SetDisplay("Signal Length", "Signal line length of MACD", "MACD")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_body = None
self._prev_hist = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(macd_momentum_reversal_strategy, self).OnReseted()
self._prev_body = None
self._prev_hist = None
def OnStarted2(self, time):
super(macd_momentum_reversal_strategy, self).OnStarted2(time)
self._prev_body = None
self._prev_hist = None
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()
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
body = abs(candle.ClosePrice - candle.OpenPrice)
prev_body = self._prev_body
self._prev_body = body
if not macd_value.IsFormed or macd_value.Macd is None or macd_value.Signal is None:
return
hist = macd_value.Macd - macd_value.Signal
prev_hist = self._prev_hist
self._prev_hist = hist
if prev_body is None or prev_hist is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
grows = body > prev_body
if grows and candle.ClosePrice > candle.OpenPrice and hist < prev_hist and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif grows and candle.ClosePrice < candle.OpenPrice and hist > prev_hist and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return macd_momentum_reversal_strategy()