Открыть на GitHub

Стратегия TugbaGold

Общее описание

TugbaGold — это сеточный советник из MetaTrader 5, использующий мартингейл и усреднение. Конвертация переносит его логику в StockSharp с применением высокоуровневого API. Стратегия добавляет новые ордера, когда предыдущая свеча закрывается в сторону импульса, и строит сетку позиций с заданным шагом. Закрытие сетки выполняется либо полной фиксацией крайних ордеров, либо частичным закрытием в зависимости от выбранного режима.

Логика работы

  1. Анализируются закрытые свечи типа, заданного параметром CandleType. Для сигналов используется предыдущая свеча, как в оригинале MT5.
  2. Бычья свеча разрешает постановку нового buy-ордера, медвежья — нового sell-ордера.
  3. Новый ордер добавляется только если дистанция до лучшей существующей цены больше PointOrderStepPips.
  4. Первый ордер открывается объёмом StartVolume. Каждый следующий удваивает объём самой выгодной позиции, но не превышает MaxVolume и биржевые ограничения.
  5. Когда в корзине есть минимум два ордера, вычисляются целевые цены с учётом буфера MinimalProfitPips:
    • Average — средневзвешенное крайних ордеров + буфер прибыли.
    • Partial — комбинация худшей и лучшей позиций, где худшая использует StartVolume, а лучшая — свой фактический объём.
  6. При достижении цели выполняются соответствующие действия:
    • Average — полное закрытие обеих крайних позиций.
    • Partial — полное закрытие худшей позиции и частичное (StartVolume) закрытие лучшей.
  7. Если в рынке всего один ордер, применяется тейк-профит TakeProfitPips.

Параметры

Параметр Описание
TakeProfitPips Дистанция тейк-профита для одиночной позиции. 0 — отключить.
StartVolume Начальный объём первого ордера сетки.
MaxVolume Максимальный объём ордера. 0 — без ограничения.
CloseMode Режим закрытия: Average (две крайние позиции) или Partial (частичное + полное).
PointOrderStepPips Минимальная дистанция между усредняющими ордерами.
MinimalProfitPips Дополнительный буфер прибыли для выхода.
CandleType Тип свечей, используемых для сигналов.

Управление позицией

  • Шаг цены берётся из Security.PriceStep, иначе используется значение 0.0001.
  • Объёмы нормализуются по минимальному, максимальному и шаговому ограничению инструмента.
  • Состояние корзины хранится внутри стратегии; при закрытиях отправляются рыночные заявки BuyMarket / SellMarket.
  • В OnStarted автоматически вызывается StartProtection().

Особенности и ограничения

  • Предполагается мгновенное исполнение рыночных заявок, аналогично торговому терминалу MT5.
  • Для корректного расчёта целей требуются актуальные котировки bid/ask (данные Level1).
  • Стоп-лоссы из оригинального эксперта не восстанавливаются — закрытие полностью управляется логикой стратегии.
  • Мартингейл быстро увеличивает объём позиций, поэтому необходим строгий риск-менеджмент.

Детали конвертации

  • Формулы усреднения и перераспределения объёмов повторяют исходный код.
  • Выбор лучших/худших ордеров реализован через отслеживание максимальной и минимальной цены входа в каждой стороне.
  • Вся логика работает внутри подписки на свечи и использует только высокоуровневые методы StockSharp.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// TugbaGold strategy: candle direction + EMA trend filter with martingale-style averaging.
/// Buys on bullish candle above EMA, sells on bearish candle below EMA.
/// </summary>
public class TugbaGoldStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private bool _wasBullishSignal;
	private bool _hasPrevSignal;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }

	public TugbaGoldStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasBullishSignal = false;
		_hasPrevSignal = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_wasBullishSignal = false;
		_hasPrevSignal = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaValue)
	{
		if (candle.State != CandleStates.Finished) return;

		var bullish = candle.ClosePrice > candle.OpenPrice;
		var bearish = candle.ClosePrice < candle.OpenPrice;
		var bullishSignal = bullish && candle.ClosePrice > emaValue;
		var bearishSignal = bearish && candle.ClosePrice < emaValue;
		var crossedUp = bullishSignal && (!_hasPrevSignal || !_wasBullishSignal);
		var crossedDown = bearishSignal && (!_hasPrevSignal || _wasBullishSignal);

		if (crossedUp && Position <= 0)
			BuyMarket();
		else if (crossedDown && Position >= 0)
			SellMarket();

		if (bullishSignal || bearishSignal)
		{
			_wasBullishSignal = bullishSignal;
			_hasPrevSignal = true;
		}
	}
}