Стратегия воспроизводит советник MetaTrader "GLAM Trader", объединяя сигналы сразу с трёх таймфреймов:
EMA(3) на 15-минутных свечах фиксирует краткосрочный тренд.
Фильтр Лагерра с параметром gamma 0.7 на пятиминутных свечах показывает, где находится цена относительно сглаженной траектории.
Awesome Oscillator на часовом графике добавляет компонент импульса в стиле Билла Уильямса.
Сделка открывается только при полном согласии всех индикаторов, что позволяет отсеять ложные сигналы, возникающие при анализе одного таймфрейма.
Логика работы
Подготовка данных
15-минутные свечи подключены к ExponentialMovingAverage длиной EmaPeriod (по умолчанию 3).
5-минутные свечи поступают в LaguerreFilter с параметром LaguerreGamma.
Часовые свечи подключены к AwesomeOscillator.
Для каждого таймфрейма сохраняется последнее закрытие готовой свечи, чтобы повторить сравнение "значение индикатора против цены" из оригинального советника.
Условия входа
Покупка: EMA находится выше текущего закрытия 15-минутной свечи, Лагерр выше последнего закрытия на M5, а Awesome Oscillator выше закрытия последней часовой свечи.
Продажа: все три условия выполняются в противоположном направлении.
Управление рисками
Раздельные расстояния стоп-лосса и тейк-профита в пунктах для длинных и коротких позиций.
Трейлинг-стоп активируется, когда цена проходит минимум заданное число пунктов в сторону прибыли, и затем подтягивается без отката назад.
Любой защитный сценарий (тейк-профит, стоп-лосс, трейлинг) закрывает позицию целиком рыночным ордером, как и в версии на MQL.
Параметры
Параметр
Описание
Значение по умолчанию
TradeVolume
Объём ордера при входе.
0.1
PrimaryCandleType
Таймфрейм, на котором рассчитывается EMA и принимается решение.
Свечи 15 минут
LaguerreCandleType
Таймфрейм для фильтра Лагерра.
Свечи 5 минут
AwesomeCandleType
Таймфрейм для Awesome Oscillator.
Свечи 60 минут
EmaPeriod
Длина EMA на основном таймфрейме.
3
LaguerreGamma
Параметр gamma фильтра Лагерра.
0.7
LongStopLossPoints
Стоп-лосс для длинных позиций (в пунктах).
20
ShortStopLossPoints
Стоп-лосс для коротких позиций (в пунктах).
20
LongTakeProfitPoints
Тейк-профит для длинных позиций (в пунктах).
50
ShortTakeProfitPoints
Тейк-профит для коротких позиций (в пунктах).
50
LongTrailingPoints
Дистанция трейлинг-стопа для лонгов (в пунктах).
15
ShortTrailingPoints
Дистанция трейлинг-стопа для шортов (в пунктах).
15
Примечания
Хранятся только последние значения индикаторов — дополнительные массивы цен не создаются.
Все комментарии и сообщения в коде написаны на английском языке в соответствии с требованиями проекта.
Подбирайте параметры, учитывая PriceStep инструмента, чтобы защитные уровни соответствовали минимальному шагу цены на бирже.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Glam Trader strategy - EMA crossover with momentum confirmation.
/// Buys when fast EMA crosses above slow EMA and momentum is positive.
/// Sells when fast EMA crosses below slow EMA and momentum is negative.
/// </summary>
public class GlamTraderSimpleStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GlamTraderSimpleStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_momentumPeriod = Param(nameof(MomentumPeriod), 14)
.SetDisplay("Momentum Period", "Momentum lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var mom = new Momentum { Length = MomentumPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, mom, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal mom)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
// Fast crosses above slow + positive momentum = buy
if (_prevFast <= _prevSlow && fast > slow && mom > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Fast crosses below slow + negative momentum = sell
else if (_prevFast >= _prevSlow && fast < slow && mom < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}