GitHub で見る

手動取引軽量ユーティリティパネル戦略

概要

手動取引軽量ユーティリティ パネル戦略は、StockSharp の高レベル戦略 API を使用した MT4 の「手動取引軽量ユーティリティ」パネルの動作を複製します。戦略パラメーターと同じインタラクティブなコントロールを公開するため、オペレーターはカスタム チャート オブジェクトに依存せずに、成行注文、指値注文、逆指値注文の切り替え、自動価格計算の調整、出来高管理の構成、リスク管理の付加を行うことができます。

この戦略は裁量取引向けに設計されています。注文は、UI で Send Buy Order または Send Sell Order パラメータを変更することで手動でトリガーされます。すべてのコマンドは即座に認識され、同時にこの戦略により、自動価格提案やリスクレベルなどのすべての計算がリアルタイムの市場データと同期されます。

主な特長

  • 手動注文ディスパッチ。成行注文、指値注文、逆指値注文をサポートしており、買い手側と売り手側の両方に対応します。
  • 自動価格提案 MT4 パネル ロジックを反映し、最新の買い/売りストリームから提案された指値または逆指値を更新します。
  • オプションの手動価格モード。オペレーターは機器のステップ サイズを考慮しながら希望のトリガー レベルを入力できます。
  • ロット制御スイッチが有効になっている場合、グローバル ロット サイズと個別の売買数量による 数量管理
  • 統合されたストップロスおよびテイクプロフィット管理は、MT4 上の注文に関連付けられた保護をエミュレートするために戦略レイヤーに実装されています。
  • 詳細なフィードバック パラメータを介して、双方の最新の計算されたエントリ レベルを常に反映します。

変換メモ

  • MT4 チャート オブジェクト (ボタン、ラベル、編集ボックス) は、Hydra/ターミナルで簡単にアクセスできるように、論理セクションにグループ化された戦略パラメーターに置き換えられます。
  • プロテクティブ ストップとターゲットは、StockSharp が MT4 と同じ方法で未決注文に埋め込まないため、ライブ市場価格を観察することによって内部的に処理されます。
  • ポイントで表される価格オフセットは商品メタデータ (PriceStep および VolumeStep) を再利用するため、リミットとストップは常に為替制約を尊重します。

使用法

  1. Hydra または Terminal で戦略を証券とポートフォリオに添付します。
  2. デフォルトのロットサイズ、リスクパラメータ、価格オフセットを設定します。
  3. 必要に応じて、Lot Control を有効にして、買いボタンと売りボタンの独立した数量を維持します。
  4. 注文タイプ (市場、保留中の指値、または保留中のストップ) と、トリガー価格を市場に従うか手動のままにするかを選択します。
  5. 準備ができたら、Send Buy Order または Send Sell Ordertrue に切り替えます。この戦略は、対応する注文を送信し、処理が完了するとフラグを false にリセットします。
  6. プロテクションマネージャーは、実行されたエントリー価格から計算された設定されたストップロスまたはテイクプロフィットレベルでオープンポジションをクローズします。

ファイル

  • CS/ManualTradingLightweightUtilityPanelStrategy.cs – 戦略の C# 実装。
  • README.md – 英語のドキュメント (このファイル)。
  • README_zh.md – 簡体字中国語のドキュメント。
  • README_ru.md – ロシア語のドキュメント。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Manual Trading Panel strategy: SMA mean reversion with RSI filter.
/// Buys when close is below SMA and RSI is oversold, sells when above and overbought.
/// </summary>
public class ManualTradingLightweightUtilityPanelStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public ManualTradingLightweightUtilityPanelStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("SMA Period", "SMA period", "Indicators");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 8)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candlesSinceTrade = SignalCooldownCandles;
		var sma = new SimpleMovingAverage { Length = SmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(sma, rsi, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		var close = candle.ClosePrice;

		if (close < sma && rsi < 35 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			BuyMarket();
			_candlesSinceTrade = 0;
		}
		else if (close > sma && rsi > 65 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			SellMarket();
			_candlesSinceTrade = 0;
		}
	}
}