Daily breakout system for GBPUSD that combines an EMA calculated on highs, RSI filters, MACD momentum confirmation and ATR-based risk management. The script reproduces the four-layer profit taking and breakeven behaviour of the original MetaTrader version.
Key Facts
Market: GBP/USD spot or CFD
Timeframe: Daily candles (configurable)
Direction: Long and short
Position Style: Multi-target scaling with shared stop loss
Instruments Used: EMA (High), RSI, MACD main line, ATR
Indicator Setup
EMA on High prices – default length 6, approximates the dynamic breakout level.
RSI – default length 10, defines overbought/oversold corridors used as momentum filters.
MACD main line – fast 5, slow 21, signal 14. Only the main line is used to measure momentum slope.
ATR – length 28, delivers volatility-dependent stops and targets.
Entry Logic
Long Entries
The previous daily bar opens below the EMA (High) and closes above it (cross-over confirmation).
RSI stays between 60 and 80 – prevents trades during weak momentum and avoids overextended rallies.
MACD main line satisfies one of two momentum checks:
The value two bars ago is negative (indicating the trend recently turned positive), or
The relative reduction in absolute MACD between the last two bars exceeds the configurable MacdDiffBuy threshold (default 0.5).
If all conditions hold, four equal market buy orders are placed (default 0.1 lots each). Any existing short exposure is flattened before the new batch is sent.
Short Entries
The bar opens above the EMA (High) and closes below it.
RSI is between 25 and 39 – mirrors the long side thresholds.
MACD two bars ago is positive or the relative change in absolute MACD between the last two bars is above MacdDiffSell (default 0.15).
On confirmation, the strategy flattens existing longs, then submits four equal market sells.
Trade Management
Initial Stop: Shared ATR stop calculated from the entry close. Longs use entry - ATR * StopLossMultiplier (default 1.6). Shorts use entry + ATR * StopLossMultiplier.
Profit Targets: Four incremental ATR-based levels per direction: 1.0, 1.5, 2.0, and 2.5 ATR multiples scaled by the TakeProfitMultiplier parameter (default 1). Each level closes one quarter of the original position via a market order when price trades through the level.
Breakeven Behaviour: After each partial exit the protective stop for the remaining position is moved to the most recent target price. This mimics the original EA which modifies stop losses to the filled take-profit price whenever a TP deal occurs.
Stop Handling: If price touches the protective level intrabar (using candle high/low), the remaining position is closed immediately at market.
Risk Control Notes
The strategy does not pyramid beyond the four-entry batch. A new signal is ignored while exposure remains in the same direction.
ATR must be positive; signals are skipped if the volatility indicator has not formed yet.
Parameter changes at runtime affect future orders only; per-order volume is captured at entry for correct scaling on exits.
Parameters
Name
Description
Default
OrderVolume
Volume per individual market order in the batch
0.1
EmaPeriod
EMA length applied to candle highs
6
RsiPeriod
RSI averaging period
10
AtrPeriod
ATR averaging period
28
StopLossMultiplier
ATR multiple for the protective stop
1.6
TakeProfitMultiplier
Base ATR multiple for profit targets
1.0
MacdFastPeriod
MACD fast EMA length
5
MacdSlowPeriod
MACD slow EMA length
21
MacdSignalPeriod
MACD signal EMA length
14
MacdDiffBuyThreshold
Minimum MACD slope improvement for long trades
0.5
MacdDiffSellThreshold
Minimum MACD slope improvement for short trades
0.15
RsiUpperLimit
Maximum RSI allowed before a long entry
80
RsiUpperLevel
Minimum RSI required for a long entry
60
RsiLowerLevel
Maximum RSI allowed for a short entry
39
RsiLowerLimit
Minimum RSI required before shorts
25
CandleType
Timeframe used for candle subscription
1 Day
Deployment Tips
Optimise RSI and MACD thresholds together; loosening RSI corridors without adjusting the MACD acceleration filters can create whipsaws.
Because partial exits rely on candle extremes, accurate data for high/low values is important for realistic backtests.
Always run with sufficient capital to handle four simultaneous orders per signal.
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>
/// Alexav D1 Profit GBPUSD strategy (simplified). Uses EMA crossover with RSI
/// filter for breakout entries with ATR-based stop/take management.
/// </summary>
public class AlexavD1ProfitGbpUsdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaFastLength;
private readonly StrategyParam<int> _emaSlowLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<decimal> _rsiUpperLevel;
private readonly StrategyParam<decimal> _rsiLowerLevel;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaFastLength
{
get => _emaFastLength.Value;
set => _emaFastLength.Value = value;
}
public int EmaSlowLength
{
get => _emaSlowLength.Value;
set => _emaSlowLength.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public decimal RsiUpperLevel
{
get => _rsiUpperLevel.Value;
set => _rsiUpperLevel.Value = value;
}
public decimal RsiLowerLevel
{
get => _rsiLowerLevel.Value;
set => _rsiLowerLevel.Value = value;
}
public AlexavD1ProfitGbpUsdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_emaFastLength = Param(nameof(EmaFastLength), 6)
.SetGreaterThanZero()
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators");
_emaSlowLength = Param(nameof(EmaSlowLength), 21)
.SetGreaterThanZero()
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators");
_rsiLength = Param(nameof(RsiLength), 10)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
_rsiUpperLevel = Param(nameof(RsiUpperLevel), 65m)
.SetDisplay("RSI Upper", "Max RSI for buy", "Filters");
_rsiLowerLevel = Param(nameof(RsiLowerLevel), 35m)
.SetDisplay("RSI Lower", "Min RSI for sell", "Filters");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaFast = new ExponentialMovingAverage { Length = EmaFastLength };
var emaSlow = new ExponentialMovingAverage { Length = EmaSlowLength };
decimal prevFast = 0, prevSlow = 0;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaFast, emaSlow, (ICandleMessage candle, decimal fastVal, decimal slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevFast = fastVal;
prevSlow = slowVal;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastVal;
prevSlow = slowVal;
return;
}
var close = candle.ClosePrice;
// EMA fast crosses above slow - buy signal
var bullishCross = prevFast <= prevSlow && fastVal > slowVal;
// EMA fast crosses below slow - sell signal
var bearishCross = prevFast >= prevSlow && fastVal < slowVal;
if (bullishCross && Position <= 0)
BuyMarket();
else if (bearishCross && Position >= 0)
SellMarket();
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
DrawOwnTrades(area);
}
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class alexav_d1_profit_gbp_usd_strategy(Strategy):
def __init__(self):
super(alexav_d1_profit_gbp_usd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candles", "General")
self._ema_fast_length = self.Param("EmaFastLength", 6) \
.SetDisplay("EMA Fast", "Fast EMA period", "Indicators")
self._ema_slow_length = self.Param("EmaSlowLength", 21) \
.SetDisplay("EMA Slow", "Slow EMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaFastLength(self):
return self._ema_fast_length.Value
@property
def EmaSlowLength(self):
return self._ema_slow_length.Value
def OnReseted(self):
super(alexav_d1_profit_gbp_usd_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(alexav_d1_profit_gbp_usd_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
ema_fast = ExponentialMovingAverage()
ema_fast.Length = self.EmaFastLength
ema_slow = ExponentialMovingAverage()
ema_slow.Length = self.EmaSlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema_fast, ema_slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_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 not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return alexav_d1_profit_gbp_usd_strategy()