GitHub で見る

BrakeExp Channel Strategy

This strategy trades based on the BrakeExp indicator, which builds an exponential channel around price movements. The indicator switches between long and short regimes and generates buy or sell signals when price crosses the dynamic channel borders.

How It Works

  • The indicator maintains an exponential curve that follows price.
  • When the curve is below price (uptrend), the strategy looks for buy signals.
  • When the curve is above price (downtrend), the strategy looks for sell signals.
  • A crossing from one side to the other produces an entry signal in the new direction and closes the opposite position.

Parameters

  • Candle Type – timeframe of processed candles.
  • Volume – order volume used for market entries.
  • A, B – parameters defining the shape of the BrakeExp curve.
  • Buy Open / Sell Open – permission to open long or short positions.
  • Buy Close / Sell Close – permission to close short or long positions.

Notes

This implementation focuses on the core logic of the BrakeExp indicator and does not include stop-loss or take-profit management. Additional risk controls can be added if required.

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;

/// <summary>
/// Channel breakout strategy using EMA and price crossover.
/// </summary>
public class BrakeExpChannelStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	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 BrakeExpChannelStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

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

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

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		SubscribeCandles(CandleType)
			.Bind(ema, ProcessCandle)
			.Start();
	}

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevEma = emaVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevClose <= _prevEma && close > emaVal;
		var crossDown = _prevClose >= _prevEma && close < emaVal;

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

		_prevClose = close;
		_prevEma = emaVal;
	}
}