Эта стратегия представляет собой перенос на высокоуровневый API StockSharp советника MetaTrader 4 oc08_vy_m0moqesu15 из каталога MQL/8615. Оригинальный советник синхронизирует позицию с одной сглаженной скользящей средней (SMMA) и прикрепляет к каждой сделке фиксированные уровни стоп-лосса и тейк-профита. Версия на C# сохраняет ту же направленную идею, используя стандартные компоненты StockSharp.
Торговая идея
Направление: Закрытие цены выше сглаженной скользящей средней трактуется как восходящий тренд, ниже — как нисходящий.
Выравнивание позиции: Стратегия поддерживает только одну позицию и при смене сигнала мгновенно переворачивается в новое направление.
Управление рисками: Для каждой позиции задаются стоп-лосс и тейк-профит в шагах цены. Функция StartProtection заменяет ручную установку SL/TP из MQ4.
Исполнение: Заявки отправляются по рынку после закрытия свечи, что повторяет логику OrdersTotal()==0 в исходном эксперте.
Как работает стратегия
При старте происходит подписка на свечи выбранного таймфрейма и привязка индикатора SmoothedMovingAverage с заданным периодом.
После закрытия свечи значение индикатора сравнивается с ценой закрытия.
Если закрытие выше SMMA и стратегия находится в шорте либо вне рынка, отправляется рыночная покупка, перекрывающая шорт (если был) и открывающая лонг.
Если закрытие ниже SMMA и стратегия в лонге либо вне рынка, отправляется рыночная продажа, перекрывающая лонг (если был) и открывающая шорт.
Расстояния стоп-лосса и тейк-профита рассчитываются один раз при запуске на основе PriceStep инструмента. Значение 0 отключает соответствующий уровень.
При наличии области графика автоматически выводятся свечи, значение индикатора и сделки стратегии.
Параметры
Параметр
Значение по умолчанию
Описание
StopLossPoints
100
Расстояние стоп-лосса в шагах цены. 0 — стоп отключён.
TakeProfitPoints
100
Расстояние тейк-профита в шагах цены. 0 — тейк отключён.
MaPeriod
12
Период сглаженной скользящей средней для определения направления тренда.
TradeVolume
1
Объём рыночной заявки. При старте значение копируется в свойство Strategy.Volume.
CandleType
Таймфрейм 15 минут
Тип свечей (таймфрейм), по которым строятся индикатор и сигналы.
Все параметры настраиваются в StockSharp Designer/Runner и снабжены диапазонами для оптимизации.
Отличия от версии MetaTrader
Расчёт объёма через свободную маржу (Lots/Prots) заменён на фиксированный параметр TradeVolume, что обеспечивает предсказуемость и совместимость с портфелями StockSharp.
Стоп-лосс и тейк-профит управляются через StartProtection, что воспроизводит исходные смещения, но использует стандартные механизмы StockSharp.
Стратегия игнорирует незавершённые свечи, повторяя логику флага New_Bar из MQ4 и предотвращая досрочные сделки.
Практические рекомендации
Убедитесь, что инструмент предоставляет корректный PriceStep. Если шаг не задан, стратегия использует значение 1 при вычислении защитных расстояний.
Период скользящей средней синхронизируется с текущим параметром на каждой свече, поэтому изменения настроек применяются без перезапуска.
Для полного соответствия оригиналу используйте тот же таймфрейм графика и задайте объём заявки согласно желаемому торговому лоту.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Smoothed MA directional strategy. Goes long when price is above the MA, short when below.
/// </summary>
public class SmoothedMaDirectionalStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
public SmoothedMaDirectionalStrategy()
{
_maPeriod = Param(nameof(MaPeriod), 12)
.SetDisplay("MA Period", "Number of bars for the moving average.", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Time frame used for price analysis.", "General");
}
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal maValue)
{
if (candle.State != CandleStates.Finished)
return;
var closePrice = candle.ClosePrice;
if (closePrice > maValue && Position <= 0)
{
// Price above MA - go long
if (Position < 0)
BuyMarket(); // Close short
BuyMarket(); // Open long
}
else if (closePrice < maValue && Position >= 0)
{
// Price below MA - go short
if (Position > 0)
SellMarket(); // Close long
SellMarket(); // Open short
}
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class smoothed_ma_directional_strategy(Strategy):
def __init__(self):
super(smoothed_ma_directional_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 12).SetDisplay("MA Period", "Number of bars for MA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Time frame", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnStarted2(self, time):
super(smoothed_ma_directional_strategy, self).OnStarted2(time)
ma = SimpleMovingAverage()
ma.Length = self._ma_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(ma, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def OnProcess(self, candle, ma_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
if close > ma_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif close < ma_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return smoothed_ma_directional_strategy()