View on GitHub

FT TIME BIGDOG Breakout Strategy

Overview

The FT TIME BIGDOG strategy is a London-session breakout system converted from the MetaTrader 4 expert advisor FT_TIME_BIGDOG.mq4 (directory MQL/9259). It measures the consolidation range that forms between the configured start and stop hours and then places stop orders above and below that range once the window closes. The StockSharp version keeps the original behaviour while exposing configurable parameters for breakout timing, order distance and risk management.

Trading Logic

  1. On every trading day the strategy records the highest high and lowest low of finished candles whose opening hour lies between StartHour and StopHour (inclusive).
  2. After the stop hour candle finishes, if the accumulated range is narrower than RangeLimitPoints, two pending stop orders become eligible:
    • A buy stop at the recorded high.
    • A sell stop at the recorded low.
  3. Orders are created only if the market price is at least OrderBufferPoints away from the entry level. Best bid/ask prices are used when available, otherwise the latest candle close is used.
  4. Each pending order includes a protective stop at the opposite side of the range and a take profit offset defined by TakeProfitPoints.
  5. When a position is opened, the opposite pending order is cancelled. The active position is monitored on finished candles: if price touches the stored stop loss or take profit level the position is closed at market.
  6. The cycle runs at most once per day; all state is reset at the start of the next trading day.

Parameters

Parameter Default Description
StartHour 14 Hour (0–23) marking the beginning of the accumulation window.
StopHour 16 Hour when pending orders become eligible. Must be greater than or equal to StartHour.
RangeLimitPoints 50 Maximum width of the session range in broker points (points × PointMultiplier). No orders are placed if the range is wider.
TakeProfitPoints 50 Take-profit distance applied to triggered positions, expressed in broker points.
OrderBufferPoints 20 Minimum distance required between the market price and a pending order. Prevents orders from being placed too close to current price.
PointMultiplier 1 Multiplier applied to the instrument point size. Set to 10 for five-digit forex symbols.
Volume 0.1 Order volume for both stop orders.
CandleType 1 hour Candle series used to measure the range and drive signal evaluation.

Risk and Trade Management

  • Stop loss for long trades equals the session low; stop loss for short trades equals the session high.
  • Take profit levels are calculated from the breakout price using TakeProfitPoints and the instrument point size.
  • All risk controls are executed on candle close events; intrabar excursions beyond stop levels may result in delayed exits.

Differences vs. Original Expert Advisor

  • The MetaTrader version operates on tick events while this port relies on finished candles and level 1 updates. Behaviour inside a candle may therefore differ slightly.
  • Point conversion uses Security.PriceStep multiplied by PointMultiplier. Verify this combination before running live.
  • Orders are placed only when StartHour <= StopHour. Cross-midnight windows are not supported in this port.

Usage Notes

  1. Assign the desired security and verify that level 1 data is available for accurate buffer checks.
  2. Configure trading hours according to the broker time zone.
  3. Run in simulation first to validate the point conversion and timing relative to your data feed.
  4. Reset or stop the strategy before manually altering pending orders to avoid conflicting state.

Files

  • CS/FtTimeBigdogStrategy.cs – core StockSharp implementation with detailed inline comments.
  • MQL/9259/FT_TIME_BIGDOG.mq4 – original MetaTrader source used for the conversion.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// FT Time Bigdog: Range breakout using N-bar high/low channel with ATR stops.
/// </summary>
public class FtTimeBigdogStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _channelLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _entryPrice;
	private decimal _highest;
	private decimal _lowest;
	private int _barCount;
	private readonly decimal[] _highs = new decimal[20];
	private readonly decimal[] _lows = new decimal[20];

	public FtTimeBigdogStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_channelLength = Param(nameof(ChannelLength), 20)
			.SetDisplay("Channel Length", "Lookback for high/low channel.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int ChannelLength
	{
		get => _channelLength.Value;
		set => _channelLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

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

		_entryPrice = 0;
		_barCount = 0;
		_highest = 0;
		_lowest = 0;
		Array.Clear(_highs, 0, _highs.Length);
		Array.Clear(_lows, 0, _lows.Length);
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_entryPrice = 0;
		_barCount = 0;
		_highest = 0;
		_lowest = 0;
		Array.Clear(_highs, 0, _highs.Length);
		Array.Clear(_lows, 0, _lows.Length);

		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(atr, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var len = Math.Min(ChannelLength, _highs.Length);
		var idx = _barCount % len;
		_highs[idx] = candle.HighPrice;
		_lows[idx] = candle.LowPrice;
		_barCount++;

		if (_barCount < len || atrVal <= 0)
			return;

		var high = decimal.MinValue;
		var low = decimal.MaxValue;
		for (var i = 0; i < len; i++)
		{
			if (_highs[i] > high) high = _highs[i];
			if (_lows[i] < low) low = _lows[i];
		}

		var prevHigh = _highest;
		var prevLow = _lowest;
		_highest = high;
		_lowest = low;

		if (prevHigh == 0 || prevLow == 0)
			return;

		var close = candle.ClosePrice;

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

		if (Position == 0)
		{
			if (close > prevHigh)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (close < prevLow)
			{
				_entryPrice = close;
				SellMarket();
			}
		}
	}
}