Открыть на GitHub

Стратегия Heiken Ashi Smoothed MTF

Обзор

Стратегия Heiken Ashi Smoothed MTF — это порт советника "HASNEWJ" с платформы MetaTrader. Она заново строит сглаженные свечи Heiken Ashi на шести таймфреймах (M1, M5, M15, M30, H1, H4) и ждёт, пока старшие интервалы полностью совпадут по направлению. Сделка открывается, когда поток M5 показывает свежую коррекцию, а более длинные временные рамки продолжают демонстрировать сильный бычий или медвежий тренд. Ручные стоп-лосс и тейк-профит повторяют поведение оригинального EA, включая автоматическое увеличение стопа после убыточной сделки.

Индикаторы и данные

  • Сглаженные свечи Heiken Ashi на таймфреймах M1, M5, M15, M30, H1 и H4.
    • Первый этап сглаживания применяет настраиваемое скользящее среднее к исходным значениям OHLC.
    • Второй этап сглаживает промежуточные значения открытия и закрытия Heiken Ashi ещё одним скользящим средним.
  • Счётчики направлений, которые показывают, сколько обновлений M1 каждый таймфрейм оставался бычьим или медвежьим.
  • Цена закрытия M1 для проверки условий по стоп-лоссу и тейк-профиту.

Логика входа

  1. При закрытии каждой свечи обновлять направление сглаженного Heiken Ashi на соответствующем таймфрейме.
  2. После закрытия M1 увеличивать или сбрасывать счётчики бычьих/медвежьих состояний в зависимости от текущего направления на каждом таймфрейме.
  3. Условия для покупки:
    • Сглаженный Heiken Ashi на M5 бычий и счётчик бычьих обновлений меньше MaxM5TrendLength (по умолчанию 10).
    • Сглаженный Heiken Ashi на M15 бычий и счётчик бычьих обновлений превышает MinM15TrendLength (по умолчанию 200).
    • Сглаженные свечи на M30, H1 и H4 также бычьи.
    • В настоящий момент нет длинной позиции (короткая позиция может быть перевёрнута).
  4. Условия для продажи:
    • Сглаженный Heiken Ashi на M5 медвежий и счётчик медвежьих обновлений меньше MaxM5TrendLength.
    • Сглаженный Heiken Ashi на M15 медвежий и счётчик медвежьих обновлений превышает MinM15TrendLength.
    • Сглаженные свечи на M30, H1 и H4 медвежьи.
    • Нет открытой короткой позиции (длинная позиция будет закрыта или перевёрнута).
  5. Объём рыночного ордера равен TradeVolume плюс модуль текущей позиции противоположного направления, чтобы переворот закрывал прежнюю сделку.

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

  • На каждом закрытии M1 рассчитывается ручной стоп-лосс и тейк-профит с использованием Security.PriceStep.
  • Позиция закрывается по тейк-профиту, если цена проходит TakeProfitPoints шагов в прибыльную сторону.
  • Позиция закрывается по стоп-лоссу, если цена проходит StopLossPoints шагов против позиции.
  • После убыточной сделки следующий вход расширяет стоп-лосс на ExtraStopLossPoints шагов, имитируя флаг fail из оригинального советника.
  • Объём сделки фиксируется параметром TradeVolume; стратегия не наращивает позицию, кроме случаев переворота.

Параметры

Имя Описание Значение по умолчанию
TradeVolume Базовый объём рыночных ордеров 0.1
TakeProfitPoints Дистанция тейк-профита в ценовых шагах 20
StopLossPoints Дистанция стоп-лосса в ценовых шагах 500
ExtraStopLossPoints Дополнительные шаги стоп-лосса после убыточной сделки 5
FirstMaPeriod Период первого сглаживающего скользящего среднего 6
FirstMaMethod Тип первого скользящего среднего (Simple, Exponential, Smoothed, LinearWeighted) Smoothed
SecondMaPeriod Период второго сглаживающего скользящего среднего 2
SecondMaMethod Тип второго скользящего среднего LinearWeighted
MaxM5TrendLength Максимальное число обновлений M5, разрешающее вход на откате 10
MinM15TrendLength Минимальное число обновлений M15, подтверждающее тренд 200
M1CandleType Тип данных для базовых минутных свечей TimeFrame(00:01:00)
M5CandleType Тип данных для свечей подтверждения на M5 TimeFrame(00:05:00)
M15CandleType Тип данных для свечей подтверждения на M15 TimeFrame(00:15:00)
M30CandleType Тип данных для свечей подтверждения на M30 TimeFrame(00:30:00)
H1CandleType Тип данных для свечей подтверждения на H1 TimeFrame(01:00:00)
H4CandleType Тип данных для свечей подтверждения на H4 TimeFrame(04:00:00)

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

  • Счётчики направлений обновляются на закрытии каждой M1 свечи, что приблизительно воспроизводит тиковые счётчики MetaTrader, оставаясь при этом в рамках свечной модели.
  • Убедитесь, что для инструмента задан Security.PriceStep; если его нет, стратегия использует шаг 0.0001 при расчёте стопа и цели.
  • Оба этапа сглаживания строятся на скользящих средних. Подбор метода и периода для каждого этапа помогает адаптировать систему к разным уровням волатильности инструмента.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Heiken Ashi Smoothed MTF: EMA trend with RSI filter and ATR stops.
/// </summary>
public class HeikenAshiSmoothedMtfStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevClose;
	private decimal _entryPrice;

	public HeikenAshiSmoothedMtfStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_emaLength = Param(nameof(EmaLength), 20)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");
		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevClose = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0; _entryPrice = 0;
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, rsi, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		if (_prevClose == 0 || atrVal <= 0) { _prevClose = close; return; }

		if (Position > 0)
		{
			if (close < emaVal || close <= _entryPrice - atrVal * 1.5m || close >= _entryPrice + atrVal * 2.5m) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if (close > emaVal || close >= _entryPrice + atrVal * 1.5m || close <= _entryPrice - atrVal * 2.5m) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (close > emaVal && _prevClose <= emaVal && rsiVal > 50) { _entryPrice = close; BuyMarket(); }
			else if (close < emaVal && _prevClose >= emaVal && rsiVal < 50) { _entryPrice = close; SellMarket(); }
		}
		_prevClose = close;
	}
}