The ASCV BrainTrend Signal Strategy is a conversion of the MetaTrader expert that trades on BrainTrend1 indicator signals. The StockSharp version relies on high-level indicator bindings to combine the Average True Range (ATR), Stochastic Oscillator, and Jurik Moving Average (JMA) in order to detect momentum reversals and place trades with optional protective stops.
Core Idea
Calculate ATR to measure current volatility and define a dynamic confirmation band.
Smooth closing prices with a Jurik Moving Average and compare the current value with the value two bars back.
When the smoothed difference is larger than ATR / 2.3, update the state of the BrainTrend logic:
%K of the Stochastic Oscillator below 47 toggles the system into a potential short setup.
%K above 53 toggles the system into a potential long setup.
A signal from the previous bar is executed on the next completed candle. Signals can be flipped with the Reverse Signals parameter.
Stop-loss, take-profit, and trailing-stop levels are defined in pips (multiples of the instrument price step).
Entry and Exit Rules
Long entry: Previous bar issued a buy signal and the strategy is not already long. The order size equals Volume + abs(current position), so shorts are covered before opening the new long.
Short entry: Previous bar issued a sell signal and the strategy is not already short.
Stop-loss: Placed at entry price ± StopLossPips * price step. If the price trades beyond the stop level inside the next candle, the position is closed at market.
Take-profit: Optional take profit at entry price ± TakeProfitPips * price step.
Trailing-stop: Enabled when both TrailingStopPips and TrailingStepPips are greater than zero. After the price moves TrailingStopPips + TrailingStepPips in favor of the trade, the stop is trailed behind the move by TrailingStopPips.
Parameters
Parameter
Description
Default
AtrPeriod
ATR averaging period for volatility estimation.
14
StochasticPeriod
Base period for the Stochastic Oscillator.
12
JmaLength
Jurik Moving Average smoothing length.
7
StopLossPips
Stop-loss distance in pips (price steps).
15
TakeProfitPips
Take-profit distance in pips.
46
TrailingStopPips
Trailing stop distance in pips.
0 (disabled)
TrailingStepPips
Minimum favorable move required before trailing.
5
ReverseSignals
Invert buy/sell signals.
false
CandleType
Working timeframe, defaults to 15-minute candles.
15m
Notes
All indicator calculations are performed on finished candles to avoid mid-bar noise.
If the instrument does not supply MinPriceStep, a default step of 0.0001 is used when converting pip distances.
The strategy draws candles, the Stochastic oscillator, and the JMA on the chart for monitoring.
Trailing stops mirror the original MetaTrader logic: they only move in the direction of the trade and require both distance and step thresholds to be met.
Usage Tips
Adjust AtrPeriod and StochasticPeriod to fit the volatility of the instrument being traded.
Increase the pip-based risk parameters when trading assets with larger tick sizes (e.g., futures) to avoid immediate stop-outs.
Enable ReverseSignals to mirror the original Expert Advisor's reverse mode.
Combine with broker-side risk controls if real-money trading is involved.
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>
/// ASCV BrainTrend Signal strategy. Uses DEMA crossover (8/25).
/// </summary>
public class AscvBrainTrendSignalStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public AscvBrainTrendSignalStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 8).SetGreaterThanZero().SetDisplay("Fast DEMA", "Fast DEMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 25).SetGreaterThanZero().SetDisplay("Slow DEMA", "Slow DEMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new DoubleExponentialMovingAverage { Length = FastPeriod };
var slow = new DoubleExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import DoubleExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ascv_brain_trend_signal_strategy(Strategy):
def __init__(self):
super(ascv_brain_trend_signal_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 8) \
.SetDisplay("Fast DEMA", "Fast DEMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 25) \
.SetDisplay("Slow DEMA", "Slow DEMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(ascv_brain_trend_signal_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(ascv_brain_trend_signal_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = DoubleExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = DoubleExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return ascv_brain_trend_signal_strategy()