Estrategia Arpeet MACD
La estrategia Arpeet MACD opera cruces de MACD con un filtro de línea cero. Una señal larga aparece cuando la línea MACD cruza por encima de la línea de señal mientras permanece por debajo de cero. Una señal corta ocurre cuando el MACD cruza por debajo de la línea de señal por encima de cero.
Detalles
- Criterios de entrada:
- Largo: MACD cruza por encima de la señal y MACD < 0.
- Corto: MACD cruza por debajo de la señal y MACD > 0.
- Stops: Ninguno.
- Valores predeterminados:
FastLength= 12SlowLength= 26SignalLength= 9
- Filtros:
- Categoría: Indicador
- Dirección: Ambos
- Indicadores: MACD
- Stops: No
- Complejidad: Bajo
- Marco temporal: Cualquiera
- 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>
/// Arpeet MACD strategy - trades MACD crossovers with zero-line filter.
/// </summary>
public class ArpeetMacdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _signalLength;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevDiff;
private int _barIndex;
private int _lastTradeBar;
/// <summary>
/// Candle type for strategy calculation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Fast MA period.
/// </summary>
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
/// <summary>
/// Slow MA period.
/// </summary>
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
/// <summary>
/// Signal line period.
/// </summary>
public int SignalLength
{
get => _signalLength.Value;
set => _signalLength.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Initialize strategy parameters.
/// </summary>
public ArpeetMacdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_fastLength = Param(nameof(FastLength), 12)
.SetGreaterThanZero()
.SetDisplay("Fast MA", "Fast MA period", "Indicators");
_slowLength = Param(nameof(SlowLength), 26)
.SetGreaterThanZero()
.SetDisplay("Slow MA", "Slow MA period", "Indicators");
_signalLength = Param(nameof(SignalLength), 9)
.SetGreaterThanZero()
.SetDisplay("Signal Length", "Signal line period", "Indicators");
_cooldownBars = Param(nameof(CooldownBars), 350)
.SetDisplay("Cooldown Bars", "Bars between trades", "Trading");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevDiff = 0;
_barIndex = 0;
_lastTradeBar = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
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 value)
{
if (candle.State != CandleStates.Finished)
return;
_barIndex++;
var macdValue = (MovingAverageConvergenceDivergenceSignalValue)value;
if (macdValue.Macd is not decimal macd || macdValue.Signal is not decimal signal)
return;
var cooldownOk = _barIndex - _lastTradeBar > CooldownBars;
var diff = macd - signal;
var crossedUp = diff > 0 && _prevDiff <= 0;
var crossedDown = diff < 0 && _prevDiff >= 0;
if (crossedUp && macd < 0 && Position <= 0 && cooldownOk)
{
BuyMarket();
_lastTradeBar = _barIndex;
}
else if (crossedDown && macd > 0 && Position >= 0 && cooldownOk)
{
SellMarket();
_lastTradeBar = _barIndex;
}
_prevDiff = diff;
}
}
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 CandleStates
from StockSharp.Algo.Indicators import MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class arpeet_macd_strategy(Strategy):
"""
Arpeet MACD strategy - trades MACD crossovers with zero-line filter.
"""
def __init__(self):
super(arpeet_macd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", tf(1)) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._fast_length = self.Param("FastLength", 12) \
.SetGreaterThanZero() \
.SetDisplay("Fast MA", "Fast MA period", "Indicators")
self._slow_length = self.Param("SlowLength", 26) \
.SetGreaterThanZero() \
.SetDisplay("Slow MA", "Slow MA period", "Indicators")
self._signal_length = self.Param("SignalLength", 9) \
.SetGreaterThanZero() \
.SetDisplay("Signal Length", "Signal line period", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 350) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Trading")
self._prev_diff = 0.0
self._bar_index = 0
self._last_trade_bar = 0
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, v): self._candle_type.Value = v
@property
def FastLength(self): return self._fast_length.Value
@FastLength.setter
def FastLength(self, v): self._fast_length.Value = v
@property
def SlowLength(self): return self._slow_length.Value
@SlowLength.setter
def SlowLength(self, v): self._slow_length.Value = v
@property
def SignalLength(self): return self._signal_length.Value
@SignalLength.setter
def SignalLength(self, v): self._signal_length.Value = v
@property
def CooldownBars(self): return self._cooldown_bars.Value
@CooldownBars.setter
def CooldownBars(self, v): self._cooldown_bars.Value = v
def OnReseted(self):
super(arpeet_macd_strategy, self).OnReseted()
self._prev_diff = 0.0
self._bar_index = 0
self._last_trade_bar = 0
def OnStarted2(self, time):
super(arpeet_macd_strategy, self).OnStarted2(time)
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = self.FastLength
macd.Macd.LongMa.Length = self.SlowLength
macd.SignalMa.Length = self.SignalLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(macd, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, macd)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, value):
if candle.State != CandleStates.Finished:
return
self._bar_index += 1
macd_val = value.Macd
signal_val = value.Signal
if macd_val is None or signal_val is None:
return
macd_val = float(macd_val)
signal_val = float(signal_val)
cooldown_ok = self._bar_index - self._last_trade_bar > self.CooldownBars
diff = macd_val - signal_val
crossed_up = diff > 0 and self._prev_diff <= 0
crossed_down = diff < 0 and self._prev_diff >= 0
if crossed_up and macd_val < 0 and self.Position <= 0 and cooldown_ok:
self.BuyMarket()
self._last_trade_bar = self._bar_index
elif crossed_down and macd_val > 0 and self.Position >= 0 and cooldown_ok:
self.SellMarket()
self._last_trade_bar = self._bar_index
self._prev_diff = diff
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return arpeet_macd_strategy()