Открыть на GitHub

Стратегия Exp KWAN NRP

Обзор

Стратегия Exp KWAN NRP воспроизводит оригинальный советник MetaTrader, объединяя стохастик, индекс относительной силы и индикатор Momentum в единое отношение. Полученное значение сглаживается настраиваемой скользящей средней, а наклон сглаженной линии определяет моменты открытия и закрытия позиций. Подход подходит для любых инструментов и таймфреймов и ориентирован на ловлю направленных движений во время смены импульса.

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

  1. Рассчитать отношение KWAN: перемножить значение линии %D стохастика и RSI и разделить на показания Momentum.
  2. Сгладить отношение выбранным типом скользящей средней (простая, экспоненциальная, сглаженная или взвешенная).
  3. Оценить наклон сглаженной линии на заданном смещении бара SignalBar.
  4. При развороте линии вверх открывать длинные позиции и закрывать короткие; при развороте вниз открывать короткие позиции и закрывать длинные.
  5. Дополнительно можно включить защиту Stop Loss и Take Profit в шагах цены для автоматического выхода при достижении заданного диапазона.

Торговые сигналы

  • Открытие лонга: сглаженное значение KWAN на сигнальном баре выше, чем на предыдущем баре, и разрешено открывать покупки.
  • Закрытие лонга: при наличии длинной позиции сглаженное значение разворачивается вниз и разрешено закрывать покупки.
  • Открытие шорта: сглаженное значение KWAN на сигнальном баре ниже, чем на предыдущем баре, и разрешено открывать продажи.
  • Закрытие шорта: при наличии короткой позиции сглаженное значение разворачивается вверх и разрешено закрывать продажи.

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

  • Используйте свойство стратегии Volume, чтобы задать базовый объём заявки. При смене направления открытая противоположная позиция закрывается автоматически.
  • Включите UseProtection, чтобы активировать стоп-лосс и тейк-профит, заданные в шагах цены. Защиты можно применять по отдельности или вместе.
  • Стратегия подписывается на свечи типа CandleType и торгует только по закрытию полностью сформированных свечей.

Параметры

Имя Описание Значение по умолчанию
CandleType Таймфрейм для расчёта индикаторов и оценки сигналов. Часовые свечи
KPeriod Период линии %K стохастика. 5
DPeriod Период линии %D стохастика. 3
SlowingPeriod Дополнительное сглаживание для линии %K. 3
RsiPeriod Период индикатора RSI. 14
MomentumPeriod Период индикатора Momentum. 14
SmoothingMethod Тип скользящей средней для сглаживания отношения KWAN (Simple, Exponential, Smoothed, Weighted). Simple
SmoothingLength Период сглаживающей скользящей средней. 3
SignalBar Смещение бара для оценки наклона (0 — текущая закрытая свеча). 1
EnableBuyEntries Разрешить открытие длинных позиций по бычьим сигналам. true
EnableSellEntries Разрешить открытие коротких позиций по медвежьим сигналам. true
EnableBuyExits Разрешить закрывать длинные позиции при появлении медвежьих сигналов. true
EnableSellExits Разрешить закрывать короткие позиции при появлении бычьих сигналов. true
UseProtection Включить защиту стоп-лосс/тейк-профит. true
StopLossSteps Расстояние стоп-лосса в шагах цены. 1000
TakeProfitSteps Расстояние тейк-профита в шагах цены. 2000

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

  • Если Momentum равен нулю, отношение KWAN становится нестабильным; стратегия пропускает такие бары, чтобы избежать деления на ноль.
  • Параметр SignalBar позволяет смещать сигналы для дополнительного подтверждения или синхронизации с историей.
  • При промышленной эксплуатации рекомендуется дополнять стратегию брокерскими лимитами и дополнительными фильтрами.
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Strategy replicating the Exp KWAN NRP expert advisor by combining RSI and Momentum signals.
/// Enters long when RSI crosses above 50 and momentum is positive,
/// enters short when RSI crosses below 50 and momentum is negative.
/// </summary>
public class ExpKwanNrpStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _momentumPeriod;

	private decimal _prevRsi;
	private decimal _prevMom;
	private bool _initialized;

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

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public int MomentumPeriod
	{
		get => _momentumPeriod.Value;
		set => _momentumPeriod.Value = value;
	}

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

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI length", "Indicators");

		_momentumPeriod = Param(nameof(MomentumPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Momentum Period", "Momentum length", "Indicators");
	}

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

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

		_prevRsi = 0;
		_prevMom = 0;
		_initialized = false;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var momentum = new Momentum { Length = MomentumPeriod };

		var subscription = SubscribeCandles(CandleType);

		subscription
			.Bind(rsi, momentum, (ICandleMessage candle, decimal rsiValue, decimal momValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (!_initialized)
				{
					_prevRsi = rsiValue;
					_prevMom = momValue;
					_initialized = true;
					return;
				}

				var rsiUp = rsiValue > _prevRsi;
				var rsiDown = rsiValue < _prevRsi;
				var momUp = momValue > _prevMom;
				var momDown = momValue < _prevMom;

				// Buy when both RSI and Momentum are turning up
				if (rsiUp && momUp && Position <= 0)
				{
					BuyMarket();
				}
				// Sell when both RSI and Momentum are turning down
				else if (rsiDown && momDown && Position >= 0)
				{
					SellMarket();
				}

				_prevRsi = rsiValue;
				_prevMom = momValue;
			})
			.Start();

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