GitHub で見る

高速 低速 RVI クロスオーバー戦略

概要

この戦略は、MetaTrader エキスパート アドバイザー _HPCS_FastSlowRVIsCrossOver_MT4_EA_V01_WE を複製します。設定された取引セッション中に相対活力指数 (RVI) のメインラインがシグナルラインを横切ったときに取引されます。キャンドルごとに 1 つの取引のみが許可され、戦略はオプションのストップロス、テイクプロフィット、およびピップで表されるトレーリングストップ距離をサポートします。

取引ロジック

  1. Candle Type パラメーターで選択された標準の時間ベースのローソク足を作成します。
  2. 構成された RVI 期間 と 4 期間の単純移動平均をシグナルラインとして使用して RVI を計算します。
  3. RVI がシグナルラインを上回ったら、ショートポジションを閉じ、ロングポジションにオープン/スケールします。
  4. RVI がシグナルラインを下回った場合、ロングポジションを閉じ、ショートポジションにオープン/スケールします。
  5. 開始時間停止時間の間隔外に表示される信号は無視します。
  6. 選択したリスクパラメータに従って保護注文を出します。トレーリング ストップは、StockSharp 保護エンジンによって管理されます。
  7. バーごとに 1 回だけ反応することで、同じローソク足での重複エントリーを避けます。

パラメーター

名前 説明
RVI期間 相対活力指数で使用されるバーの数。
利益確定 (pips) ピップス単位で測定されるオプションのテイクプロフィット距離。無効にするには、ゼロに設定します。
ストップロス (pips) ピップ単位で測定されるオプションのストップロス距離。無効にするには、ゼロに設定します。
トレーリングストップ (pips) オプションのトレーリングストップ距離 (ピップ単位)。末尾を無効にするには、ゼロに設定します。
トレーリングステップ (pips) トレーリングストップが強化される前に必要な最小限の有利な動き。トレーリングストップがアクティブな場合にのみ機能します。
ボリューム 各エントリで送信された注文量。
キャンドルタイプ 分析に使用される時間枠またはカスタムローソク足データタイプ。
開始時間 日次取引ウィンドウの開始 (包括的)。
時間停止 日次取引ウィンドウの終了 (限定)。

注意事項

  • ピップ サイズは、MetaTrader ポイントの処理に一致するセキュリティ ティック サイズに調整されます (5 桁および 3 桁のシンボルは 10 倍の乗数を使用します)。
  • OnStarted 内で StartProtection を呼び出して、保護命令と追跡管理を有効にします。
  • プロジェクト ガイドラインの要求に従って、ソース コード内のすべてのコメントは英語で書かれています。
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Fast and slow Relative Vigor Index crossover strategy.
/// Opens a long position when the RVI average line crosses above the signal line,
/// and opens a short position on the opposite crossover.
/// </summary>
public class FastSlowRviCrossoverStrategy : Strategy
{
	private readonly StrategyParam<int> _rviPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _previousAverage;
	private decimal? _previousSignal;

	public int RviPeriod
	{
		get => _rviPeriod.Value;
		set => _rviPeriod.Value = value;
	}

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

	public FastSlowRviCrossoverStrategy()
	{
		_rviPeriod = Param(nameof(RviPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("RVI Period", "Period for the Relative Vigor Index", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candles used for analysis", "General");
	}

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

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

		var rvi = new ExponentialMovingAverage { Length = RviPeriod };
		var signal = new ExponentialMovingAverage { Length = RviPeriod * 2 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rvi, signal, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal avgValue, decimal sigValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (_previousAverage.HasValue && _previousSignal.HasValue)
		{
			var longSignal = _previousAverage.Value <= _previousSignal.Value && avgValue > sigValue;
			var shortSignal = _previousAverage.Value >= _previousSignal.Value && avgValue < sigValue;

			if (longSignal && Position <= 0)
			{
				BuyMarket();
			}
			else if (shortSignal && Position >= 0)
			{
				SellMarket();
			}
		}

		_previousAverage = avgValue;
		_previousSignal = sigValue;
	}
}