Ver no GitHub

M.A Break Strategy

This strategy replicates the behaviour of the MetaTrader "M.A break mt5 buy" and "M.A break mt5 sell" experts by combining both breakout directions into a single StockSharp implementation. It watches a configurable candle series, analyses several exponential moving averages, and confirms a strong impulse candle before opening trades. Positions are managed through fixed protective stops and targets measured in pips.

Trading logic

  1. Trend confirmation. Two EMA pairs (fast vs. slow) must be aligned in the trade direction on the completed candle. For longs both fast averages must be above their slow counterparts; for shorts the relationships are inverted. The previous candle open also has to be on the correct side of a dedicated EMA filter.
  2. Quiet-range measurement. A configurable number of earlier candles (excluding the most recent impulse candle) define the "quiet" period. Their highest range is compared against a minimum pip threshold.
  3. Impulse detection. The latest finished candle must expand by at least ImpulseStrength times the quiet range. Candle size limits in pips can be enforced to ignore unusually small or large moves.
  4. Candlestick template. The impulse candle must exhibit a specific wick structure:
    • Long trades: bullish body, upper wick not exceeding BullUpperWickPercent of the candle range, and lower wick at least BullLowerWickPercent of the range.
    • Short trades: bearish body, upper wick of at least BearUpperWickPercent, and lower wick not larger than BearLowerWickPercent of the range.
  5. Pullback condition. The impulse low (for longs) or high (for shorts) must test an additional EMA to guarantee that the breakout emerged from a pullback.
  6. Position control. Only one net position is allowed. The strategy closes the opposite side before entering a new trade and never opens a position against the trend filter.
  7. Exit management. Stop-loss and take-profit levels are calculated in pips from the entry price. Each finished candle checks whether the price has touched the protective levels and exits accordingly.

Parameters

Parameter Description
Candle Type Primary candle series used for all calculations.
Fast MA 1 / Slow MA 1 Periods of the first EMA pair that defines the primary trend.
Fast MA 2 / Slow MA 2 Periods of the secondary EMA pair used as an additional trend filter.
Open Filter MA EMA period that filters the previous candle open price.
Pullback MA EMA period whose value must be touched by the impulse wick.
Quiet Bars Number of historical candles used to measure the quiet market range.
Quiet Range (pips) Minimal pip range required across the quiet candles before considering a breakout.
Impulse Multiplier Minimal ratio between the impulse candle size and the quiet range.
Min / Max Candle Size (pips) Optional limits for the impulse candle range. Zero disables the respective bound.
Bull Upper Wick % / Bull Lower Wick % Shape filters for the bullish impulse candle, expressed as percentages of the candle range.
Bear Upper Wick % / Bear Lower Wick % Shape filters for the bearish impulse candle.
Volume Order size in lots used for both long and short entries.
Stop-Loss (pips) Distance to the protective stop measured from the entry price. Zero disables the stop.
Take-Profit (pips) Distance to the profit target. Zero disables the target.
Enable Long / Enable Short Toggle breakout trading in each direction independently.

Usage notes

  • Configure the candle series to match the timeframe used by the original expert (for example, M5 or H1). The default is a 5-minute timeframe.
  • The strategy stores only the recent history required for the quiet-range calculation, preventing unnecessary memory usage.
  • Entry prices are approximated by the impulse candle close, which matches the original MetaTrader behaviour of placing market orders at the beginning of the next bar.
  • Stop-loss and take-profit levels are evaluated on every completed candle. If both levels are hit within the same bar the stop has priority, mirroring the conservative handling used in the source experts.
  • Enabling only one direction reproduces the original "buy" or "sell" expert advisors, while leaving both toggles active allows symmetric breakout trading.

Conversion details

  • Both original MQ5 files were encoded in UTF-16 and built from blocks generated by the FXD engine. Each block has been translated into explicit C# logic.
  • EMA comparisons and candlestick templates follow the same shifts as the MetaTrader version (Shift = 1), meaning the strategy always evaluates fully closed candles.
  • Virtual stop logic and chart labels from the MQ5 scripts were intentionally omitted because they do not influence order placement.

Testing

Compile the solution through AlgoTrading.sln or run the strategy inside the StockSharp strategy tester. Adjust the instrument price step if the security metadata lacks this information; the implementation falls back to 0.0001 to emulate common FX pip values.

namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// MA Break strategy: EMA breakout with impulse candle confirmation.
/// Buys when close crosses above EMA with strong bullish candle body.
/// Sells when close crosses below EMA with strong bearish candle body.
/// </summary>
public class MaBreakStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _bodyRatio;

	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public decimal BodyRatio { get => _bodyRatio.Value; set => _bodyRatio.Value = value; }

	public MaBreakStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for breakout", "Indicators");
		_bodyRatio = Param(nameof(BodyRatio), 0.7m)
			.SetDisplay("Body Ratio", "Min body/range ratio for impulse", "Pattern");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0;
		_prevEma = 0;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0;
		_prevEma = 0;
		_hasPrev = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();
	}

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

		var range = candle.HighPrice - candle.LowPrice;
		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);

		if (_hasPrev && range > 0)
		{
			var isImpulse = body >= range * BodyRatio;

			if (_prevClose <= _prevEma && candle.ClosePrice > emaValue
				&& candle.ClosePrice > candle.OpenPrice && isImpulse && Position <= 0)
				BuyMarket();
			else if (_prevClose >= _prevEma && candle.ClosePrice < emaValue
				&& candle.ClosePrice < candle.OpenPrice && isImpulse && Position >= 0)
				SellMarket();
		}

		_prevClose = candle.ClosePrice;
		_prevEma = emaValue;
		_hasPrev = true;
	}
}