Открыть на GitHub

Стратегия XCCI Histogram Vol Direct

Обзор

XCCI Histogram Vol Direct Strategy — портирование советника MQL5 Exp_XCCI_Histogram_Vol_Direct. Алгоритм умножает Commodity Channel Index (CCI) на объём, сглаживает обе серии выбранным типом скользящего среднего и анализирует знак наклона сглаженного осциллятора. Как только цвет гистограммы меняется, стратегия закрывает позиции против нового движения и открывает сделки в его сторону. Все расчёты выполняются только по завершённым свечам, поэтому поведение совпадает в тестере и в реальном времени.

Оригинальный эксперт использовал собственную библиотеку сглаживания, уровни на основе объёма и отложенное исполнение на следующей свече. Версия для StockSharp сохраняет параметры, подбирает ближайшие доступные индикаторы и реализует последовательность закрытия/открытия позиций через высокоуровневый API.

Режим рынка и идея

  • Нацелен на участки рынка, где всплески объёма сопровождают ускорение импульса.
  • Лучше всего работает на таймфреймах с явными колебаниями (по умолчанию 2-часовые свечи), но масштабируется от внутридневной до свинговой торговли.
  • Сигналы реагируют на смену знака наклона у сглаженного произведения CCI и объёма, поэтому индикатор ведёт себя как детектор разворотного импульса.

Индикаторы и последовательность обработки

  1. Commodity Channel Index (CCI) — рассчитывается по выбранному типу свечей с периодом CciPeriod.
  2. Источник объёмаTick или Real (в StockSharp оба варианта используют candle.TotalVolume, потому что количество тиков недоступно).
  3. Взвешенный осциллятор — произведение CCI на выбранный объём.
  4. Сглаживание — к взвешенному осциллятору и к чистому объёму применяется однотипное сглаживание длиной SmoothingLength:
    • Sma → SimpleMovingAverage
    • Ema → ExponentialMovingAverage
    • Smma → SmoothedMovingAverage
    • Lwma → WeightedMovingAverage
    • Jjma → JurikMovingAverage
    • Jurx → ZeroLagExponentialMovingAverage
    • Parabolic → ArnaudLegouxMovingAverage (фаза из параметра преобразуется в смещение ALMA)
    • T3 → TripleExponentialMovingAverage
    • Vidya → ExponentialMovingAverage (наиболее близкая замена)
    • Ama → KaufmanAdaptiveMovingAverage
  5. Окраска по направлению — сравнивается текущее сглаженное значение с предыдущим. Рост получает цвет 0 (бычий), снижение — 1 (медвежий), одинаковые значения наследуют предыдущий цвет, как в буфере исходного индикатора.
  6. Память сигналов — сохраняется история цветов, чтобы анализировать свечу SignalBar и предыдущую.

Торговые правила

Управление длинными позициями

  • Вход: если цвет сигнальной свечи 1 (медвежий), а предыдущей — 0 (бычий), открывается покупка при AllowLongEntries = true, если нет текущей длинной позиции. Объём ордера равен Volume + |Position|, что позволяет закрыть шорт перед новым лонгом.
  • Выход: если свеча до сигнальной окрашена в бычий цвет (0) и AllowShortExits = true, все короткие позиции закрываются, чтобы не идти против нового импульса.

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

  • Вход: если сигнальная свеча получила цвет 0 после 1, открывается шорт при AllowShortEntries = true и отсутствии текущей короткой позиции. Логика объёма идентична.
  • Выход: когда свеча до сигнальной медвежья (1) и AllowLongExits = true, длинная позиция закрывается.

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

  • StopLossPoints и TakeProfitPoints переводятся в цену через PriceStep инструмента и применяются через StartProtection.
  • Оба защитных уровня активируются для каждой сделки; установите параметр в 0, чтобы отключить отдельный уровень.

Параметры

Параметр Описание Значение по умолчанию
CciPeriod Период CCI. 14
Smoothing Тип сглаживания для произведения CCI и объёма. T3
SmoothingLength Длина скользящего среднего. 12
SmoothingPhase Фазовый параметр, используемый ALMA; сохранён для совместимости. 15
HighLevel2, HighLevel1, LowLevel1, LowLevel2 Множители порогов исходного индикатора (пригодны для визуализации). 100, 80, -80, -100
SignalBar Номер свечи назад, определяющий сигнал (0 = последняя закрытая). 1
AllowLongEntries / AllowShortEntries Разрешение на открытие позиций. true
AllowLongExits / AllowShortExits Разрешение на закрытие позиций противоположным сигналом. true
StopLossPoints Размер стоп-лосса в пунктах цены. 1000
TakeProfitPoints Размер тейк-профита в пунктах цены. 2000
VolumeSource Источник объёма (Tick или Real, оба используют свечной объём). Tick
CandleType Таймфрейм анализа. 2 часа

Последовательность обработки свечи

  1. Дождаться закрытия очередной свечи выбранного таймфрейма.
  2. Рассчитать CCI и умножить его на выбранный объём.
  3. Пропустить взвешенный CCI и чистый объём через одинаковые фильтры сглаживания.
  4. После формирования обоих фильтров определить новый цвет и обновить историю.
  5. Проанализировать цвета свечей SignalBar и SignalBar + 1, принять решение о закрытии текущей позиции и/или открытии новой.
  6. Применить защитные ордера согласно параметрам риска.

Практические рекомендации

  • Перед запуском задайте положительное значение Volume — оно определяет размер сделки.
  • Из-за отсутствия счётчика тиков в стандартных свечах StockSharp оба режима объёма используют TotalVolume. При необходимости точного тик-объёма используйте кастомные свечи.
  • Параметр SmoothingPhase влияет только на ALMA. Для остальных фильтров он игнорируется, как и в оригинальном индикаторе.
  • Множители HighLevel*/LowLevel* сохранены для совместимости. Их можно визуализировать, если построить сглаженный объём и умножить на эти коэффициенты.

Ограничения и отличия от MQL5

  • В библиотеке StockSharp отсутствуют точные аналоги VIDYA и Parabolic MA, поэтому используются EMA и ALMA. Характеристики близки, но не полностью совпадают с оригиналом.
  • Исполнение происходит на закрытии сигнальной свечи. В MQL5 использовалось смещение на начало следующей свечи (TimeShiftSec); при рынке с низкой задержкой результат эквивалентен.
  • Тиковый объём аппроксимируется общим объёмом свечи, поскольку количество тиков не передаётся в сообщениях свечей.

Начало работы

  1. Подключите стратегию к нужному инструменту, задайте Volume — количество лотов/контрактов на сделку.
  2. Выберите таймфрейм через CandleType (по умолчанию 2 часа).
  3. Настройте параметры сглаживания и риск-менеджмента под волатильность инструмента.
  4. Запустите в режиме теста/бумажной торговли, оцените график сглаженного осциллятора и при необходимости скорректируйте SignalBar.

Идеи для оптимизации

  • Совместно оптимизируйте CciPeriod и SmoothingLength, чтобы добиться нужной чувствительности.
  • Протестируйте значения SignalBar 0 и 1 для более раннего или более позднего реагирования.
  • Подберите значения StopLossPoints и TakeProfitPoints под средний диапазон (ATR) конкретного инструмента.
  • Используйте дополнительные фильтры тренда старшего таймфрейма, если требуется подтверждение направления.

Чек-лист безопасности

  • Убедитесь, что PriceStep и Volume соответствуют спецификации инструмента перед выходом на реальный рынок.
  • Контролируйте проскальзывание и при необходимости добавляйте внешние ограничения по риску.
  • Периодически проверяйте логи сделок, чтобы параметры разрешения направлений (Allow*) соответствовали текущей торговой гипотезе.
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>
/// XCCI Histogram Vol Direct strategy. Uses CCI zero-line crossover.
/// </summary>
public class XcciHistogramVolDirectStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private decimal? _prevCci;

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

	public XcciHistogramVolDirectStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14).SetGreaterThanZero().SetDisplay("CCI Period", "CCI lookback", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCci = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCci = null;
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(cci, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal cciVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevCci = cciVal; return; }
		if (_prevCci == null) { _prevCci = cciVal; return; }
		if (_prevCci.Value < 0m && cciVal >= 0m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevCci.Value > 0m && cciVal <= 0m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevCci = cciVal;
	}
}