Auf GitHub ansehen

Three Breaky Strategy

The Three Breaky Strategy is a full conversion of the MetaTrader 4 expert advisor ThreeBreaky_v1.mq4. The StockSharp version keeps the original trio of breakout subsystems, translates their candle-based logic to the high-level API, and adds clear position bookkeeping for each module. The strategy works on a single configurable timeframe and can enable or disable any subsystem without affecting the others.

Trading Modules

  1. System 1 – ATR Expansion Breakout

    • Uses the previous candle only.
    • Goes long when the previous candle is bullish and its high–low range exceeds four times the 72-period average true range.
    • Goes short when the previous candle is bearish and the same range condition is satisfied.
  2. System 2 – Ichimoku Cloud Flip

    • Observes the cloud boundaries (Senkou Span A and Senkou Span B) with default periods 9/26/52.
    • A long signal triggers when two candles ago closed below both spans and the latest closed above both spans (a bullish flip through the cloud).
    • A short signal triggers when two candles ago closed above both spans and the latest closed below both spans.
  3. System 3 – Exceptional Body Breakout

    • Tracks the body size of the previous 20 completed candles.
    • A long setup requires the previous candle to be bullish and its body to be more than three times the maximum body observed in that 20-candle history.
    • A short setup mirrors the condition for bearish bodies.

Every subsystem trades a dedicated virtual position. Order timestamps are stored to ensure a module can open at most one trade per candle, just like the original buyTag and sellTag logic.

Exit Logic

  • Parabolic SAR Reversal: All open positions share a Parabolic SAR (0.005/0.2) exit. When price crosses the SAR between the previous two candles, the affected position is closed.
  • Risk Management: Optional stop-loss and take-profit distances (in pips) are evaluated on each completed candle. If the configured thresholds are breached, the relevant position is closed immediately.

Indicators Used

  • Average True Range (period 72) for the average volatility baseline.
  • Ichimoku Kinko Hyo (9, 26, 52) for the cloud flip filter.
  • Parabolic SAR (0.005 acceleration, 0.2 maximum) for exits and trailing logic.
  • Rolling body-size buffer (20 candles) to reproduce the MQL maximum body comparison.

Parameters

Parameter Description
UseSystem1 Enables the ATR expansion breakout module.
UseSystem2 Enables the Ichimoku cloud flip module.
UseSystem3 Enables the large body breakout module.
OrderVolume Volume used for every market order generated by any module.
StopLossPips Protective stop distance in pips. Set to zero to disable.
TakeProfitPips Take-profit distance in pips. Set to zero to disable.
CandleType Timeframe for the working candles (defaults to 1 hour).

Workflow Summary

  1. Subscribe to the configured candle series and process only finished candles.
  2. Update the ATR, Ichimoku, and Parabolic SAR indicators together with the rolling body history.
  3. Close positions that hit stops, targets, or Parabolic SAR reversals.
  4. If trading is allowed, evaluate every subsystem independently and issue market orders when all the respective conditions are met.
  5. Store the latest indicator outputs so that the next candle can access the same historical values as in the original MQL implementation.

Notes

  • The strategy assumes a pip value based on the security price step; five-digit and three-digit FX quotes are normalized to four and two decimal pip sizes respectively.
  • Subsystems can run simultaneously. Each keeps its own entry price, position direction, and last signal timestamps to mirror the MagicNumber+N separation from the source EA.
  • The StockSharp implementation retains the "once per bar" execution pattern by using candle open times to block duplicate orders within a single bar.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

public class ThreeBreakyStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public ThreeBreakyStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 15).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 60).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}