Auf GitHub ansehen

Early Bird Range Break Strategy

Overview

The Early Bird Range Break Strategy is a C# port of the MetaTrader "earlyBird3" expert advisor. It targets range breakouts that happen shortly after the European trading session opens. The algorithm observes an early-morning consolidation range, filters potential breakouts with a 14-period RSI, and enters up to three market orders in the direction of the breakout. Each order uses pre-defined take-profit levels, a shared stop-loss, and an optional trailing mechanism that is enabled only when volatility expands beyond its recent average.

Data requirements

  • A single time-frame candle stream (default: 5-minute candles) for the traded instrument.
  • The instrument must provide a valid PriceStep because all stop-loss and take-profit distances are defined in points.
  • Trading times are evaluated using the timestamps of incoming candles (server time of the data source).

Trading session

  1. Range construction – Between RangeStartHour and RangeEndHour the strategy records the highest high and lowest low.
  2. Trading window – After TradingStartHour:TradingStartMinute and before TradingEndHour the breakout logic becomes active.
  3. Forced closing – At ClosingHour all remaining positions are liquidated regardless of profit or loss.
  4. Weekdays only – Signals are processed from Monday to Friday.

Entry logic

  1. A long breakout level is set at range high + EntryBufferPoints, while a short breakout level is set at range low - EntryBufferPoints. The buffer is expressed in price points.
  2. The RSI filter must be greater than 50 for a long setup and less than or equal to 50 for a short setup.
  3. Only one breakout per direction is allowed each trading day. When triggered, three market orders (default volume 0.1) are submitted immediately.
  4. If an opposite position is already open and HedgeTrading is disabled, the new signal is ignored. When HedgeTrading is enabled the strategy first closes the existing position and then enters the new direction. This mirrors the intent of the original EA but uses position reversal because StockSharp accounts are netted.

Exit management

  1. Stop-loss – A shared stop-loss (StopLossPoints) is applied to the aggregate position. If price crosses the level the remaining size is closed immediately.
  2. Take-profit ladder – Three targets (TakeProfit1Points, TakeProfit2Points, TakeProfit3Points) close one position portion each. The remaining portion stays open until stopped, trailed, or closed by session end.
  3. Trailing stop – When only one portion is left, the current candle range must exceed ATR * TrailingRiskMultiplier. If the price has advanced by at least TrailingStopPoints, the stop-loss is stepped in the trade direction while preserving the initial stop distance.
  4. Session close – Any open exposure is fully flattened once the current time reaches ClosingHour.

Parameters

Parameter Description Default
AutoTrading Enables/disables order execution. true
HedgeTrading Allows position reversal on opposite signals (implemented as flat-and-reverse). true
OrderType 0 – both directions, 1 – long only, 2 – short only. 0
TradeVolume Volume per submitted market order. 0.1
StopLossPoints Stop-loss distance in price points. 60
TakeProfit1Points Take-profit distance for the first portion. 10
TakeProfit2Points Take-profit distance for the second portion. 20
TakeProfit3Points Take-profit distance for the third portion. 30
TrailingStopPoints Minimum favorable move before the trailing stop activates. 15
TrailingRiskMultiplier Multiplier applied to ATR when validating volatility expansion. 1.0
EntryBufferPoints Extra distance added to the breakout levels. 2
RangeStartHour Hour when the reference range begins. 3
RangeEndHour Hour when the reference range ends. 7
TradingStartHour Hour when breakout entries are allowed. 7
TradingStartMinute Minute when breakout entries are allowed. 15
TradingEndHour Hour after which no new entries are taken. 15
ClosingHour Hour when all trades are closed. 17
RsiPeriod RSI lookback used for filtering. 14
VolatilityPeriod ATR lookback for the volatility gate. 16
CandleType Candle series used for analysis (default 5-minute). TimeSpan.FromMinutes(5)

Implementation notes

  • The strategy subscribes to candles via the StockSharp high-level API and binds RSI and ATR indicators directly to the subscription.
  • Indicator values are consumed inside the ProcessCandle callback without calling GetValue or storing custom buffers, following project guidelines.
  • Only finished candles are processed; partial updates are ignored.
  • All price distances are converted from points to absolute prices using the instrument PriceStep. Make sure the security definition exposes the correct tick size.
  • The original expert advisor kept separate MQL orders for hedging. StockSharp uses net positions, so this port performs a close-and-reverse operation when HedgeTrading is enabled.

Usage tips

  • Align the candle time-frame with the trading venue used in the original EA (M5 to H1 in MetaTrader). Adjust RangeStartHour, RangeEndHour, and the trading window to reflect the local market schedule of your data feed.
  • When optimizing, focus on the breakout buffer, take-profit ladder, and volatility filter because they define the balance between false breakouts and missed moves.
  • Trailing is intentionally conservative—if you need tighter exits, consider reducing TrailingRiskMultiplier or StopLossPoints so that the trailing adjustments occur more frequently.
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Early Bird RangeBreak: EMA trend following with ATR stops.
/// </summary>
public class EarlyBirdRangeBreakStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevClose;
	private decimal _entryPrice;

	public EarlyBirdRangeBreakStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_emaLength = Param(nameof(EmaLength), 20)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevClose = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0; _entryPrice = 0;
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (_prevClose == 0 || atrVal <= 0) { _prevClose = close; return; }

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || close < emaVal) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || close > emaVal) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (close > emaVal && _prevClose <= emaVal) { _entryPrice = close; BuyMarket(); }
			else if (close < emaVal && _prevClose >= emaVal) { _entryPrice = close; SellMarket(); }
		}
		_prevClose = close;
	}
}