Открыть на GitHub

Стратегия Grid Template

Обзор

Стратегия представляет собой порт MT4-советника Grid_Template на платформу StockSharp. Она строит симметричную сетку отложен ных стоп-заявок вокруг текущих цен Bid/Ask, поэтому может использоваться как самостоятельный шаблон пробоя либо как основа для д обавления собственных фильтров входа. После срабатывания или отмены всех заявок сетка формируется заново. Реализация сохраняет ф ормулу управления капиталом из оригинала и позволяет автоматически снимать «просроченные» заявки через заданное количество часов.

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

  • Подписка на поток Level1 позволяет постоянно отслеживать лучшие цены покупки и продажи, индикаторы не требуются.
  • При отсутствии позиции и активных заявок стратегия выставляет GridOrders покупок-stop выше Ask и GridOrders продаж-stop ниж е Bid.
  • Первая ступень сетки находится на расстоянии PriceDistancePips пунктов от цены, каждая следующая добавляет ещё GridStepPips пунктов.
  • Все ордера используют одинаковый объём (фиксированный либо рассчитанный по риск-проценту) и одинаковые значения стоп-лосса/тей к-профита.
  • Как только отложенный ордер исполняется, стратегия регистрирует соответствующие защитные заявки (SellStop/BuyStop и SellL imit/BuyLimit) — комментарии наследуются, что упрощает идентификацию.
  • Если ни одна заявка не сработала до истечения таймера, все оставшиеся ордера отменяются и сетка выставляется заново.

Управление капиталом

  • При выключенной опции UseMoneyManagement используется фиксированный объём StaticVolume.
  • При включении объём считается по формуле оригинала freeMargin * RiskPercent / 100000, затем округляется к ближайшему шагу об ъёма (VolumeStep) и ограничивается диапазоном VolumeMinVolumeMax. В качестве свободной маржи используется текущая стоимость портфеля.
  • Итоговый объём дополнительно нормализуется под требования площадки; если значение ниже минимального лота, ордер не отправляется .

Управление ордерами и риском

  • Buy Stop выставляются по формуле ask + PriceDistancePips + GridStepPips * level, Sell Stop зеркально от Bid.
  • Защитные заявки создаются только после исполнения входного ордера, что имитирует поведение MT4, где стоп и тейк принадлежат тем же тикетам.
  • Параметр PendingExpirationHours задаёт время жизни сетки. Ноль означает, что заявки будут ждать исполнения до ручной отмены.
  • После закрытия позиции до нуля стратегия отменяет все оставшиеся защитные заявки, чтобы начать следующий цикл с «чистого листа» .

Параметры

Параметр Описание
OrderComment Комментарий, присваиваемый всем ордерам сетки.
StaticVolume Фиксированный объём при выключенном управлении капиталом.
UseMoneyManagement Включает расчёт объёма по риск-проценту.
RiskPercent Процент риска, используемый в формуле объёма.
TakeProfitPips Расстояние до тейк-профита для каждой заявки.
StopLossPips Расстояние до стоп-лосса для каждой заявки.
PriceDistancePips Отступ от текущей цены до первой ступени сетки.
GridStepPips Прибавка расстояния между соседними уровнями.
GridOrders Количество заявок в каждом направлении.
PendingExpirationHours Время жизни сетки до автоотмены (часы).

Примечания

  • Шаблон не накладывает индикаторных ограничений. При необходимости логику можно расширить, переопределив TryPlaceGrid или доба вив собственные проверки перед выставлением сетки.
  • Защитные ордера реализованы отдельными заявками, поэтому при частичных исполнениях возможны отличия от MT4, где стопы и тейки х ранятся внутри тикета.
  • Перед запуском убедитесь, что величина пункта, вычисленная из PriceStep и Decimals, соответствует спецификации инструмента.
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// Grid Template strategy: places trades at regular grid intervals.
/// Buys when price drops by grid step, sells when price rises by grid step.
/// </summary>
public class GridTemplateStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<decimal> _gridStepPercent;

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

	public decimal GridStepPercent
	{
		get => _gridStepPercent.Value;
		set => _gridStepPercent.Value = value;
	}

	public GridTemplateStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_gridStepPercent = Param(nameof(GridStepPercent), 3.0m)
			.SetGreaterThanZero()
			.SetDisplay("Grid Step %", "Price change percentage for grid level", "Grid");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var sma = new SimpleMovingAverage { Length = 10 };

		decimal? lastTradePrice = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, (candle, smaVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;

				if (!lastTradePrice.HasValue)
				{
					lastTradePrice = close;
					return;
				}

				var step = lastTradePrice.Value * GridStepPercent / 100m;

				if (close <= lastTradePrice.Value - step)
				{
					BuyMarket();
					lastTradePrice = close;
				}
				else if (close >= lastTradePrice.Value + step)
				{
					SellMarket();
					lastTradePrice = close;
				}
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, sma);
			DrawOwnTrades(area);
		}
	}
}