GitHub で見る

SpectrAnalysis WPR戦略

この戦略は、MQL5エキスパート Exp_i-SpectrAnalysis_WPR から変換されました。 Williams %Rインジケーターの方向を分析し、インジケーターの転換に従ってポジションをオープン/クローズします。

ロジック

  1. 選択した時間軸のローソク足を購読する。
  2. 設定した期間でWilliams %Rを計算する。
  3. 最新の2つのインジケーター値を保持して上向きまたは下向きの方向を検出する。
  4. インジケーターが上向きに転換しロングエントリーが許可されている場合:
    • 有効な場合はショートポジションをクローズ。
    • 新しいロングポジションをオープン。
  5. インジケーターが下向きに転換しショートエントリーが許可されている場合:
    • 有効な場合はロングポジションをクローズ。
    • 新しいショートポジションをオープン。

完成したローソク足のみが処理されます。戦略は複雑な履歴クエリを使用せず、高レベルAPIバインディングに依存します。

パラメーター

名前 説明 デフォルト
Candle Type 計算に使用するローソク足の時間軸 4h
WPR Period Williams %Rインジケーターの期間 13
Allow Long Entry ロングポジションのオープンを許可 true
Allow Short Entry ショートポジションのオープンを許可 true
Allow Long Exit ロングポジションのクローズを許可 true
Allow Short Exit ショートポジションのクローズを許可 true

注意事項

元のMQLバージョンはWilliams %Rの出力にスペクトル分析を適用していました。 このC#変換では標準のWilliams %Rインジケーターを使用し、最近のインジケーター値を追跡することでシグナルロジックを再現しています。

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;

/// <summary>
/// Strategy based on Williams %R trend direction.
/// </summary>
public class SpectrAnalysisWprStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _wprPeriod;
	private readonly StrategyParam<bool> _buyPosOpen;
	private readonly StrategyParam<bool> _sellPosOpen;
	private readonly StrategyParam<bool> _buyPosClose;
	private readonly StrategyParam<bool> _sellPosClose;

	private decimal? _prev;
	private decimal? _prev2;

	/// <summary>
	/// Candle type for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Williams %R period.
	/// </summary>
	public int WprPeriod
	{
		get => _wprPeriod.Value;
		set => _wprPeriod.Value = value;
	}

	/// <summary>
	/// Allow opening long positions.
	/// </summary>
	public bool BuyPosOpen
	{
		get => _buyPosOpen.Value;
		set => _buyPosOpen.Value = value;
	}

	/// <summary>
	/// Allow opening short positions.
	/// </summary>
	public bool SellPosOpen
	{
		get => _sellPosOpen.Value;
		set => _sellPosOpen.Value = value;
	}

	/// <summary>
	/// Allow closing long positions.
	/// </summary>
	public bool BuyPosClose
	{
		get => _buyPosClose.Value;
		set => _buyPosClose.Value = value;
	}

	/// <summary>
	/// Allow closing short positions.
	/// </summary>
	public bool SellPosClose
	{
		get => _sellPosClose.Value;
		set => _sellPosClose.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the strategy.
	/// </summary>
	public SpectrAnalysisWprStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for indicator", "General");
		_wprPeriod = Param(nameof(WprPeriod), 13)
			.SetGreaterThanZero()
			.SetDisplay("WPR Period", "Williams %R period", "Indicator");
		_buyPosOpen = Param(nameof(BuyPosOpen), true)
			.SetDisplay("Allow Long Entry", "Enable long position opening", "Trading");
		_sellPosOpen = Param(nameof(SellPosOpen), true)
			.SetDisplay("Allow Short Entry", "Enable short position opening", "Trading");
		_buyPosClose = Param(nameof(BuyPosClose), true)
			.SetDisplay("Allow Long Exit", "Enable closing of long positions", "Trading");
		_sellPosClose = Param(nameof(SellPosClose), true)
			.SetDisplay("Allow Short Exit", "Enable closing of short positions", "Trading");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, CandleType);
	}

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

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

		_prev = null;
		_prev2 = null;

		var wpr = new WilliamsR { Length = WprPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(wpr, ProcessCandle).Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal wprValue)
	{
		if (candle.State != CandleStates.Finished || !IsFormedAndOnlineAndAllowTrading())
			return;

		if (_prev is null || _prev2 is null)
		{
			_prev2 = _prev;
			_prev = wprValue;
			return;
		}

		// Upward direction detected (WPR was falling, now turning up)
		if (_prev < _prev2 && wprValue >= _prev)
		{
			if (BuyPosOpen && Position <= 0)
				BuyMarket(Position < 0 ? Volume + Math.Abs(Position) : Volume);
			else if (SellPosClose && Position < 0)
				BuyMarket(Math.Abs(Position));
		}
		// Downward direction detected (WPR was rising, now turning down)
		else if (_prev > _prev2 && wprValue <= _prev)
		{
			if (SellPosOpen && Position >= 0)
				SellMarket(Position > 0 ? Volume + Position : Volume);
			else if (BuyPosClose && Position > 0)
				SellMarket(Position);
		}

		_prev2 = _prev;
		_prev = wprValue;
	}
}