Стратегия Color Zerolag HLR
Стратегия представляет собой C# конверсию MQL5 эксперта Exp_ColorZerolagHLR. Она строит пять осцилляторов Hi-Lo Range (HLR) с разными периодами и весами, затем сглаживает их для получения быстрых и медленных линий тренда. Пересечения линий используются для генерации торговых сигналов.
Описание
- Вычисляет пять значений HLR по максимумам и минимумам за заданные периоды.
- Взвешивает и суммирует их для построения быстрой линии тренда.
- Применяет экспоненциальное сглаживание для получения медленной линии без задержки.
- Торгует при пересечении быстрой и медленной линий.
Параметры
Smoothing– коэффициент сглаживания EMA.Factor1..Factor5– веса компонент HLR.HlrPeriod1..HlrPeriod5– периоды расчёта HLR.BuyPosOpen/SellPosOpen– разрешение на открытие длинных/коротких позиций.BuyPosClose/SellPosClose– разрешение на закрытие позиций.CandleType– таймфрейм свечей.
Индикаторы
- Highest, Lowest (по пять штук).
Логика торговли
- Если ранее быстрая линия была выше медленной и теперь пересекла её вниз, открывается покупка и закрывается продажа.
- Если ранее быстрая линия была ниже медленной и теперь пересекла её вверх, открывается продажа и закрывается покупка.
Используйте стратегию в образовательных целях и адаптируйте параметры под собственные требования.
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>
/// Strategy based on weighted Hi-Lo Range oscillator with zero lag smoothing.
/// </summary>
public class ColorZerolagHlrStrategy : Strategy
{
private readonly StrategyParam<int> _smoothing;
private readonly StrategyParam<int> _hlrPeriod1;
private readonly StrategyParam<int> _hlrPeriod2;
private readonly StrategyParam<int> _hlrPeriod3;
private readonly StrategyParam<decimal> _factor1;
private readonly StrategyParam<decimal> _factor2;
private readonly StrategyParam<decimal> _factor3;
private readonly StrategyParam<DataType> _candleType;
private Highest _high1;
private Lowest _low1;
private Highest _high2;
private Lowest _low2;
private Highest _high3;
private Lowest _low3;
private decimal _smoothConst;
private decimal _prevFast;
private decimal _prevSlow;
private bool _isFirst;
public int Smoothing { get => _smoothing.Value; set => _smoothing.Value = value; }
public int HlrPeriod1 { get => _hlrPeriod1.Value; set => _hlrPeriod1.Value = value; }
public int HlrPeriod2 { get => _hlrPeriod2.Value; set => _hlrPeriod2.Value = value; }
public int HlrPeriod3 { get => _hlrPeriod3.Value; set => _hlrPeriod3.Value = value; }
public decimal Factor1 { get => _factor1.Value; set => _factor1.Value = value; }
public decimal Factor2 { get => _factor2.Value; set => _factor2.Value = value; }
public decimal Factor3 { get => _factor3.Value; set => _factor3.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorZerolagHlrStrategy()
{
_smoothing = Param(nameof(Smoothing), 15)
.SetGreaterThanZero()
.SetDisplay("Smoothing", "EMA smoothing factor", "Indicator");
_factor1 = Param(nameof(Factor1), 0.2m)
.SetDisplay("Factor 1", "Weight for HLR period 1", "Indicator");
_hlrPeriod1 = Param(nameof(HlrPeriod1), 8)
.SetGreaterThanZero()
.SetDisplay("HLR Period 1", "Lookback for HLR 1", "Indicator");
_factor2 = Param(nameof(Factor2), 0.35m)
.SetDisplay("Factor 2", "Weight for HLR period 2", "Indicator");
_hlrPeriod2 = Param(nameof(HlrPeriod2), 21)
.SetGreaterThanZero()
.SetDisplay("HLR Period 2", "Lookback for HLR 2", "Indicator");
_factor3 = Param(nameof(Factor3), 0.45m)
.SetDisplay("Factor 3", "Weight for HLR period 3", "Indicator");
_hlrPeriod3 = Param(nameof(HlrPeriod3), 34)
.SetGreaterThanZero()
.SetDisplay("HLR Period 3", "Lookback for HLR 3", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for calculations", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_isFirst = true;
_prevFast = default;
_prevSlow = default;
_smoothConst = default;
_high1 = default;
_low1 = default;
_high2 = default;
_low2 = default;
_high3 = default;
_low3 = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_smoothConst = (Smoothing - 1m) / Smoothing;
_isFirst = true;
_high1 = new Highest { Length = HlrPeriod1 };
_low1 = new Lowest { Length = HlrPeriod1 };
_high2 = new Highest { Length = HlrPeriod2 };
_low2 = new Lowest { Length = HlrPeriod2 };
_high3 = new Highest { Length = HlrPeriod3 };
_low3 = new Lowest { Length = HlrPeriod3 };
Indicators.Add(_high1);
Indicators.Add(_low1);
Indicators.Add(_high2);
Indicators.Add(_low2);
Indicators.Add(_high3);
Indicators.Add(_low3);
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var h1 = _high1.Process(candle);
var l1 = _low1.Process(candle);
var h2 = _high2.Process(candle);
var l2 = _low2.Process(candle);
var h3 = _high3.Process(candle);
var l3 = _low3.Process(candle);
if (!h1.IsFormed || !l1.IsFormed || !h2.IsFormed || !l2.IsFormed || !h3.IsFormed || !l3.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var high1 = h1.ToDecimal();
var low1 = l1.ToDecimal();
var high2 = h2.ToDecimal();
var low2 = l2.ToDecimal();
var high3 = h3.ToDecimal();
var low3 = l3.ToDecimal();
var mid = (candle.HighPrice + candle.LowPrice) / 2m;
var hlr1 = high1 - low1 == 0 ? 0m : 100m * (mid - low1) / (high1 - low1);
var hlr2 = high2 - low2 == 0 ? 0m : 100m * (mid - low2) / (high2 - low2);
var hlr3 = high3 - low3 == 0 ? 0m : 100m * (mid - low3) / (high3 - low3);
var fast = Factor1 * hlr1 + Factor2 * hlr2 + Factor3 * hlr3;
var slow = fast / Smoothing + _prevSlow * _smoothConst;
if (_isFirst)
{
_prevFast = fast;
_prevSlow = slow;
_isFirst = false;
return;
}
// Cross signals
if (_prevFast > _prevSlow && fast < slow && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (_prevFast < _prevSlow && fast > slow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 Highest, Lowest, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class color_zerolag_hlr_strategy(Strategy):
"""
Strategy based on weighted Hi-Lo Range oscillator with zero lag smoothing.
"""
def __init__(self):
super(color_zerolag_hlr_strategy, self).__init__()
self._smoothing = self.Param("Smoothing", 15) \
.SetDisplay("Smoothing", "EMA smoothing factor", "Indicator")
self._factor1 = self.Param("Factor1", 0.2) \
.SetDisplay("Factor 1", "Weight for HLR period 1", "Indicator")
self._hlr_period1 = self.Param("HlrPeriod1", 8) \
.SetDisplay("HLR Period 1", "Lookback for HLR 1", "Indicator")
self._factor2 = self.Param("Factor2", 0.35) \
.SetDisplay("Factor 2", "Weight for HLR period 2", "Indicator")
self._hlr_period2 = self.Param("HlrPeriod2", 21) \
.SetDisplay("HLR Period 2", "Lookback for HLR 2", "Indicator")
self._factor3 = self.Param("Factor3", 0.45) \
.SetDisplay("Factor 3", "Weight for HLR period 3", "Indicator")
self._hlr_period3 = self.Param("HlrPeriod3", 34) \
.SetDisplay("HLR Period 3", "Lookback for HLR 3", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe for calculations", "General")
self._smooth_const = 0.0
self._prev_fast = 0.0
self._prev_slow = 0.0
self._is_first = True
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_zerolag_hlr_strategy, self).OnReseted()
self._is_first = True
self._prev_fast = 0.0
self._prev_slow = 0.0
self._smooth_const = 0.0
def OnStarted2(self, time):
super(color_zerolag_hlr_strategy, self).OnStarted2(time)
smoothing = self._smoothing.Value
self._smooth_const = (smoothing - 1.0) / smoothing
self._is_first = True
self._high1 = Highest()
self._high1.Length = self._hlr_period1.Value
self._low1 = Lowest()
self._low1.Length = self._hlr_period1.Value
self._high2 = Highest()
self._high2.Length = self._hlr_period2.Value
self._low2 = Lowest()
self._low2.Length = self._hlr_period2.Value
self._high3 = Highest()
self._high3.Length = self._hlr_period3.Value
self._low3 = Lowest()
self._low3.Length = self._hlr_period3.Value
self.Indicators.Add(self._high1)
self.Indicators.Add(self._low1)
self.Indicators.Add(self._high2)
self.Indicators.Add(self._low2)
self.Indicators.Add(self._high3)
self.Indicators.Add(self._low3)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.on_process).Start()
def on_process(self, candle):
if candle.State != CandleStates.Finished:
return
cv1 = CandleIndicatorValue(self._high1, candle)
h1 = self._high1.Process(cv1)
cv2 = CandleIndicatorValue(self._low1, candle)
l1 = self._low1.Process(cv2)
cv3 = CandleIndicatorValue(self._high2, candle)
h2 = self._high2.Process(cv3)
cv4 = CandleIndicatorValue(self._low2, candle)
l2 = self._low2.Process(cv4)
cv5 = CandleIndicatorValue(self._high3, candle)
h3 = self._high3.Process(cv5)
cv6 = CandleIndicatorValue(self._low3, candle)
l3 = self._low3.Process(cv6)
if (not h1.IsFormed or not l1.IsFormed or not h2.IsFormed or
not l2.IsFormed or not h3.IsFormed or not l3.IsFormed):
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
high1 = float(h1)
low1 = float(l1)
high2 = float(h2)
low2 = float(l2)
high3 = float(h3)
low3 = float(l3)
mid = (float(candle.HighPrice) + float(candle.LowPrice)) / 2.0
hlr1 = 0.0 if (high1 - low1) == 0 else 100.0 * (mid - low1) / (high1 - low1)
hlr2 = 0.0 if (high2 - low2) == 0 else 100.0 * (mid - low2) / (high2 - low2)
hlr3 = 0.0 if (high3 - low3) == 0 else 100.0 * (mid - low3) / (high3 - low3)
fast = self._factor1.Value * hlr1 + self._factor2.Value * hlr2 + self._factor3.Value * hlr3
slow = fast / self._smoothing.Value + self._prev_slow * self._smooth_const
if self._is_first:
self._prev_fast = fast
self._prev_slow = slow
self._is_first = False
return
if self._prev_fast > self._prev_slow and fast < slow and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_fast < self._prev_slow and fast > slow and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return color_zerolag_hlr_strategy()