GitHub で見る

Glam Trader (Multi-timeframe Confirmation)

Overview

The strategy replicates the original MetaTrader "GLAM Trader" expert advisor by combining information from three timeframes:

  • A fast EMA(3) on the 15-minute chart captures short-term trend bias.
  • A Laguerre filter with gamma 0.7 applied to 5-minute candles measures whether price is trading above or below its smoothed path.
  • The Awesome Oscillator on hourly candles supplies a momentum check aligned with Bill Williams' definition.

Only when all three components agree does the strategy open a trade, aiming to filter out noise that would appear when any single timeframe is evaluated in isolation.

Trading Logic

  1. Data preparation
    • 15-minute candles feed an ExponentialMovingAverage with length EmaPeriod (default 3).
    • 5-minute candles feed a LaguerreFilter with smoothing LaguerreGamma.
    • 60-minute candles feed an AwesomeOscillator.
    • For each timeframe the latest finished candle close is stored to reproduce the original indicator-versus-price comparison.
  2. Entry conditions
    • Long: the EMA is above the current 15-minute close, Laguerre is above the latest 5-minute close, and Awesome Oscillator is above the latest hourly close.
    • Short: each of the three indicators must sit below its corresponding close.
  3. Risk management
    • Separate stop-loss and take-profit distances (expressed in instrument points) for long and short trades.
    • Trailing stops activate once price travels at least the specified trailing distance beyond the entry price. The stop is ratcheted in the trend direction without backing off.
    • All protective actions (take-profit, stop-loss, trailing stop) close the entire position with market orders, mirroring the MQL implementation.

Parameters

Name Description Default
TradeVolume Order size for new positions. 0.1
PrimaryCandleType Timeframe used for the EMA and main signal. 15-minute candles
LaguerreCandleType Timeframe analysed by the Laguerre filter. 5-minute candles
AwesomeCandleType Timeframe analysed by the Awesome Oscillator. 60-minute candles
EmaPeriod EMA length on the primary timeframe. 3
LaguerreGamma Gamma parameter for the Laguerre filter. 0.7
LongStopLossPoints Stop-loss distance for long trades, in points. 20
ShortStopLossPoints Stop-loss distance for short trades, in points. 20
LongTakeProfitPoints Take-profit distance for long trades, in points. 50
ShortTakeProfitPoints Take-profit distance for short trades, in points. 50
LongTrailingPoints Trailing distance for long trades, in points. 15
ShortTrailingPoints Trailing distance for short trades, in points. 15

Notes

  • The strategy subscribes to three independent candle streams and keeps only the most recent finished values, avoiding manual history buffers.
  • All comments and log messages remain in English for clarity, matching project conventions.
  • Adjust the point-based risk parameters according to the instrument's PriceStep so that protective levels reflect the broker's tick size.
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>
/// Glam Trader strategy - EMA crossover with momentum confirmation.
/// Buys when fast EMA crosses above slow EMA and momentum is positive.
/// Sells when fast EMA crosses below slow EMA and momentum is negative.
/// </summary>
public class GlamTraderSimpleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _momentumPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GlamTraderSimpleStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_momentumPeriod = Param(nameof(MomentumPeriod), 14)
			.SetDisplay("Momentum Period", "Momentum lookback", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var mom = new Momentum { Length = MomentumPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, mom, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		// Fast crosses above slow + positive momentum = buy
		if (_prevFast <= _prevSlow && fast > slow && mom > 0 && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Fast crosses below slow + negative momentum = sell
		else if (_prevFast >= _prevSlow && fast < slow && mom < 0 && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}