Стратегия 4 SMA повторяет советник MetaTrader 4 SMA.mq4. Расчёты выполняются на 30-минутных свечах по медианной цене (среднее между High и Low). Сравнение четырёх простых скользящих средних с периодами 5, 20, 40 и 60 позволяет находить моменты ускорения тренда. Порт StockSharp сохраняет логику единственной позиции и задействует высокоуровневый API фреймворка.
Логика торговли
Для каждой закрытой свечи вычисляется медианная цена (high + low) / 2, которая подаётся на вход четырём SMA.
Покупка выполняется, когда быстрая SMA выше средней, средняя выше медленной, медленная превосходит очень медленную минимум на один шаг цены, а значение медленной SMA на предыдущей свече было ниже или равно очень медленной. Сделка открывается только при отсутствии длинной позиции.
Продажа — зеркальные условия: быстрая SMA ниже средней, средняя ниже медленной, очень медленная выше медленной не менее чем на шаг цены, а медленная SMA на предыдущей свече была выше или равна очень медленной. Открывается только при отсутствии короткой позиции.
Управление позицией
Длинные позиции закрываются при пересечении медленной SMA вниз через очень медленную, короткие — при обратном пересечении.
После входа рассчитываются уровни стоп-лосса и тейк-профита. Расстояния измеряются в пунктах и умножаются на шаг цены инструмента, как и в оригинальном коде.
Трейлинг-стоп активируется после прохождения ценой заданного расстояния. Уровень подтягивается по каждой свече и никогда не отодвигается назад.
Параметры
Название
Описание
Значение по умолчанию
CandleType
Свечной поток для расчётов (по умолчанию 30 минут).
Таймфрейм M30
TakeProfit
Расстояние до тейк-профита в пунктах.
50
StopLoss
Расстояние до стоп-лосса в пунктах.
50
TrailingStop
Дистанция трейлинг-стопа в пунктах.
11
FastLength
Период быстрой SMA.
5
MediumLength
Период средней SMA.
20
SlowLength
Период медленной SMA.
40
VerySlowLength
Период очень медленной SMA.
60
Все числовые параметры доступны для оптимизации через интерфейс StockSharp.
Отличия от версии MQL
В MT4 трейлинг реализован через модификацию ордеров, тогда как порт закрывает позицию рыночным приказом при достижении рассчитанного уровня.
Учёт шага цены позволяет применять стратегию к инструментам с любой минимальной котировкой.
Реализация построена на высокоуровневых подписках SubscribeCandles и системе параметров, что соответствует рекомендациям проекта.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class FourSmaStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
private int _cooldownRemaining;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FourSmaStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 20).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 80).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 100).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevFast = fast;
_prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevFast = fast;
_prevSlow = slow;
}
}