Estratégia Neon de Ondas de Momentum
A estratégia Neon de Ondas de Momentum usa cruzamentos do histograma MACD para operar em ambas as direções. A estratégia vai comprado quando o histograma cruza acima do nível de entrada (zero por padrão) e vai vendido quando cruza abaixo. As posições são fechadas quando o histograma atinge os níveis de saída configurados.
Detalhes
- Critérios de entrada: O histograma MACD cruza o nível de entrada.
- Comprado/Vendido: Ambas as direções.
- Critérios de saída: O histograma cruza os níveis de saída de comprado/vendido.
- Stops: Não.
- Valores padrão:
FastLength= 12SlowLength= 26SignalLength= 20EntryLevel= 0LongExitLevel= 11ShortExitLevel= -9CandleType= 1 minute
- Filtros:
- Categoria: Momentum
- Direção: Ambos
- Indicadores: MACD
- Stops: Não
- Complexidade: Básico
- Período: Intradiário (1m)
- 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>
/// Neon Momentum Waves strategy based on MACD histogram levels.
/// The histogram (MACD line minus signal line) crossing above EntryLevel goes long and crossing below it goes short, reversing an
/// opposite position. A long closes once the histogram reaches LongExitLevel and a short once it reaches ShortExitLevel.
/// </summary>
public class NeonMomentumWavesStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _signalLength;
private readonly StrategyParam<decimal> _entryLevel;
private readonly StrategyParam<decimal> _longExitLevel;
private readonly StrategyParam<decimal> _shortExitLevel;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevHist;
/// <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 smoothing length.
/// </summary>
public int SignalLength
{
get => _signalLength.Value;
set => _signalLength.Value = value;
}
/// <summary>
/// Histogram entry level.
/// </summary>
public decimal EntryLevel
{
get => _entryLevel.Value;
set => _entryLevel.Value = value;
}
/// <summary>
/// Histogram level to exit long position.
/// </summary>
public decimal LongExitLevel
{
get => _longExitLevel.Value;
set => _longExitLevel.Value = value;
}
/// <summary>
/// Histogram level to exit short position.
/// </summary>
public decimal ShortExitLevel
{
get => _shortExitLevel.Value;
set => _shortExitLevel.Value = value;
}
/// <summary>
/// Candle type parameter.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="NeonMomentumWavesStrategy"/>.
/// </summary>
public NeonMomentumWavesStrategy()
{
_fastLength = Param(nameof(FastLength), 12)
.SetDisplay("Fast Length", "MACD fast EMA length", "MACD");
_slowLength = Param(nameof(SlowLength), 26)
.SetDisplay("Slow Length", "MACD slow EMA length", "MACD");
_signalLength = Param(nameof(SignalLength), 20)
.SetDisplay("Signal Length", "MACD signal smoothing", "MACD");
_entryLevel = Param(nameof(EntryLevel), 0m)
.SetDisplay("Entry Level", "Histogram entry threshold", "Parameters");
_longExitLevel = Param(nameof(LongExitLevel), 11m)
.SetDisplay("Long Exit Level", "Histogram level to exit longs", "Parameters");
_shortExitLevel = Param(nameof(ShortExitLevel), -9m)
.SetDisplay("Short Exit Level", "Histogram level to exit shorts", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHist = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_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);
DrawIndicator(area, macd);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!macdValue.IsFormed)
return;
var typed = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
if (typed.Macd is not decimal macdLine || typed.Signal is not decimal signal)
return;
var hist = macdLine - signal;
var prevHist = _prevHist;
_prevHist = hist;
if (prevHist is not decimal prev)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prev <= EntryLevel && hist > EntryLevel && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (prev >= EntryLevel && hist < EntryLevel && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (Position > 0 && hist >= LongExitLevel)
SellMarket(Position);
else if (Position < 0 && hist <= ShortExitLevel)
BuyMarket(-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 neon_momentum_waves_strategy(Strategy):
"""
Neon Momentum Waves strategy based on MACD histogram levels.
The histogram (MACD line minus signal line) crossing above EntryLevel goes long and crossing below it goes short, reversing an
opposite position. A long closes once the histogram reaches LongExitLevel and a short once it reaches ShortExitLevel.
"""
def __init__(self):
super(neon_momentum_waves_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 12).SetDisplay("Fast Length", "MACD fast EMA length", "MACD")
self._slow_length = self.Param("SlowLength", 26).SetDisplay("Slow Length", "MACD slow EMA length", "MACD")
self._signal_length = self.Param("SignalLength", 20).SetDisplay("Signal Length", "MACD signal smoothing", "MACD")
self._entry_level = self.Param("EntryLevel", 0.0).SetDisplay("Entry Level", "Histogram entry threshold", "Parameters")
self._long_exit_level = self.Param("LongExitLevel", 11.0).SetDisplay("Long Exit Level", "Histogram level to exit longs", "Parameters")
self._short_exit_level = self.Param("ShortExitLevel", -9.0).SetDisplay("Short Exit Level", "Histogram level to exit shorts", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles", "General")
self._prev_hist = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(neon_momentum_waves_strategy, self).OnReseted()
self._prev_hist = None
def OnStarted2(self, time):
super(neon_momentum_waves_strategy, self).OnStarted2(time)
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.DrawIndicator(area, macd)
self.DrawOwnTrades(area)
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
hist = float(macd_line) - float(signal_line)
prev = self._prev_hist
self._prev_hist = hist
if prev is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
entry = float(self._entry_level.Value)
if prev <= entry and hist > entry and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif prev >= entry and hist < entry and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and hist >= float(self._long_exit_level.Value):
self.SellMarket(self.Position)
elif self.Position < 0 and hist <= float(self._short_exit_level.Value):
self.BuyMarket(-self.Position)
def CreateClone(self):
return neon_momentum_waves_strategy()