Стратегия Three Line Break
Стратегия торгует развороты, определяемые индикатором Three Line Break. Индикатор сравнивает текущие максимум и минимум с наивысшим максимумом и наинизшим минимумом предыдущих N завершенных свечей. Пробой недавнего максимума в нисходящем тренде сигнализирует о смене тренда вверх и открывает длинную позицию; пробой недавнего минимума в восходящем тренде открывает короткую позицию. Позиции переворачиваются при каждом сигнале.
Детали
- Критерии входа:
- Long: переход
Downtrend→Uptrend - Short: переход
Uptrend→Downtrend
- Long: переход
- Long/Short: обе стороны
- Критерии выхода: противоположный сигнал (переворот позиции)
- Стопы: нет
- Значения по умолчанию:
LinesBreak= 3CandleType= TimeSpan.FromHours(12).TimeFrame()
- Фильтры:
- Категория: следование тренду
- Направление: обе
- Индикаторы: Highest, Lowest (логика Three Line Break)
- Стопы: нет
- Сложность: базовая
- Таймфрейм: среднесрочный
- Сезонность: нет
- Нейросети: нет
- Дивергенция: нет
- Уровень риска: средний
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on the Three Line Break pattern.
/// Detects trend reversals when price breaks above/below recent N-bar high/low.
/// </summary>
public class ThreeLineBreakStrategy : Strategy
{
private readonly StrategyParam<int> _linesBreak;
private readonly StrategyParam<DataType> _candleType;
private Lowest _lowest;
private decimal _prevHigh;
private decimal _prevLow;
private bool _trendUp = true;
public int LinesBreak { get => _linesBreak.Value; set => _linesBreak.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ThreeLineBreakStrategy()
{
_linesBreak = Param(nameof(LinesBreak), 3)
.SetGreaterThanZero()
.SetDisplay("Lines Break", "Number of lines for trend detection", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_lowest = null;
_prevHigh = 0;
_prevLow = 0;
_trendUp = true;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = LinesBreak };
_lowest = new Lowest { Length = LinesBreak };
Indicators.Add(_lowest);
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(highest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, highest);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue highValue)
{
if (candle.State != CandleStates.Finished)
return;
var lowValue = _lowest.Process(highValue);
if (!highValue.IsFormed || !lowValue.IsFormed)
return;
var currentHigh = highValue.GetValue<decimal>();
var currentLow = lowValue.GetValue<decimal>();
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevHigh = currentHigh;
_prevLow = currentLow;
return;
}
if (_prevHigh == 0 || _prevLow == 0)
{
_prevHigh = currentHigh;
_prevLow = currentLow;
return;
}
var trendUp = _trendUp;
if (trendUp && candle.LowPrice < _prevLow)
trendUp = false;
else if (!trendUp && candle.HighPrice > _prevHigh)
trendUp = true;
if (trendUp != _trendUp)
{
if (trendUp && Position <= 0)
BuyMarket();
else if (!trendUp && Position >= 0)
SellMarket();
}
_trendUp = trendUp;
_prevHigh = currentHigh;
_prevLow = currentLow;
}
}
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 three_line_break_strategy(Strategy):
def __init__(self):
super(three_line_break_strategy, self).__init__()
self._lines_break = self.Param("LinesBreak", 3) \
.SetDisplay("Lines Break", "Number of lines for trend detection", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for analysis", "General")
self._lowest = None
self._prev_high = 0.0
self._prev_low = 0.0
self._trend_up = True
@property
def lines_break(self):
return self._lines_break.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(three_line_break_strategy, self).OnReseted()
self._lowest = None
self._prev_high = 0.0
self._prev_low = 0.0
self._trend_up = True
def OnStarted2(self, time):
super(three_line_break_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self.lines_break
self._lowest = Lowest()
self._lowest.Length = self.lines_break
self.Indicators.Add(self._lowest)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(highest, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, highest)
self.DrawOwnTrades(area)
def process_candle(self, candle, high_value):
if candle.State != CandleStates.Finished:
return
low_value = self._lowest.Process(high_value)
if not high_value.IsFormed or not low_value.IsFormed:
return
current_high = float(high_value)
current_low = float(low_value)
if self._prev_high == 0.0 or self._prev_low == 0.0:
self._prev_high = current_high
self._prev_low = current_low
return
trend_up = self._trend_up
if trend_up and float(candle.LowPrice) < self._prev_low:
trend_up = False
elif not trend_up and float(candle.HighPrice) > self._prev_high:
trend_up = True
if trend_up != self._trend_up:
if trend_up and self.Position <= 0:
self.BuyMarket()
elif not trend_up and self.Position >= 0:
self.SellMarket()
self._trend_up = trend_up
self._prev_high = current_high
self._prev_low = current_low
def CreateClone(self):
return three_line_break_strategy()