Auf GitHub ansehen

Lbs V12 Strategy

Overview

The Lbs V12 strategy is a conversion of the MetaTrader expert advisor LBS_V12.mq4. It opens a pair of breakout stop orders around the previous 15-minute candle when the configured trigger hour begins. Both orders are offset by the current Average True Range (ATR) value in order to account for short-term volatility. The strategy attempts to catch the first impulse of the trading session and manages exits through virtual stop-loss, take-profit and trailing rules evaluated on every finished candle.

Trading Logic

  1. The strategy monitors finished candles of the selected timeframe (15 minutes by default).
  2. When a new candle with minute 00 appears at the configured TriggerHour, the previous candle becomes the reference range.
  3. If there are no open positions and no working orders for the current day, two stop orders are sent:
    • Buy stop above the reference high plus the instrument spread, one price step and the latest ATR value.
    • Sell stop below the reference low minus the same buffers.
  4. Protective price levels for each side are stored internally:
    • Stop-loss is placed beyond the opposite extreme of the reference candle.
    • Take-profit is calculated using the MetaTrader-style point distance.
    • A trailing stop activates once the trade moves further than the configured distance.
  5. When a long or short position is opened, the opposite stop order is cancelled. All protection is applied virtually: candle highs and lows are compared against the stored stop/take values and the position is closed with market orders when limits are reached.
  6. The strategy runs only once per day. All pending orders and internal state are cleared at the start of a new trading date.

Parameters

Name Description Default
Volume Trading volume in lots. 1
TriggerHour Hour of the day (terminal time zone) when the breakout orders should be sent. 9
TakeProfitPoints MetaTrader-style points between the entry price and the take-profit target. 100
TrailingStopPoints MetaTrader-style points used for the trailing stop after the trade moves into profit. 20
AtrPeriod Period of the ATR indicator that offsets the pending orders. 3
CandleType Candle type used for signal calculations. The default is 15-minute time frame candles. 15m timeframe

Risk Management

  • Exits are executed through market orders when the candle extremes touch the virtual stop-loss or take-profit levels.
  • The trailing stop increases (for longs) or decreases (for shorts) the protective level whenever the trade gains more than the configured distance.
  • Daily reset ensures that the strategy does not accumulate multiple positions or outdated pending orders.

Notes

  • Accurate bid/ask updates improve the spread compensation that is added to the breakout prices. If spread data is not available, the strategy falls back to one price step.
  • The conversion keeps the original MetaTrader defaults but adapts take-profit handling for short positions so that the target is always placed in the profitable direction.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// LBS V12 strategy - ATR channel breakout with EMA trend.
/// Buys when close breaks above EMA + ATR.
/// Sells when close breaks below EMA - ATR.
/// </summary>
public class LbsV12Strategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<decimal> _atrMultiplier;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private int _cooldownRemaining;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public decimal AtrMultiplier { get => _atrMultiplier.Value; set => _atrMultiplier.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public LbsV12Strategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetDisplay("EMA Period", "EMA lookback", "Indicators");
		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetDisplay("ATR Period", "ATR lookback", "Indicators");
		_atrMultiplier = Param(nameof(AtrMultiplier), 3m)
			.SetDisplay("ATR Multiplier", "Channel width multiplier", "Indicators");
		_cooldownCandles = Param(nameof(CooldownCandles), 100)
			.SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_cooldownRemaining = default;
	}

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

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var atr = new AverageTrueRange { Length = AtrPeriod };

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

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

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			return;
		}

		var close = candle.ClosePrice;
		var mult = AtrMultiplier;

		if (close > ema + atr * mult && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (close < ema - atr * mult && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
	}
}