SR Breakout Strategy monitors support and resistance levels derived from Donchian Channels on two timeframes (H1 and H4). When a completed candle closes above resistance or below support, the strategy writes an informational log message. The implementation mirrors the alerting logic of the original MQL4 expert without placing any orders.
How It Works
Two candle subscriptions are created: one for the 1-hour timeframe and another for the 4-hour timeframe.
Each subscription is bound to its own DonchianChannels indicator with a configurable lookback length (default 26).
Once the indicator is formed, the strategy keeps track of the previous candle close for each timeframe.
On every finished candle, the current close is compared with the Donchian upper and lower bands:
If the close moves from below to above the upper band, a "cross above resistance" message is logged.
If the close moves from above to below the lower band, a "cross below support" message is logged.
The logic reproduces the notification behavior of the MQL4 script by using LogInfo entries as alerts.
Parameters
Name
Description
Default
LookbackLength
Number of candles used to compute Donchian support/resistance.
26
Hour1CandleType
Candle type for the one-hour subscription.
TimeFrame(1h)
Hour4CandleType
Candle type for the four-hour subscription.
TimeFrame(4h)
Signals
H1 breakout – logs when the one-hour candle close crosses above resistance or below support.
H4 breakout – logs when the four-hour candle close crosses above resistance or below support.
Notes
The strategy is intended for alerting only; it does not execute trades.
Both candle subscriptions must provide high and low data for the Donchian indicator to operate correctly.
Adjust the lookback length or candle types to match other trading sessions or instruments.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Support and resistance breakout strategy using Donchian channels.
/// Buys when price breaks above resistance (upper band), sells when breaks below support (lower band).
/// </summary>
public class SrBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _lookbackLength;
private readonly StrategyParam<DataType> _candleType;
private readonly Queue<decimal> _highHistory = new();
private readonly Queue<decimal> _lowHistory = new();
public int LookbackLength
{
get => _lookbackLength.Value;
set => _lookbackLength.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public SrBreakoutStrategy()
{
_lookbackLength = Param(nameof(LookbackLength), 20)
.SetGreaterThanZero()
.SetDisplay("Lookback", "Number of candles for Donchian channel", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis", "General");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_highHistory.Clear();
_lowHistory.Clear();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_highHistory.Count < LookbackLength)
{
EnqueueCandle(candle);
return;
}
var highs = _highHistory.ToArray();
var lows = _lowHistory.ToArray();
var upper = GetMax(highs);
var lower = GetMin(lows);
var close = candle.ClosePrice;
var range = upper - lower;
var volume = Volume;
if (volume <= 0)
volume = 1;
var breakoutPadding = range * 0.05m;
// Break above resistance
if (close > upper + breakoutPadding)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
// Break below support
else if (close < lower - breakoutPadding)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
EnqueueCandle(candle);
}
private void EnqueueCandle(ICandleMessage candle)
{
_highHistory.Enqueue(candle.HighPrice);
_lowHistory.Enqueue(candle.LowPrice);
if (_highHistory.Count > LookbackLength)
{
_highHistory.Dequeue();
_lowHistory.Dequeue();
}
}
private static decimal GetMax(IEnumerable<decimal> values)
{
var max = decimal.MinValue;
foreach (var value in values)
{
if (value > max)
max = value;
}
return max;
}
private static decimal GetMin(IEnumerable<decimal> values)
{
var min = decimal.MaxValue;
foreach (var value in values)
{
if (value < min)
min = value;
}
return min;
}
/// <inheritdoc />
protected override void OnReseted()
{
_highHistory.Clear();
_lowHistory.Clear();
base.OnReseted();
}
}