GitHub で見る

BreakOut15 Strategy

Overview

BreakOut15 is a 15-minute breakout strategy converted from the MetaTrader 4 expert advisor "BreakOut15.mq4". The strategy combines a moving-average crossover filter with breakout execution and multi-stage trailing protection. Orders are sent through the high-level StockSharp API and rely on finished candles only.

Core Logic

  1. Calculate two configurable moving averages (fast and slow) using the selected method, period, shift, and applied price.
  2. When the fast average crosses above the slow average, schedule a long breakout price at Close + BreakoutLevel * PriceStep. A bearish crossover schedules a short breakout at Close - BreakoutLevel * PriceStep.
  3. Pending breakout prices are cancelled if the crossover condition disappears, trading hours end, or a breakout in the opposite direction becomes active.
  4. Market entries are executed once the candle breaks through the pending level and equity and risk checks pass.
  5. Open positions are managed by stop-loss, take-profit, and one of three trailing-stop modes. Moving-average crossbacks force an immediate exit.
  6. Optional time filters prevent new trades outside the configured window and can liquidate positions late on Fridays.

Money Management

  • UseMoneyManagement / TradeSizePercent – enables risk-based sizing. The position size equals the integer part of floor(equity * percent / 10000) / 10, with a minimum of 1 lot.
  • FixedVolume – fallback size when money management is disabled or equity is unavailable.
  • MaxVolume – caps any computed volume.
  • MinimumEquity – blocks new trades when equity drops below the threshold.

Risk Management

  • StopLossPips / TakeProfitPips – classic protective offsets measured in pips (converted via the instrument price step).
  • UseTrailingStop – turns on dynamic stop handling once a position exists.
  • TrailingStopType
    • Immediate: trail by the original stop-loss distance right away.
    • Delayed: wait for TrailingStopPips of profit before trailing at that distance.
    • MultiLevel: lock in gains at three programmable milestones (Level1/2/3TriggerPips) and then trail by Level3TrailingPips.

Trading Schedule

  • UseTimeLimit, StartHour, StopHour – allow trading only inside the specified hour interval.
  • UseFridayClose, FridayCloseHour – optionally flatten all positions late on Friday.

Indicators and Data

  • Fast/Slow moving averages – choose between Simple, Exponential, Smoothed, Linear Weighted, or Least Squares methods.
  • Applied price modes – reproduce MT4 price sources (close, open, high, low, median, typical, weighted).
  • CandleType – defaults to 15-minute time-frame candles but can be changed if needed.

Additional Notes

  • The strategy automatically synchronises entry, stop, and target prices with the current average position price so trailing adjustments reflect actual fills.
  • All calculations depend on the instrument PriceStep; ensure it matches the traded market.
  • Tests should validate breakout triggering, trailing-stop transitions, and money-management rounding rules across bullish and bearish scenarios.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// BreakOut15 strategy - EMA crossover with breakout confirmation.
/// Buys when fast EMA crosses above slow EMA and price breaks above the fast EMA.
/// Sells on bearish crossover with price below fast EMA.
/// </summary>
public class BreakOut15Strategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BreakOut15Strategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 20)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fast > slow;
		var crossDown = _prevFast >= _prevSlow && fast < slow;

		if (crossUp && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}