Открыть на GitHub

Стратегия OHLC Check

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

Стратегия OHLC Check повторяет логику классического советника MetaTrader, который анализирует структуру свечи по её значениям Open, High, Low и Close. Алгоритм оценивает тело свечи с настраиваемым сдвигом по истории и открывает позицию в направлении этого тела, при необходимости инвертируя сигнал. Это простая ценовая стратегия без использования индикаторов.

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

  1. Стратегия подписывается на выбранный таймфрейм и ждёт завершения свечи перед обработкой данных.
  2. После закрытия свечи сохраняются цены открытия и закрытия, чтобы параметр SignalShift мог ссылаться на более старые бары.
  3. Если тело свечи бычье (закрытие выше открытия), формируется сигнал на покупку. Медвежье тело (закрытие ниже открытия) создаёт сигнал на продажу. При равенстве Open и Close сделки не открываются.
  4. Флаг ReverseSignals позволяет инвертировать направление, полностью воспроизводя режим реверсной торговли исходного эксперта.
  5. При отсутствии позиции стратегия пытается открыть рыночный ордер в сторону сигнала, если текущий спред не превышает порог SpreadLimitPips. Спред контролируется через поток стакана.
  6. Если позиция уже существует, противоположный сигнал закрывает её вместо разворота, что соответствует поведению в MQL-версии.
  7. При запуске активируются защитные стоп-лосс и тейк-профит, расстояние до которых задаётся в пунктах и переводится в шаг цены инструмента.

Параметры

Параметр Значение по умолчанию Описание
CandleType Таймфрейм 5 минут Источник свечных данных для оценки тела.
StopLossPips 50 Стоп-лосс в пунктах; значение 0 отключает стоп.
TakeProfitPips 100 Тейк-профит в пунктах; значение 0 отключает цель.
ReverseSignals false Инвертирует направление сигналов.
SpreadLimitPips 1 Максимальный допустимый спред в пунктах при открытии позиции.
SignalShift 1 Количество завершённых свечей назад для расчёта сигнала (1 = предыдущая свеча).
OrderVolume 1 Объём заявки при открытии позиции.

Рекомендации по использованию

  • Для пересчёта пунктов в цену используется информация инструмента. Если у инструмента 3 или 5 знаков после запятой, автоматически применяется корректировка на десять пунктов.
  • Для проверки спреда необходим поток заявок (стакан). При отсутствии котировок bid/ask открытие новых сделок будет пропущено.
  • Защитные стопы устанавливаются один раз при старте стратегии. Изменение параметров после запуска требует перезапуска для применения новых значений.
  • Стратегия реагирует только на тело свечи и полностью игнорирует значения High и Low, как и оригинальная MQL-реализация.

Порядок запуска

  1. Подключите стратегию к инструменту, по которому доступны свечи и стакан заявок.
  2. Настройте параметры: таймфрейм, размеры стопов и тейк-профита, а также объём позиции.
  3. Запустите стратегию — она начнёт работу со следующей закрывшейся свечи.
  4. Следите за журналом: там будут отражаться отказы по спреду и исполненные сделки. При необходимости корректируйте параметры.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// OHLC check strategy. Trades based on candle structure (bullish/bearish body).
/// </summary>
public class OhlcCheckStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _confirmBars;

	private int _bullCount;
	private int _bearCount;

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

	public int ConfirmBars
	{
		get => _confirmBars.Value;
		set => _confirmBars.Value = value;
	}

	public OhlcCheckStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_confirmBars = Param(nameof(ConfirmBars), 3)
			.SetGreaterThanZero()
			.SetDisplay("Confirm Bars", "Consecutive candles to confirm direction", "Trading");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_bullCount = 0;
		_bearCount = 0;
	}

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

		_bullCount = 0;
		_bearCount = 0;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (candle.ClosePrice > candle.OpenPrice)
		{
			_bullCount++;
			_bearCount = 0;
		}
		else if (candle.ClosePrice < candle.OpenPrice)
		{
			_bearCount++;
			_bullCount = 0;
		}

		// Consecutive bullish candles → buy
		if (_bullCount >= ConfirmBars && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
			_bullCount = 0;
		}
		// Consecutive bearish candles → sell
		else if (_bearCount >= ConfirmBars && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
			_bearCount = 0;
		}
	}
}