Стратегия повторяет логику советника MetaTrader Exp_AbsolutelyNoLagLwma. Для выбранных свечей выполняется двойное сглаживание линейной взвешенной средней (LWMA), после чего направление наклона классифицируется цветами: 2 — восходящее движение, 1 — нейтральное состояние, 0 — нисходящее движение. Смена цвета генерирует торговые сигналы. Реализация в StockSharp использует высокоуровневый API: стратегия подписывается на свечи заданного таймфрейма и выставляет рыночные заявки в соответствии с сигналами.
Логика работы
Индикаторная часть
Источник цены выбирается параметром Price Type.
К выбранной цене применяется LWMA длиной LWMA Length.
Результат дополнительно сглаживается второй LWMA той же длины.
Текущее значение сравнивается с предыдущим:
2 (рост) — текущее значение выше предыдущего.
1 (флэт) — значения равны.
0 (падение) — текущее значение ниже предыдущего.
Формирование сигналов
Обрабатываются только завершенные свечи. Параметр Signal Bar задает смещение относительно последней завершенной свечи (1 — последняя, 2 — предпоследняя и т.д.). Дополнительно запоминается цвет предыдущей свечи, чтобы не генерировать повторные входы.
Бычий переход: выбранная свеча имеет цвет 2, а предыдущая — не 2. При включенном разрешении открываются длинные позиции и закрываются активные короткие.
Медвежий переход: выбранная свеча имеет цвет 0, а предыдущая — не 0. При включенном разрешении открываются короткие позиции и закрываются активные длинные.
Управление позициями
Сделки совершаются рыночными заявками. При развороте направление позиции меняется объемом Volume + |Position|, что гарантирует закрытие противоположной позиции.
Разрешения на входы и выходы по лонгам/шортам настраиваются отдельно, что позволяет использовать стратегию только для входов либо только для выходов.
В методе OnStarted вызывается StartProtection(), чтобы активировать стандартную защиту StockSharp.
Параметры
LWMA Length — длина обеих LWMA.
Price Type — тип цены для расчета индикатора (Close, Open, High, Low, Median, Typical, Weighted, Simpl, Quarter, варианты TrendFollow и Demark).
Signal Bar — количество завершенных свечей назад для оценки сигнала.
Enable Long Entries — разрешение на открытие длинных позиций.
Enable Short Entries — разрешение на открытие коротких позиций.
Enable Long Exits — закрытие длинных позиций при появлении медвежьего сигнала.
Enable Short Exits — закрытие коротких позиций при появлении бычьего сигнала.
Candle Type — таймфрейм свечей, используемых индикатором.
Volume — стандартный параметр стратегии, определяющий объем сделок при открытии.
Дополнительные сведения
По умолчанию используется таймфрейм 4 часа, как в оригинальном советнике, но его можно изменить через параметр Candle Type.
Стратегия не выставляет стоп-лоссы и тейк-профиты; при необходимости подключайте дополнительные модули риск-менеджмента StockSharp.
По требованию Python-версия не создавалась.
namespace StockSharp.Samples.Strategies;
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Absolutely No Lag LWMA strategy (simplified).
/// Uses two EMAs of different periods to detect trend direction changes.
/// </summary>
public class AbsolutelyNoLagLwmaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public AbsolutelyNoLagLwmaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Source candles", "General");
_fastPeriod = Param(nameof(FastPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
decimal prevFast = 0, prevSlow = 0;
bool 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);
}
}
}