GitHub で見る

ValidateMe 戦略

概要

ValidateMe 戦略は、元の MQL4 エキスパート アドバイザーから基本的な検証フレームワークを移植します。このロジックは、資金の利用可能性を確認し、ストップロスとテイクプロフィットの距離が為替の制約を尊重していることを確認し、選択した方向で単一の成行注文を発行することに重点を置いています。この戦略は取引執行イベントを継続的に監視し、ポジションまたはアクティブな注文が存在しない場合にのみ新しいポジションをオープンします。

取引ロジック

  1. この戦略は、構成された証券のティック データをサブスクライブします。
  2. 戦略がオンラインで形成され、取引が許可されている場合、未決済のポジションやアクティブな注文が存在しないことが確認されます。
  3. 次に、定義されたロットサイズを使用して、設定された方向 (買いまたは売り) に成行注文を送信します。
  4. 保護モジュールは、ピップ距離から計算されたテイクプロフィット注文とストップロス注文を即座に添付し、ブローカーのストップレベル(端数価格に合わせて調整)への準拠を保証します。
  5. ポジションがクローズされると、ストラテジーは次のティックを待機し、新しい注文を送信する前に検証を繰り返します。

パラメーター

パラメータ 説明
利益確定 (pips) エントリー価格から利益確定までの距離 (pips)。ゼロより大きくなければなりません。
ストップロス (pips) エントリー価格からストップロスまでの距離 (pips)。ゼロより大きくなければなりません。
たくさん すべての成行注文に使用されるロットの取引量。
方向 成行注文の方向 (買いまたは売り)。

リスク管理

  • この戦略では、絶対オフセットを指定した StartProtection を使用して、テイクプロフィット注文とストップロス注文の両方を登録します。
  • ピップサイズは、MetaTrader の動作を模倣するために証券価格ステップと小数精度から計算されます (5 桁と 3 桁のシンボルは 10 倍のポイント サイズを使用します)。
  • この戦略は、アクティブな既存の注文がない場合にのみ新しい注文を発行し、注文の重複を回避します。

使用上の注意

  • ストラテジーを証券に添付し、希望の量と方向を設定します。
  • ブローカーの要件に従って、テイクプロフィットとストップロスの距離をピップ単位で設定します。
  • この戦略はインジケーターに依存せず、完全な取引システムではなく検証フレームワークとして意図されています。
  • 必要に応じて、ポートフォリオのリスク管理(最大ドローダウンなど)を外部で組み合わせることができます。
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// ValidateMe strategy: RSI crossover at oversold/overbought levels.
/// Buys when RSI crosses above 30, sells when RSI crosses below 70.
/// </summary>
public class ValidateMeStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _period;

	private decimal _prevRsi;
	private bool _hasPrev;

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

	public ValidateMeStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_period = Param(nameof(Period), 14)
			.SetGreaterThanZero()
			.SetDisplay("Period", "RSI period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		var rsi = new RelativeStrengthIndex { Length = Period };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
	}

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

		if (_hasPrev)
		{
			if (_prevRsi < 30 && rsiValue >= 30 && Position <= 0)
				BuyMarket();
			else if (_prevRsi > 70 && rsiValue <= 70 && Position >= 0)
				SellMarket();
		}

		_prevRsi = rsiValue;
		_hasPrev = true;
	}
}