Стратегия следует за пробоями длительных максимумов и минимумов. Покупка происходит, когда цена закрытия превышает наибольший максимум за период, а продажа — когда цена закрытия опускается ниже наименьшего минимума. При противоположном сигнале позиция переворачивается, поэтому стратегия всегда находится в рынке.
Подход пытается захватывать устойчивые тренды, входя после значительного пробоя. Поскольку сделки совершаются только на ключевых экстремумах, стратегия фильтрует шум, но может получать крупные просадки во время боковых движений.
Детали
Критерии входа: пробой максимума/минимума предыдущих Period баров.
Длинные/короткие: оба направления, всегда в рынке.
Критерии выхода: противоположный пробой.
Стопы: нет.
Значения по умолчанию:
Period = 100
Volume = 1m
CandleType = TimeSpan.FromDays(1)
Фильтры:
Категория: Тренд
Направление: Оба
Индикаторы: 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>
/// Breakout strategy using Highest/Lowest channels.
/// </summary>
public class PzReversalTrendFollowingStrategy : Strategy
{
private readonly StrategyParam<int> _period;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHighest;
private decimal _prevLowest;
private bool _hasPrev;
public int Period { get => _period.Value; set => _period.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public PzReversalTrendFollowingStrategy()
{
_period = Param(nameof(Period), 30)
.SetGreaterThanZero()
.SetDisplay("Period", "Lookback period for breakout", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevHighest = 0;
_prevLowest = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = Period };
var lowest = new Lowest { Length = Period };
SubscribeCandles(CandleType)
.Bind(highest, lowest, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highestValue, decimal lowestValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevHighest = highestValue;
_prevLowest = lowestValue;
_hasPrev = true;
return;
}
if (candle.ClosePrice > _prevHighest && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (candle.ClosePrice < _prevLowest && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevHighest = highestValue;
_prevLowest = lowestValue;
}
}
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
from StockSharp.Algo.Strategies import Strategy
class pz_reversal_trend_following_strategy(Strategy):
def __init__(self):
super(pz_reversal_trend_following_strategy, self).__init__()
self._period = self.Param("Period", 30) .SetDisplay("Period", "Channel lookback period", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) .SetDisplay("Candle Type", "Candle type", "General")
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
@property
def period(self):
return self._period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(pz_reversal_trend_following_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(pz_reversal_trend_following_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self.period
lowest = Lowest()
lowest.Length = self.period
self.SubscribeCandles(self.candle_type).Bind(highest, lowest, self.process_candle).Start()
def process_candle(self, candle, high, low):
if candle.State != CandleStates.Finished:
return
hv = float(high)
lv = float(low)
if not self._has_prev:
self._prev_high = hv
self._prev_low = lv
self._has_prev = True
return
close = float(candle.ClosePrice)
if close > self._prev_high and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif close < self._prev_low and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_high = hv
self._prev_low = lv
def CreateClone(self):
return pz_reversal_trend_following_strategy()