Auf GitHub ansehen

Starter-Strategie

Die Starter-Strategie ist eine Konvertierung des MetaTrader 5-Experten "Starter (barabashkakvn's edition)". Das System wartet darauf, dass der Commodity Channel Index (CCI) aus extremem überverkauftem oder überkauftem Bereich zurückprallt, und bestätigt die Bewegung mit der Steigung eines langfristigen gleitenden Durchschnitts. Wenn der Momentum mit dem Trendfilter übereinstimmt, öffnet die Strategie eine einzelne Marktposition, deren Größe durch einen konfigurierbaren Risikoanteil des Portfolios bestimmt wird. Schutz-Stops und ein optionaler Trailing-Mechanismus reproduzieren die Geldmanagement-Regeln des Original-Experten.

Handelslogik

  • Trendfilter — ein konfigurierbarer gleitender Durchschnitt (MA) muss schneller als MaDelta steigen, um Long-Trades zu erlauben, und schneller als MaDelta fallen, um Short-Trades zu erlauben. Die Strategie unterstützt dieselben Glättungsmethoden wie die MQL-Version (einfach, exponentiell, geglättet, linear gewichtet).
  • CCI-Bestätigung — der Commodity Channel Index muss von unten wieder über -CciLevel kreuzen, um Long-Einträge auszulösen, und von oben unter CciLevel kreuzen, um Shorts auszulösen. Der Indikator wird nur auf abgeschlossenen Kerzen ausgewertet und spiegelt die ursprüngliche bar-by-bar-Verarbeitung wider.
  • Einzelpositionsmodell — der Algorithmus hält maximal eine offene Position. Neue Signale werden ignoriert, bis der aktuelle Trade geschlossen ist, entsprechend der MetaTrader-Logik, die nach Magic Number und Symbol filtert.

Einstiegsregeln

  1. Auf den Kerzenschluss warten.
  2. Die neuesten und vorherigen Werte des gleitenden Durchschnitts bei den konfigurierten Verschiebungen berechnen.
  3. Die aktuellen und vorherigen CCI-Lesewerte berechnen.
  4. Long gehen, wenn:
    • Die Steigung des gleitenden Durchschnitts MaDelta übersteigt (aktueller MA minus vorheriger MA).
    • Der aktuelle CCI-Wert größer als der vorherige ist.
    • Der CCI durch -CciLevel nach oben kreuzt (vorheriger unter dem Schwellenwert, aktueller darüber).
  5. Short gehen, wenn:
    • Die Steigung des gleitenden Durchschnitts unter -MaDelta liegt.
    • Der aktuelle CCI-Wert kleiner als der vorherige ist.
    • Der CCI durch CciLevel nach unten kreuzt (vorheriger über dem Schwellenwert, aktueller darunter).

Ausstiegsregeln

  • Initialer Stop-Loss — wenn StopLossPips größer als null ist, wird der ausgeführte Einstiegspreis um StopLossPips * PriceStep verschoben, um einen anfänglichen Schutz-Stop zu berechnen.
  • Trailing Stop — wenn sowohl TrailingStopPips als auch TrailingStepPips positiv sind, wird der Stop vorgerückt, sobald der Preis sich um mindestens den konfigurierten Schritt verbessert. Long-Trades bewegen den Stop auf Close - TrailingStop, Shorts auf Close + TrailingStop.
  • Manuelle Schließung — wenn der Preis das Stop-Niveau innerhalb der Kerzenspanne berührt, schließt die Strategie die Position mit einer Marktorder und setzt den Schutzzustand zurück.

Risikomanagement

  • Positionsgrößenbestimmung — das Basisvolumen beträgt Portfolio.CurrentValue * MaximumRisk / price. Wenn der Broker oder das Backend einen ungültigen Eigenkapitalwert meldet, greift die Strategie auf die manuelle Eigenschaft Volume zurück (Standard 1).
  • Verluststrähnen-Reduzierung — nach zwei oder mehr aufeinanderfolgenden Verlust-Trades wird das Volumen um volume * losses / DecreaseFactor reduziert, was die ursprüngliche DecreaseFactor-Regel nachahmt. Jeder profitable Trade setzt den Verlust-Zähler zurück.

Parameter

Parameter Standard Beschreibung
MaximumRisk 0.02 Anteil des Eigenkapitals, der pro Trade riskiert wird, wenn die Position dimensioniert wird.
DecreaseFactor 3 Lot-Reduktionsdivisor, der nach zwei oder mehr aufeinanderfolgenden Verlust-Trades angewendet wird.
CciPeriod 14 Anzahl der Balken, die vom Commodity Channel Index verwendet werden.
CciLevel 100 Überverkauft/Überkauft-Schwellenwert für CCI-Kreuzungen.
CciCurrentBar 0 Verschiebung des aktuellen CCI-Werts (0 = neueste Kerze).
CciPreviousBar 1 Verschiebung des vorherigen CCI-Werts.
MaPeriod 120 Periode des Trendfilter-gleitenden Durchschnitts.
MaMethod Simple Glättungsmethode des gleitenden Durchschnitts (Simple, Exponential, Smoothed, LinearWeighted).
MaCurrentBar 0 Auf den gleitenden Durchschnittswert angewendete Verschiebung.
MaDelta 0.001 Minimaler Steigungsunterschied zwischen aktuellen und vorherigen MA-Lesewerten.
StopLossPips 0 Initialer Stop-Loss-Abstand in Pips (0 deaktiviert den Stop).
TrailingStopPips 5 Basis-Trailing-Stop-Abstand in Pips (0 deaktiviert das Trailing).
TrailingStepPips 5 Minimale Pip-Verbesserung, bevor der Trailing Stop vorgerückt wird.
CandleType 30m-Zeitrahmen Primäre Kerzensubskription, die von der Strategie verarbeitet wird.

Implementierungshinweise

  • Indikatorpuffer werden intern zwischengespeichert, damit die Strategie auf historische Werte mit beliebigen Verschiebungen zugreifen kann, was den MQL-Ansatz der Indizierung von Indikator-Arrays repliziert.
  • Die Pip-Größe wird aus Security.PriceStep abgeleitet. Wenn das Instrument keinen gültigen Preisschritt meldet, werden die Stop- und Trailing-Abstände als null behandelt.
  • Alle Kommentare im Code sind gemäß den Repository-Richtlinien in Englisch verfasst.
  • Die Python-Version ist absichtlich ausgelassen, wie angefordert.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Conversion of the MetaTrader 5 expert advisor "Starter".
/// Uses the Commodity Channel Index and a moving average slope filter to open trades with adaptive position sizing and trailing protection.
/// </summary>
public class StarterStrategy : Strategy
{
	private readonly StrategyParam<decimal> _maximumRisk;
	private readonly StrategyParam<decimal> _decreaseFactor;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _cciLevel;
	private readonly StrategyParam<int> _cciCurrentBar;
	private readonly StrategyParam<int> _cciPreviousBar;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<MovingAverageMethods> _maMethod;
	private readonly StrategyParam<int> _maCurrentBar;
	private readonly StrategyParam<decimal> _maDelta;
	private readonly StrategyParam<decimal> _stopLossPips;
	private readonly StrategyParam<decimal> _trailingStopPips;
	private readonly StrategyParam<decimal> _trailingStepPips;
	private readonly StrategyParam<DataType> _candleType;

	private CommodityChannelIndex _cci = null!;
	private DecimalLengthIndicator _movingAverage = null!;

	private readonly List<decimal> _cciHistory = new();
	private readonly List<decimal> _maHistory = new();

	private decimal _pipSize;
	private int _historyCapacity;

	private decimal? _longEntryPrice;
	private decimal? _shortEntryPrice;
	private decimal? _longStop;
	private decimal? _shortStop;

	private decimal _signedPosition;
	private Sides? _lastEntrySide;
	private decimal _lastEntryPrice;
	private int _consecutiveLosses;

	/// <summary>
	/// Initializes a new instance of the <see cref="StarterStrategy"/> class.
	/// </summary>
	public StarterStrategy()
	{
		_maximumRisk = Param(nameof(MaximumRisk), 0.02m)
			.SetNotNegative()
			.SetDisplay("Maximum Risk", "Fraction of portfolio equity risked per trade", "Risk Management");

		_decreaseFactor = Param(nameof(DecreaseFactor), 3m)
			.SetNotNegative()
			.SetDisplay("Decrease Factor", "Lot reduction factor after consecutive losses", "Risk Management");

		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "Number of bars for the Commodity Channel Index", "Indicators")
			
			.SetOptimize(5, 60, 1);

		_cciLevel = Param(nameof(CciLevel), 100m)
			.SetGreaterThanZero()
			.SetDisplay("CCI Level", "Threshold used for oversold/overbought detection", "Indicators")
			
			.SetOptimize(50m, 200m, 10m);

		_cciCurrentBar = Param(nameof(CciCurrentBar), 0)
			.SetNotNegative()
			.SetDisplay("CCI Current Bar", "Shift for the current CCI value", "Indicators");

		_cciPreviousBar = Param(nameof(CciPreviousBar), 1)
			.SetNotNegative()
			.SetDisplay("CCI Previous Bar", "Shift for the previous CCI value", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "Number of bars for the moving average", "Indicators")
			
			.SetOptimize(20, 200, 5);

		_maMethod = Param(nameof(MaMethod), MovingAverageMethods.Simple)
			.SetDisplay("MA Method", "Smoothing method applied to the moving average", "Indicators");

		_maCurrentBar = Param(nameof(MaCurrentBar), 0)
			.SetNotNegative()
			.SetDisplay("MA Current Bar", "Shift for the moving average", "Indicators");

		_maDelta = Param(nameof(MaDelta), 0.001m)
			.SetNotNegative()
			.SetDisplay("MA Delta", "Minimum slope difference between current and previous MA", "Signals")
			
			.SetOptimize(0.0001m, 0.01m, 0.0001m);

		_stopLossPips = Param(nameof(StopLossPips), 0m)
			.SetNotNegative()
			.SetDisplay("Stop Loss (pips)", "Initial protective stop distance in pips", "Risk Management")
			
			.SetOptimize(0m, 200m, 10m);

		_trailingStopPips = Param(nameof(TrailingStopPips), 5m)
			.SetNotNegative()
			.SetDisplay("Trailing Stop (pips)", "Base trailing distance in pips", "Risk Management")
			
			.SetOptimize(0m, 200m, 5m);

		_trailingStepPips = Param(nameof(TrailingStepPips), 5m)
			.SetNotNegative()
			.SetDisplay("Trailing Step (pips)", "Minimum improvement required before moving the trailing stop", "Risk Management")
			
			.SetOptimize(0m, 200m, 5m);

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Primary timeframe processed by the strategy", "General");
	}

	/// <summary>
	/// Risk per trade expressed as a fraction of portfolio equity.
	/// </summary>
	public decimal MaximumRisk
	{
		get => _maximumRisk.Value;
		set => _maximumRisk.Value = value;
	}

	/// <summary>
	/// Lot reduction factor applied after consecutive losing trades.
	/// </summary>
	public decimal DecreaseFactor
	{
		get => _decreaseFactor.Value;
		set => _decreaseFactor.Value = value;
	}

	/// <summary>
	/// Period for the Commodity Channel Index indicator.
	/// </summary>
	public int CciPeriod
	{
		get => _cciPeriod.Value;
		set => _cciPeriod.Value = value;
	}

	/// <summary>
	/// Overbought/oversold CCI threshold.
	/// </summary>
	public decimal CciLevel
	{
		get => _cciLevel.Value;
		set => _cciLevel.Value = value;
	}

	/// <summary>
	/// Index of the bar considered "current" for CCI comparisons.
	/// </summary>
	public int CciCurrentBar
	{
		get => _cciCurrentBar.Value;
		set => _cciCurrentBar.Value = value;
	}

	/// <summary>
	/// Index of the bar considered "previous" for CCI comparisons.
	/// </summary>
	public int CciPreviousBar
	{
		get => _cciPreviousBar.Value;
		set => _cciPreviousBar.Value = value;
	}

	/// <summary>
	/// Period for the trend filter moving average.
	/// </summary>
	public int MaPeriod
	{
		get => _maPeriod.Value;
		set => _maPeriod.Value = value;
	}

	/// <summary>
	/// Moving average smoothing method.
	/// </summary>
	public MovingAverageMethods MaMethod
	{
		get => _maMethod.Value;
		set => _maMethod.Value = value;
	}

	/// <summary>
	/// Shift for the moving average value considered "current".
	/// </summary>
	public int MaCurrentBar
	{
		get => _maCurrentBar.Value;
		set => _maCurrentBar.Value = value;
	}

	/// <summary>
	/// Minimum slope difference between current and previous moving average values.
	/// </summary>
	public decimal MaDelta
	{
		get => _maDelta.Value;
		set => _maDelta.Value = value;
	}

	/// <summary>
	/// Initial stop-loss distance expressed in pips.
	/// </summary>
	public decimal StopLossPips
	{
		get => _stopLossPips.Value;
		set => _stopLossPips.Value = value;
	}

	/// <summary>
	/// Trailing stop distance in pips.
	/// </summary>
	public decimal TrailingStopPips
	{
		get => _trailingStopPips.Value;
		set => _trailingStopPips.Value = value;
	}

	/// <summary>
	/// Minimum improvement before advancing the trailing stop in pips.
	/// </summary>
	public decimal TrailingStepPips
	{
		get => _trailingStepPips.Value;
		set => _trailingStepPips.Value = value;
	}

	/// <summary>
	/// Candle data type processed by the strategy.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

/// <inheritdoc />
protected override void OnReseted()
{
	base.OnReseted();

	_cci?.Reset();
	_movingAverage?.Reset();
	_cci = null!;
	_movingAverage = null!;
	_cciHistory.Clear();
	_maHistory.Clear();
	_pipSize = 0m;
	_historyCapacity = 0;
	_longEntryPrice = null;
	_shortEntryPrice = null;
	_longStop = null;
	_shortStop = null;
	_signedPosition = 0m;
	_lastEntrySide = null;
	_lastEntryPrice = 0m;
	_consecutiveLosses = 0;
}

/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
	base.OnStarted2(time);

		_pipSize = GetPipSize();
		_historyCapacity = CalculateHistoryCapacity();
		_cciHistory.Clear();
		_maHistory.Clear();
		_longEntryPrice = null;
		_shortEntryPrice = null;
		_longStop = null;
		_shortStop = null;
		_signedPosition = 0m;
		_lastEntrySide = null;
		_lastEntryPrice = 0m;
		_consecutiveLosses = 0;

		_cci = new CommodityChannelIndex { Length = CciPeriod };
		_movingAverage = CreateMovingAverage(MaMethod, MaPeriod);

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(_cci, _movingAverage, OnProcessCandle)
			.Start();
	}

	private void OnProcessCandle(ICandleMessage candle, decimal cciValue, decimal maValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_cci.IsFormed || !_movingAverage.IsFormed)
			return;

		// Store the latest indicator values so we can access shifted history like in MetaTrader.
		AddHistory(_cciHistory, cciValue);
		AddHistory(_maHistory, maValue);

		if (Position != 0)
		{
			// Manage trailing stop and protective exits for open positions before evaluating new entries.
			UpdateTrailing(candle);
			CheckProtectiveStops(candle);
		}

		if (Position != 0)
			// The original expert only opens a new position when no trades are active.
			return;

		if (!TryGetHistoryValue(_maHistory, MaCurrentBar, out var maCurrent) ||
			!TryGetHistoryValue(_maHistory, MaCurrentBar + 1, out var maPrevious))
			return;

		if (!TryGetHistoryValue(_cciHistory, CciCurrentBar, out var cciCurrent) ||
			!TryGetHistoryValue(_cciHistory, CciPreviousBar, out var cciPrevious))
			return;

		// Compare the moving average slope and CCI swings to detect breakout conditions.
		var maSlope = maCurrent - maPrevious;

		if (maSlope > MaDelta && cciCurrent > cciPrevious &&
			cciCurrent > -CciLevel && cciPrevious < -CciLevel)
		{
			TryEnterLong(candle.ClosePrice);
		}
		else if (maSlope < -MaDelta && cciCurrent < cciPrevious &&
			cciCurrent < CciLevel && cciPrevious > CciLevel)
		{
			TryEnterShort(candle.ClosePrice);
		}
	}

	private void TryEnterLong(decimal price)
	{
		var volume = CalculateTradeVolume(price);
		if (volume <= 0m)
			return;

		BuyMarket(volume);
		LogInfo($"Opening long position at {price} with volume {volume}.");
	}

	private void TryEnterShort(decimal price)
	{
		var volume = CalculateTradeVolume(price);
		if (volume <= 0m)
			return;

		SellMarket(volume);
		LogInfo($"Opening short position at {price} with volume {volume}.");
	}

	private void CheckProtectiveStops(ICandleMessage candle)
	{
		if (Position > 0 && _longStop.HasValue && candle.LowPrice <= _longStop.Value)
		{
			var volume = Math.Abs(Position);
			if (volume > 0)
			{
				SellMarket(volume);
				LogInfo($"Long stop-loss triggered at {_longStop.Value}.");
			}

			ResetLongProtection();
			return;
		}

		if (Position < 0 && _shortStop.HasValue && candle.HighPrice >= _shortStop.Value)
		{
			var volume = Math.Abs(Position);
			if (volume > 0)
			{
				BuyMarket(volume);
				LogInfo($"Short stop-loss triggered at {_shortStop.Value}.");
			}

			ResetShortProtection();
		}
	}

	private void UpdateTrailing(ICandleMessage candle)
	{
		if (TrailingStopPips <= 0m || _pipSize <= 0m)
			return;

		var offset = TrailingStopPips * _pipSize;
		var step = TrailingStepPips * _pipSize;

		if (Position > 0 && _longEntryPrice.HasValue)
		{
			// Advance the long stop only when price improves by at least the configured step.
			var targetStop = candle.ClosePrice - offset;
			var threshold = candle.ClosePrice - (offset + step);

			if (!_longStop.HasValue || _longStop.Value < threshold)
			{
				_longStop = targetStop;
				LogInfo($"Trailing long stop moved to {_longStop.Value}.");
			}
		}
		else if (Position < 0 && _shortEntryPrice.HasValue)
		{
			// Mirror the trailing logic for short positions.
			var targetStop = candle.ClosePrice + offset;
			var threshold = candle.ClosePrice + (offset + step);

			if (!_shortStop.HasValue || _shortStop.Value > threshold)
			{
				_shortStop = targetStop;
				LogInfo($"Trailing short stop moved to {_shortStop.Value}.");
			}
		}
	}

	private decimal CalculateTradeVolume(decimal price)
	{
		// Start from the configured strategy volume; fall back to 1 if undefined.
		var baseVolume = Volume > 0 ? Volume : 1m;

		if (price <= 0m)
			return NormalizeVolume(baseVolume);

		var equity = Portfolio?.CurrentValue ?? 0m;
		if (equity <= 0m || MaximumRisk <= 0m)
			return NormalizeVolume(baseVolume);

		// Position size equals equity * risk percent divided by price, mimicking the original risk formula.
		var volume = equity * MaximumRisk / price;

		if (DecreaseFactor > 0m && _consecutiveLosses > 1)
		{
			// Reduce the lot size after two or more losses, replicating MetaTrader's "DecreaseFactor" behavior.
			var reduction = volume * _consecutiveLosses / DecreaseFactor;
			volume -= reduction;
		}

		if (volume <= 0m)
			volume = baseVolume;

		return NormalizeVolume(volume);
	}

	private decimal NormalizeVolume(decimal volume)
	{
		var security = Security;
		if (security != null)
		{
			var step = security.VolumeStep ?? 1m;
			if (step <= 0m)
				step = 1m;

			if (volume < step)
				volume = step;

			var steps = Math.Floor(volume / step);
			if (steps < 1m)
				steps = 1m;

			volume = steps * step;
		}

		if (volume <= 0m)
			volume = 1m;

		return volume;
	}

	private void AddHistory(List<decimal> history, decimal value)
	{
		history.Add(value);

		if (history.Count > _historyCapacity)
			history.RemoveRange(0, history.Count - _historyCapacity);
	}

	private static bool TryGetHistoryValue(List<decimal> history, int shift, out decimal value)
	{
		value = default;

		if (shift < 0)
			return false;

		var index = history.Count - 1 - shift;
		if (index < 0 || index >= history.Count)
			return false;

		value = history[index];
		return true;
	}

	private void ResetLongProtection()
	{
		_longEntryPrice = null;
		_longStop = null;
	}

	private void ResetShortProtection()
	{
		_shortEntryPrice = null;
		_shortStop = null;
	}

	private decimal GetPipSize()
	{
		var security = Security;
		if (security == null)
			return 0m;

		var step = security.PriceStep ?? 0m;
		if (step <= 0m)
			return 0m;

		return step;
	}

	private int CalculateHistoryCapacity()
	{
		var cciRequirement = Math.Max(CciCurrentBar, CciPreviousBar) + CciPeriod + 5;
		var maRequirement = MaCurrentBar + MaPeriod + 5;

		return Math.Max(cciRequirement, maRequirement);
	}

	private static DecimalLengthIndicator CreateMovingAverage(MovingAverageMethods method, int period)
	{
		return method switch
		{
			MovingAverageMethods.Simple => new SMA { Length = period },
			MovingAverageMethods.Exponential => new EMA { Length = period },
			MovingAverageMethods.Smoothed => new SmoothedMovingAverage { Length = period },
			MovingAverageMethods.LinearWeighted => new WeightedMovingAverage { Length = period },
			_ => new SMA { Length = period }
		};
	}

	/// <inheritdoc />
	protected override void OnOwnTradeReceived(MyTrade trade)
	{
		base.OnOwnTradeReceived(trade);

		// Track executed volume to update position state and the loss streak counter.
		var volume = trade.Trade.Volume;
		if (volume <= 0m)
			return;

		var delta = trade.Order.Side == Sides.Buy ? volume : -volume;
		var previousPosition = _signedPosition;
		_signedPosition += delta;

		if (previousPosition == 0m && _signedPosition != 0m)
		{
			_lastEntrySide = trade.Order.Side;
			_lastEntryPrice = trade.Trade.Price;

			if (_lastEntrySide == Sides.Buy)
			{
				_longEntryPrice = trade.Trade.Price;
				_longStop = StopLossPips > 0m && _pipSize > 0m ? _lastEntryPrice - (StopLossPips * _pipSize) : null;
				ResetShortProtection();
			}
			else if (_lastEntrySide == Sides.Sell)
			{
				_shortEntryPrice = trade.Trade.Price;
				_shortStop = StopLossPips > 0m && _pipSize > 0m ? _lastEntryPrice + (StopLossPips * _pipSize) : null;
				ResetLongProtection();
			}
		}
		else if (previousPosition != 0m && _signedPosition == 0m)
		{
			var exitPrice = trade.Trade.Price;

			if (_lastEntrySide != null && _lastEntryPrice != 0m)
			{
				var profit = _lastEntrySide == Sides.Buy
					? exitPrice - _lastEntryPrice
					: _lastEntryPrice - exitPrice;

				if (profit > 0m)
				{
					_consecutiveLosses = 0;
				}
				else if (profit < 0m)
				{
					_consecutiveLosses++;
				}
			}

			_lastEntrySide = null;
			_lastEntryPrice = 0m;
			ResetLongProtection();
			ResetShortProtection();
		}
	}

	public enum MovingAverageMethods
	{
		/// <summary>
		/// Simple moving average (equivalent to MODE_SMA in MetaTrader).
		/// </summary>
		Simple,

		/// <summary>
		/// Exponential moving average (MODE_EMA).
		/// </summary>
		Exponential,

		/// <summary>
		/// Smoothed moving average (MODE_SMMA).
		/// </summary>
		Smoothed,

		/// <summary>
		/// Linear weighted moving average (MODE_LWMA).
		/// </summary>
		LinearWeighted
	}
}