Открыть на GitHub

Стратегия Up3x1 со смещёнными SMA (конвертация из MT4)

Обзор

  • Конвертация эксперта MetaTrader 4 up3x1.mq4 из каталога MQL/8097 в высокоуровневый API StockSharp.
  • Сохраняет три простых скользящих средних со смещением на 6 баров, как в оригинале.
  • Обрабатывает только завершённые свечи, повторяя проверку Volume[0] > 1 для одного решения на бар.
  • Реализованы стоп-лосс, тейк-профит, уменьшение объёма после убыточных сделок и опциональный трейлинг-стоп.

Логика торговли

  1. Индикаторы — три SMA с периодами 24, 60 и 120 (смещение 6 баров).
  2. Вход в лонг — предыдущая свеча: SMAfast₍t-1₎ < SMAmedium₍t-1₎ < SMAslow₍t-1₎; текущая свеча: SMAmedium₍t₎ < SMAfast₍t₎ < SMAslow₍t₎ (ma1 < ma2 < ma3 && ma5 < ma4 < ma6).
  3. Вход в шорт — предыдущая свеча: SMAfast₍t-1₎ > SMAmedium₍t-1₎ > SMAslow₍t-1₎; текущая свеча: SMAmedium₍t₎ > SMAfast₍t₎ > SMAslow₍t₎.
  4. Выход
    • Тейк-профит и стоп-лосс вычисляются по расстоянию в пунктах, умноженному на Security.PriceStep.
    • Трейлинг-стоп активируется, когда прибыль превышает TrailingStopPoints, и удерживает дистанцию от экстремума.
    • При смене порядка средних позиция закрывается, как в OrderClose исходного кода.

Управление объёмом

  • Если нет данных по портфелю, используется BaseVolume (0.1 лота).
  • При наличии Portfolio.CurrentValue объём = CurrentValue * RiskFraction (по умолчанию 0.00002, что соответствует FreeMargin * 0.02 / 1000).
  • После более чем одной убыточной сделки объём уменьшается на volume * losses / 3 — точная копия функции LotsOptimized.
  • Объём округляется вниз до Security.VolumeStep; сделки пропускаются, если результат меньше Security.MinVolume.

Параметры

Параметр Значение по умолчанию Описание
FastPeriod 24 Период быстрой смещённой SMA.
MediumPeriod 60 Период средней смещённой SMA.
SlowPeriod 120 Период медленной смещённой SMA.
TakeProfitPoints 150 Дистанция до тейк-профита в пунктах.
StopLossPoints 100 Дистанция до стоп-лосса в пунктах.
TrailingStopPoints 100 Размер трейлинг-стопа (0 — отключить).
BaseVolume 0.1 Базовый и минимальный объём сделки.
RiskFraction 0.00002 Множитель портфеля для динамического объёма.
CandleType Свечи H1 Тип свечей для расчётов.

Особенности конвертации

  • Используется высокоуровневый API (SubscribeCandles и Bind), без ручного хранения историй.
  • Значения индикаторов сохраняются между вызовами, имитируя обращение shift из MQL.
  • Защитные выходы исполняются рыночными командами на вычисленном уровне, что соответствует архитектуре StockSharp.
  • Все комментарии в коде написаны на английском языке, как требуют правила.

Рекомендации по работе

  1. Подключите стратегию к инструменту и портфелю в Designer или в коде.
  2. Настройте CandleType под нужный таймфрейм (по умолчанию часовые свечи).
  3. Проверьте параметры в пунктах с учётом шага цены выбранного инструмента.
  4. Установите TrailingStopPoints в ноль, если трейлинг не нужен.
  5. Следите за логами "Enter long/short" и "Exit long/short", чтобы контролировать работу алгоритма.

Структура каталога

API/3924/
├── CS/Up3x1ShiftedSmaStrategy.cs
├── README.md
├── README_zh.md
└── README_ru.md

Отказ от ответственности

Торговля на финансовых рынках связана с повышенным риском. Пример предоставлен в образовательных целях и требует тщательного тестирования до запуска на реальном счёте.

using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

public class Up3x1ShiftedSmaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public Up3x1ShiftedSmaStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 8).SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 24).SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = default;
		_prevSlow = default;
		_hasPrev = default;
		_cooldown = default;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { 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 (!IsFormedAndOnlineAndAllowTrading()) return;

		if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
		if (_cooldown > 0)
		{
			_cooldown--;
			_prevFast = fast;
			_prevSlow = slow;
			return;
		}

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{
			var volume = Volume + Math.Abs(Position);
			BuyMarket(volume);
			_cooldown = 2;
		}
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{
			var volume = Volume + Math.Abs(Position);
			SellMarket(volume);
			_cooldown = 2;
		}

		_prevFast = fast; _prevSlow = slow;
	}
}