GitHub で見る

Five MA Multi-Timeframe Strategy

Overview

The Five MA Multi-Timeframe Strategy replicates the original MT4 "5matf" expert advisor using StockSharp's high-level API. The strategy analyzes five simple moving averages across three timeframes (primary, higher, and slowest) and combines the slope of each average with the Accelerator Oscillator to produce graded entry signals. When enough bullish or bearish evidence is present on all timeframes, the strategy opens or closes positions accordingly.

Indicators and Data

  • Simple Moving Averages (SMA): Periods 5, 8, 13, 21, and 34 on all three timeframes.
  • Accelerator Oscillator (AC): Applied on the primary and tertiary timeframes to assess momentum acceleration.
  • Timeframes: Default set to 15 minutes (signal), 60 minutes (confirmation), and 240 minutes (trend filter). All timeframes can be adjusted via parameters.

Signal Logic

  1. Each SMA compares its current value to the previous candle to determine an upward or downward slope.
  2. Accelerator Oscillator checks for bullish or bearish sequences using the latest four values.
  3. Slope counts and oscillator contributions are aggregated into percentage scores for every timeframe.
  4. When all three timeframes have bullish scores above 50%, a BUY signal is generated. Scores above 75% strengthen the signal.
  5. The same thresholds applied in the opposite direction generate SELL signals.
  6. Positions are closed when an opposite signal exceeds the configured close level. New trades only open when no position is active, mirroring the original expert advisor behavior.

Parameters

Name Default Description
CandleType 15-minute candles Primary timeframe used for trading signals.
HigherTimeframe1 60-minute candles First higher timeframe for confirmation.
HigherTimeframe2 240-minute candles Second higher timeframe for slow trend filter.
FirstPeriodFifthPeriod 5, 8, 13, 21, 34 SMA lengths applied to each timeframe.
OpenLevel 0 Minimum signal grade required to open a new position.
CloseLevel 1 Opposite signal grade required to close an existing position.

All parameters can be optimized or fine-tuned within StockSharp's strategy UI.

Usage Notes

  • The strategy uses market orders and does not issue simultaneous reversals; it always waits for a flat position before opening in the opposite direction.
  • Enable history data feeds for all selected timeframes to ensure synchronized calculations.
  • Consider tuning the SMA lengths or oscillator usage when applying the strategy to different markets or volatility regimes.

Conversion Notes

This implementation retains the core behavior of the MT4 "5matf" expert advisor while leveraging StockSharp's subscription and indicator binding system. The accelerator logic requires four completed candles before signals become active, just like the original script.

using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

public class FiveMaMultiTimeframeStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;
	private int _cooldownRemaining;

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

	public FiveMaMultiTimeframeStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 20).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 80).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
		_cooldownCandles = Param(nameof(CooldownCandles), 100).SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = default;
		_prevSlow = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
		_cooldownRemaining = 0;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevFast = fast;
			_prevSlow = slow;
			return;
		}

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevFast = fast;
		_prevSlow = slow;
	}
}