Three Line Break Strategy
Strategy that trades reversals detected by the Three Line Break indicator. The indicator compares the current high and low against the highest high and lowest low of the previous N completed candles. A breakout above the recent high during a downtrend signals a new uptrend and triggers a long entry; a breakdown below the recent low during an uptrend triggers a short entry. Positions are reversed on each signal.
Details
- Entry Criteria:
- Long:
Downtrendswitches toUptrend - Short:
Uptrendswitches toDowntrend
- Long:
- Long/Short: Both
- Exit Criteria: Opposite signal (position reversal)
- Stops: No
- Default Values:
LinesBreak= 3CandleType= TimeSpan.FromHours(12).TimeFrame()
- Filters:
- Category: Trend following
- Direction: Both
- Indicators: Highest, Lowest (Three Line Break logic)
- Stops: No
- Complexity: Basic
- Timeframe: Swing
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
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()