MetaTrader 4 expert advisor GLFX rewritten for StockSharp's high-level API. The port preserves the original idea of combining higher-timeframe confirmations with strict money-management gates while removing the massive collection of rarely-used filters that depended on external indicators.
Trading logic
The strategy works on a primary timeframe (default M15) and optionally builds a confirmation timeframe by walking up the classic MetaTrader ladder (M15 → M30 → H1 → H4 → D1 → W1 → MN).
A higher-timeframe RSI (default period 57) tracks whether momentum is rising or falling. A buy confirmation appears when RSI ticks up but remains below the configured overbought ceiling. A sell confirmation requires RSI to tick down while staying above the oversold floor.
A higher-timeframe simple moving average (default period 60) detects whether price is moving away from the mean. A bullish confirmation needs the MA to rise while remaining above the current close (price pulling back into an uptrend). A bearish confirmation mirrors this logic.
Each enabled filter contributes +1 for bullish or -1 for bearish sentiment. The total must reach the number of active filters to count as a valid signal. Counters remember how many consecutive full-strength signals appeared (SignalsRepeat). If the combined strength drops below the threshold and SignalsReset is enabled, the counters reset.
When the strategy is flat and the long/short entry switches allow it, the next completed counter triggers a market order with the configured Volume. Static stop-loss and take-profit levels are converted from pips into price offsets using the instrument's tick size.
If a position is already open, strong opposite signals can close it early (AllowLongExit / AllowShortExit). Otherwise, exits rely on the stop or target managed by StartProtection().
The port does not reproduce the original EA's optional Quantum, Twitter sentiment, open-bar correlation, set testing, or advanced money-management ladders. Those modules required additional custom indicators or broker state that do not exist in StockSharp.
Parameters
Parameter
Default
Description
CandleType
M15
Working timeframe for price evaluation.
HigherTimeFrameShift
1
Number of MT4 steps used to build the confirmation timeframe. 0 keeps the current timeframe.
UseRsiSignal
true
Enable higher-timeframe RSI confirmation.
RsiPeriod
57
Period of the confirmation RSI.
RsiUpperThreshold
65
Disable new longs once RSI exceeds this value.
RsiLowerThreshold
25
Disable new shorts once RSI drops below this value.
UseMaSignal
true
Enable higher-timeframe moving average confirmation.
MaPeriod
60
Period of the confirmation moving average.
SignalsRepeat
1
Number of consecutive full-strength signals required before opening a trade.
SignalsReset
true
Reset counters when the combined signal loses momentum.
TakeProfitPips
308
Take-profit distance expressed in pips. Set to 0 to disable.
StopLossPips
290
Stop-loss distance expressed in pips. Set to 0 to disable.
Volume
0.1
Order size used for new positions (lots).
AllowLongEntry / AllowShortEntry
true
Permission switches for opening long or short trades.
AllowLongExit / AllowShortExit
true
Allow automatic closing of existing exposure on opposite signals.
Usage notes
Choose instruments with a reliable tick size so the pip conversion remains accurate. Forex pairs with three or five decimals are automatically mapped to MetaTrader "points" by multiplying the price step by ten.
Set HigherTimeFrameShift to 0 if you want to run everything on the same timeframe. In this case the indicators are fed by the primary candle stream to avoid duplicate subscriptions.
If you need the legacy behaviour of keeping trades open regardless of opposite signals, disable the corresponding Allow*Exit flag.
Money-management scaling (MMC_* settings), trailing modules, and exotic exit filters from the original script were intentionally omitted. Implement them on top of this clean core if necessary.
Custom indicators (Quantum, TSI, file-based set loading)
None
The result is a compact, maintainable strategy that keeps the recognisable GLFX behaviour—waiting for trend confirmation on a slower chart and entering only after repeated agreement—while being easy to extend using the StockSharp framework.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// GLFX strategy: RSI + SMA confirmation for entry.
/// Requires consecutive confirmations before trading.
/// </summary>
public class GlfxStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiUpper;
private readonly StrategyParam<decimal> _rsiLower;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _signalsRepeat;
private decimal _prevRsi;
private decimal _prevMa;
private int _buyCount;
private int _sellCount;
private decimal _entryPrice;
public GlfxStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI period.", "Indicators");
_rsiUpper = Param(nameof(RsiUpper), 65m)
.SetDisplay("RSI Upper", "Overbought level.", "Indicators");
_rsiLower = Param(nameof(RsiLower), 35m)
.SetDisplay("RSI Lower", "Oversold level.", "Indicators");
_maPeriod = Param(nameof(MaPeriod), 60)
.SetDisplay("MA Period", "SMA period.", "Indicators");
_signalsRepeat = Param(nameof(SignalsRepeat), 2)
.SetDisplay("Signals Repeat", "Consecutive confirmations needed.", "Signals");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public decimal RsiUpper
{
get => _rsiUpper.Value;
set => _rsiUpper.Value = value;
}
public decimal RsiLower
{
get => _rsiLower.Value;
set => _rsiLower.Value = value;
}
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
public int SignalsRepeat
{
get => _signalsRepeat.Value;
set => _signalsRepeat.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0;
_prevMa = 0;
_buyCount = 0;
_sellCount = 0;
_entryPrice = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var ma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal maVal)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevRsi == 0 || _prevMa == 0)
{
_prevRsi = rsiVal;
_prevMa = maVal;
return;
}
var close = candle.ClosePrice;
// RSI signal: rising and below upper = bullish, falling and above lower = bearish
var rsiSignal = 0;
if (rsiVal > _prevRsi && rsiVal < RsiUpper)
rsiSignal = 1;
else if (rsiVal < _prevRsi && rsiVal > RsiLower)
rsiSignal = -1;
// MA signal: price above rising MA = bullish, below falling MA = bearish
var maSignal = 0;
if (maVal > _prevMa && close > maVal)
maSignal = 1;
else if (maVal < _prevMa && close < maVal)
maSignal = -1;
// Both signals must agree
if (rsiSignal > 0 && maSignal > 0)
{
_buyCount++;
_sellCount = 0;
}
else if (rsiSignal < 0 && maSignal < 0)
{
_sellCount++;
_buyCount = 0;
}
else
{
_buyCount = 0;
_sellCount = 0;
}
// Exit on opposite signal
if (Position > 0 && _sellCount >= SignalsRepeat)
{
SellMarket();
_entryPrice = 0;
_buyCount = 0;
_sellCount = 0;
}
else if (Position < 0 && _buyCount >= SignalsRepeat)
{
BuyMarket();
_entryPrice = 0;
_buyCount = 0;
_sellCount = 0;
}
// Entry after required confirmations
if (Position == 0)
{
if (_buyCount >= SignalsRepeat)
{
_entryPrice = close;
BuyMarket();
_buyCount = 0;
_sellCount = 0;
}
else if (_sellCount >= SignalsRepeat)
{
_entryPrice = close;
SellMarket();
_buyCount = 0;
_sellCount = 0;
}
}
_prevRsi = rsiVal;
_prevMa = maVal;
}
}