Открыть на GitHub

Стратегия Ultra Absolutely No Lag LWMA

Общее описание

Ultra Absolutely No Lag LWMA — перевод эксперта MetaTrader на StockSharp с использованием высокоуровневого API. Пайплайн индикатора выполняет двойное взвешенное сглаживание цены, затем прогоняет данные через набор последовательно удлиняющихся сглаживающих средних и считает, сколько ступеней направлено вверх или вниз. Итоговые счётчики дополнительно сглаживаются и преобразуются в цветовые коды, которые определяют торговые решения. При необходимости стратегия выставляет защитные стоп- и тейк-приказы для каждой новой позиции.

Логика индикатора

  1. Двойной LWMA-фильтр — выбранная цена (по умолчанию закрытие) проходит через две последовательные LWMA, что снижает шум.
  2. Лестница сглаживания — фильтрованный ряд обрабатывается набором скользящих средних с увеличивающимися периодами (StartLength + StepSize × шаг), тип скользящей средней задаётся параметром TrendMethod.
  3. Подсчёт быков/медведей — на каждой ступени сравнивается текущее значение с предыдущим. Рост увеличивает бычий счётчик, снижение — медвежий.
  4. Финальное сглаживание — счётчики дополнительно сглаживаются методом SmoothingMethod, формируя финальное состояние индикатора.

Цвета полностью повторяют оригинал: 7–8 — сильный бычий режим, 5–6 — умеренный бычий, 1–2 — сильный медвежий, 3–4 — умеренный медвежий, 0 — состояние не сформировано.

Торговые правила

  • Если более старая свеча имела код > 4 (бычий), а последняя закрытая свеча дала код < 5 (и не равна нулю), стратегия закрывает шорты и может открыть новую длинную позицию.
  • Если более старая свеча имела код < 5 (и не равна нулю), а последняя закрытая свеча дала код > 4, стратегия закрывает лонги и может открыть шорт.
  • Параметры StopLossOffset и TakeProfitOffset задают абсолютные расстояния для защитных приказов. Ноль отключает соответствующий приказ.

Сигналы вычисляются на двух последних завершённых свечах таймфрейма индикатора, что совпадает с поведением оригинального эксперта.

Параметры

Параметр Описание
CandleType Тип/таймфрейм свечей для расчёта индикатора.
BaseLength Период двойного LWMA-фильтра.
AppliedPriceMode Тип цены (close, open, median, DeMark и т. д.).
TrendMethod Тип скользящей средней для лестницы сглаживания.
StartLength Стартовый период первой ступени.
StepSize Прибавка к периоду на каждой следующей ступени.
StepsTotal Количество ступеней лестницы.
SmoothingMethod Метод финального сглаживания счётчиков.
SmoothingLength Период финального сглаживания.
UpLevelPercent Процентный порог «сильного» бычьего режима.
DownLevelPercent Процентный порог «сильного» медвежьего режима.
SignalBar Номер свечи для анализа (1 = предыдущая завершённая свеча).
AllowBuyOpen / AllowSellOpen Разрешение на открытие длинных/коротких позиций.
AllowBuyClose / AllowSellClose Разрешение на закрытие длинных/коротких позиций.
StopLossOffset Абсолютное расстояние до стоп-лосса (0 — не выставлять).
TakeProfitOffset Абсолютное расстояние до тейк-профита (0 — не выставлять).

Рекомендации по использованию

  1. Подберите CandleType в соответствии с желаемым таймфреймом (в MQL-версии по умолчанию H4).
  2. Изменяйте StepsTotal, StartLength и StepSize, чтобы настроить компромисс между скоростью реакции и плавностью.
  3. Если защита не нужна, оставьте StopLossOffset и TakeProfitOffset равными нулю.
  4. Некоторые методы сглаживания MetaTrader отсутствуют в StockSharp; в таких случаях используется Jurik или EMA как наиболее близкая альтернатива.
  5. Стратегия работает только на закрытых свечах, поэтому тестирование лучше проводить на дневных либо четырёхчасовых данных, где задержка соответствует оригиналу.
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>
/// Ultra Absolutely No Lag LWMA strategy (simplified). Uses EMA crossover
/// as a trend-following proxy for the original multi-stage LWMA ladder.
/// </summary>
public class UltraAbsolutelyNoLagLwmaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	public UltraAbsolutelyNoLagLwmaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_fastLength = Param(nameof(FastLength), 7)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Fast EMA period", "Indicators");

		_slowLength = Param(nameof(SlowLength), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "Indicators");
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowLength };

		decimal prevFast = 0, prevSlow = 0;
		var hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevFast = fastValue;
					prevSlow = slowValue;
					return;
				}

				if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
					BuyMarket();
				else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
					SellMarket();

				prevFast = fastValue;
				prevSlow = slowValue;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fastEma);
			DrawIndicator(area, slowEma);
			DrawOwnTrades(area);
		}
	}
}