Открыть на GitHub

Стратегия Alli Heik

Стратегия Alli Heik — это конвертация советника MetaTrader 5 «AlliHeik». Она торгует Heiken Ashi Smoothed Oscillator (HASO), изначально созданным mladen. Индикатор строит пользовательские свечи Heiken Ashi: сначала сглаживает исходные цены открытия, максимума, минимума и закрытия выбранной скользящей средней, затем выполняет дополнительное сглаживание средней точки Heiken Ashi и вычисляет разность между соседними сглаженными значениями. Скользящая средняя от этой разности формирует сигнальную линию.

Сигналы принимаются по пересечению осциллятора и сигнальной линии на полностью закрытых свечах. В стратегии доступны режим разворота сигналов, автоматическое закрытие встречных позиций, фиксированные стоп-лосс и тейк-профит, а также трейлинг-стоп, повторяющий пошаговую логику оригинальной версии MetaTrader.

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

  1. Подготовка индикатора
    • Предварительно сгладить данные OHLC с помощью SMA, EMA, SMMA или LWMA.
    • Построить свечи Heiken Ashi по сглаженным данным и усреднить открытие/закрытие, чтобы получить центральную точку.
    • Повторно сгладить центральную точку и вычислить осциллятор как разницу между текущим и предыдущим сглаженным значением.
    • Сгладить осциллятор выбранной скользящей средней, формируя сигнальную линию.
  2. Условия входа
    • Обычный режим: открыть лонг, когда осциллятор пересекает сигнальную линию сверху вниз, и открыть шорт, когда он пересекает её снизу вверх (точное воспроизведение логики MQL).
    • Режим разворота: условия для лонгов и шортов меняются местами.
    • Сигналы обрабатываются только после закрытия свечи. При включённой опции позиция противоположного направления закрывается перед открытием нового ордера.
  3. Выход из позиции
    • Значения стоп-лосса и тейк-профита задаются в пунктах и переводятся в цену с учётом шага цены и точности инструмента.
    • Трейлинг-стоп активируется, когда цена проходит в прибыль TrailingStop + TrailingStep пунктов. Затем стоп переносится на текущая цена − TrailingStop для лонга (или текущая цена + TrailingStop для шорта) и сдвигается только если новое значение минимум на TrailingStep пунктов дальше предыдущего.
    • При касании ценой заданного стопа или цели позиция закрывается вручную.

Параметры

  • Volume – торговый объём в лотах.
  • Stop Loss (pips) – расстояние защитного стопа; 0 отключает стоп-лосс.
  • Take Profit (pips) – расстояние тейк-профита; 0 отключает тейк-профит.
  • Trailing Stop (pips) – расстояние трейлинг-стопа; 0 отключает трейлинг.
  • Trailing Step (pips) – минимальный прогресс цены сверх трейлинг-стопа перед его переносом (обязательно положительный при активном трейлинге).
  • Reverse Signals – инвертировать направления входов по пересечениям.
  • Close Opposite – закрывать позицию противоположного направления перед открытием новой сделки.
  • Pre Smooth Period / Method – период и тип скользящей средней для предварительного сглаживания OHLC.
  • Post Smooth Period / Method – параметры сглаживания средней точки Heiken Ashi.
  • Signal Period / Method – параметры сглаживания сигнальной линии осциллятора.
  • Candle Type – тип свечей, используемых в расчётах (по умолчанию таймфрейм 15 минут).

Особенности реализации

  • Конвертация полностью воспроизводит Heiken Ashi Smoothed Oscillator с помощью стандартных индикаторов StockSharp (SMA, EMA, SMMA, LWMA) для последовательного сглаживания цен, построения Heiken Ashi и вычисления осциллятора.
  • Перевод значений в пунктах в абсолютную цену выполняется с учётом шага цены и количества знаков, аналогично обработке 3/5 знаков в MetaTrader.
  • Проверка стопов, целей и шагового трейлинг-стопа выполняется на каждой закрывшейся свече, что соответствует поведению оригинального советника.
  • Сигналы учитываются только после накопления достаточного количества данных для всех индикаторов.

Python-реализация в данной папке отсутствует.

namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Alli Heik strategy.
/// Uses Heikin Ashi candle patterns with EMA filter for trend following.
/// Buys on bullish HA candles when above EMA, sells on bearish HA candles when below EMA.
/// </summary>
public class AlliHeikStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal _prevHaOpen;
	private decimal _prevHaClose;
	private bool _initialized;

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

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

	public AlliHeikStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Source candles for the strategy", "General");

		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "Trend filter EMA period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHaOpen = 0m;
		_prevHaClose = 0m;
		_initialized = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevHaOpen = 0;
		_prevHaClose = 0;
		_initialized = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, OnProcess)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		// Calculate Heikin Ashi values
		decimal haClose = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 4m;
		decimal haOpen;

		if (!_initialized)
		{
			haOpen = (candle.OpenPrice + candle.ClosePrice) / 2m;
			_initialized = true;
		}
		else
		{
			haOpen = (_prevHaOpen + _prevHaClose) / 2m;
		}

		var haBullish = haClose > haOpen;
		var haBearish = haClose < haOpen;
		var prevHaBullish = _prevHaClose > _prevHaOpen;
		var prevHaBearish = _prevHaClose < _prevHaOpen;

		// Buy only on a bearish-to-bullish HA flip confirmed by the EMA filter.
		if (haBullish && prevHaBearish && candle.ClosePrice > emaValue && Position <= 0)
		{
			BuyMarket();
		}
		// Sell only on a bullish-to-bearish HA flip confirmed by the EMA filter.
		else if (haBearish && prevHaBullish && candle.ClosePrice < emaValue && Position >= 0)
		{
			SellMarket();
		}

		_prevHaOpen = haOpen;
		_prevHaClose = haClose;
	}
}