Parabolic SAR con Confirmación de MACD
Esta estrategia combina el indicador Parabolic SAR con la confirmación del MACD. Se abre una posición cuando el precio cruza el SAR en una dirección respaldada por el MACD, con el objetivo de capturar reversiones de tendencia.
Detalles
- Criterios de entrada: El precio cruza el SAR y la línea MACD está en el mismo lado que su línea de señal.
- Largo/Corto: Ambas direcciones.
- Criterios de salida: Cruce opuesto de precio/SAR o MACD.
- Stops: No.
- Valores predeterminados:
SarStart= 0.02mSarIncrement= 0.02mSarMax= 0.2mMacdFast= 12MacdSlow= 26MacdSignal= 9CandleType= TimeSpan.FromMinutes(5)
- Filtros:
- Categoría: Tendencia
- Dirección: Ambos
- Indicadores: Parabolic SAR, MACD
- Stops: No
- Complejidad: Intermedio
- Marco temporal: Intradía
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// EMA crossover with MACD confirmation.
/// </summary>
public class ParabolicSarMacdTrendZoneStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<DataType> _candleType;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ParabolicSarMacdTrendZoneStrategy()
{
_fastLength = Param(nameof(FastLength), 14).SetGreaterThanZero();
_slowLength = Param(nameof(SlowLength), 40).SetGreaterThanZero();
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastLength };
var slow = new ExponentialMovingAverage { Length = SlowLength };
var macd = new MovingAverageConvergenceDivergenceSignal();
var prevF = 0m;
var prevS = 0m;
var init = false;
var lastSignal = DateTimeOffset.MinValue;
var cooldown = TimeSpan.FromMinutes(360);
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(fast, slow, macd, (candle, fv, sv, macdVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!fv.IsFormed || !sv.IsFormed || !macdVal.IsFormed)
return;
var f = fv.ToDecimal();
var s = sv.ToDecimal();
var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
var macdLine = macdTyped.Macd;
var signalLine = macdTyped.Signal;
if (!init)
{
prevF = f;
prevS = s;
init = true;
return;
}
if (candle.OpenTime - lastSignal >= cooldown)
{
if (prevF <= prevS && f > s && macdLine > signalLine && Position <= 0)
{
BuyMarket();
lastSignal = candle.OpenTime;
}
else if (prevF >= prevS && f < s && macdLine < signalLine && Position >= 0)
{
SellMarket();
lastSignal = candle.OpenTime;
}
}
prevF = f;
prevS = s;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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, MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_macd_trend_zone_strategy(Strategy):
def __init__(self):
super(parabolic_sar_macd_trend_zone_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 14) \
.SetGreaterThanZero()
self._slow_length = self.Param("SlowLength", 40) \
.SetGreaterThanZero()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._last_signal_ticks = 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(parabolic_sar_macd_trend_zone_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._last_signal_ticks = 0
def OnStarted2(self, time):
super(parabolic_sar_macd_trend_zone_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._last_signal_ticks = 0
self._fast = ExponentialMovingAverage()
self._fast.Length = self._fast_length.Value
self._slow = ExponentialMovingAverage()
self._slow.Length = self._slow_length.Value
self._macd = MovingAverageConvergenceDivergenceSignal()
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(self._fast, self._slow, self._macd, self.OnProcess).Start()
def OnProcess(self, candle, f_val, s_val, macd_val):
if candle.State != CandleStates.Finished:
return
if not f_val.IsFormed or not s_val.IsFormed or not macd_val.IsFormed:
return
fv = float(f_val)
sv = float(s_val)
macd_line = macd_val.Macd
signal_line = macd_val.Signal
if macd_line is None or signal_line is None:
return
ml = float(macd_line)
sl = float(signal_line)
if not self._initialized:
self._prev_fast = fv
self._prev_slow = sv
self._initialized = True
return
cooldown_ticks = TimeSpan.FromMinutes(360).Ticks
current_ticks = candle.OpenTime.Ticks
if current_ticks - self._last_signal_ticks >= cooldown_ticks:
if self._prev_fast <= self._prev_slow and fv > sv and ml > sl and self.Position <= 0:
self.BuyMarket()
self._last_signal_ticks = current_ticks
elif self._prev_fast >= self._prev_slow and fv < sv and ml < sl and self.Position >= 0:
self.SellMarket()
self._last_signal_ticks = current_ticks
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return parabolic_sar_macd_trend_zone_strategy()