Открыть на GitHub

Стратегия FiboChannel Line

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

FiboChannel Line — это перенос советника MetaTrader «FIBOCHANNEL» на платформу StockSharp. Вместо анализа вручную нарисованных линий каналов стратегия использует индикаторы высокого уровня, сохраняя оригинальную идею: работать по направлению канала, следить за импульсами момента и фильтровать сделки по MACD.

Основные принципы:

  • Определять тренд с помощью пары линейно взвешенных скользящих средних (LWMA).
  • Отслеживать импульсы индикатора Momentum относительно нейтрального уровня 100.
  • Проверять согласованность линии MACD и сигнальной линии перед входом.
  • Оценивать направление канала через линейную регрессию вместо чтения графических объектов.
  • Применять встроенную защиту StartProtection для контроля риска.

По умолчанию стратегия использует 30-минутные свечи, но может работать на любом доступном таймфрейме.

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

  1. Фильтр тренда — когда быстрая LWMA выше медленной, рассматриваются только покупки; когда ниже — только продажи.
  2. Условие импульса — буфер из трёх последних значений Momentum должен содержать хотя бы одно значение, отклоняющееся от 100 больше, чем Momentum Threshold. Это повторяет многократную проверку импульса в MQL.
  3. Фильтр MACD — покупки выполняются, если линия MACD выше сигнальной, продажи — если ниже.
  4. Направление канала — линейная регрессия должна показывать наклон, превышающий Slope Threshold по модулю: положительный для покупок и отрицательный для продаж.
  5. Вход и разворот — при выполнении условий стратегия отменяет активные заявки и отправляет рыночный ордер объёмом Volume + |Position|, что позволяет быстро развернуться.
  6. Выход — если наклон канала или фильтр MACD перестаёт поддерживать открытую позицию, она закрывается после отмены заявок. Дополнительно включены процентные стоп-лосс, тейк-профит и ограничение просадки по капиталу через StartProtection.

Параметры

Параметр Описание Значение по умолчанию
Candle Type Тип свечей для расчётов. 30-минутные свечи
Fast LWMA Длина быстрой LWMA. 6
Slow LWMA Длина медленной LWMA. 85
Momentum Period Период индикатора Momentum. 14
Momentum Threshold Минимальное отклонение Momentum от 100. 0.3
Channel Length Число баров для линейной регрессии. 50
Slope Threshold Минимальный модуль наклона для подтверждения направления. 0.0
MACD Fast Период быстрой EMA в MACD. 12
MACD Slow Период медленной EMA в MACD. 26
MACD Signal Период сигнальной линии MACD. 9
Take Profit % Процентное расстояние тейк-профита. 2
Stop Loss % Процентное расстояние стоп-лосса. 1
Equity Risk % Максимально допустимая просадка по капиталу. 3

Диапазоны оптимизации параметров подобраны в соответствии с оригинальными настройками советника.

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

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

Отличия от версии MetaTrader

  • Чтение координат графических объектов заменено на работу с индикатором наклона линейной регрессии.
  • Вместо сложных блоков трала и перевода в безубыток используется единый механизм StartProtection.
  • Индикаторы реализованы через связки BindEx, что исключает ручной доступ к историям значений.
  • Логика оповещений по почте и push уведомлениям убрана — все события отражаются в логах StockSharp.

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

  1. Привяжите стратегию к нужным инструменту и портфелю, задайте объём заявок через свойство Volume и при необходимости скорректируйте параметры.
  2. Убедитесь, что для выбранного таймфрейма загружено достаточно исторических данных, иначе индикаторы не смогут сформироваться.
  3. Перед запуском на реальном счёте протестируйте стратегию на демо или в режиме малых объёмов, подбирая значения Momentum Threshold и параметров риска под волатильность инструмента.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

public class FiboChannelLineStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public FiboChannelLineStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}