Ultra Absolutely No Lag LWMA — перевод эксперта MetaTrader на StockSharp с использованием высокоуровневого API. Пайплайн индикатора выполняет двойное взвешенное сглаживание цены, затем прогоняет данные через набор последовательно удлиняющихся сглаживающих средних и считает, сколько ступеней направлено вверх или вниз. Итоговые счётчики дополнительно сглаживаются и преобразуются в цветовые коды, которые определяют торговые решения. При необходимости стратегия выставляет защитные стоп- и тейк-приказы для каждой новой позиции.
Логика индикатора
Двойной LWMA-фильтр — выбранная цена (по умолчанию закрытие) проходит через две последовательные LWMA, что снижает шум.
Лестница сглаживания — фильтрованный ряд обрабатывается набором скользящих средних с увеличивающимися периодами (StartLength + StepSize × шаг), тип скользящей средней задаётся параметром TrendMethod.
Подсчёт быков/медведей — на каждой ступени сравнивается текущее значение с предыдущим. Рост увеличивает бычий счётчик, снижение — медвежий.
Финальное сглаживание — счётчики дополнительно сглаживаются методом 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 — не выставлять).
Рекомендации по использованию
Подберите CandleType в соответствии с желаемым таймфреймом (в MQL-версии по умолчанию H4).
Изменяйте StepsTotal, StartLength и StepSize, чтобы настроить компромисс между скоростью реакции и плавностью.
Если защита не нужна, оставьте StopLossOffset и TakeProfitOffset равными нулю.
Некоторые методы сглаживания MetaTrader отсутствуют в StockSharp; в таких случаях используется Jurik или EMA как наиболее близкая альтернатива.
Стратегия работает только на закрытых свечах, поэтому тестирование лучше проводить на дневных либо четырёхчасовых данных, где задержка соответствует оригиналу.
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);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ultra_absolutely_no_lag_lwma_strategy(Strategy):
def __init__(self):
super(ultra_absolutely_no_lag_lwma_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._fast_length = self.Param("FastLength", 7) \
.SetDisplay("Fast Length", "Fast EMA period", "Indicators")
self._slow_length = self.Param("SlowLength", 21) \
.SetDisplay("Slow Length", "Slow EMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastLength(self):
return self._fast_length.Value
@property
def SlowLength(self):
return self._slow_length.Value
def OnReseted(self):
super(ultra_absolutely_no_lag_lwma_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(ultra_absolutely_no_lag_lwma_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastLength
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return ultra_absolutely_no_lag_lwma_strategy()