GitHub で見る

Auto Trading Publish戦略

概要

この戦略は、MetaTrader 4のユーティリティ**「Auto Trading Publish」**をStockSharpへ移植したものです。成行注文を送信するのではなく、いつ取引を許可するかの制御に焦点を当てます。ローソク足購読で市場時計を監視し、設定された開始または停止時刻に達するとAutoTradingActiveフラグを切り替えます。このフラグは、MT4の「AutoTrading」ボタンをプログラムで切り替えていた元ユーティリティの動作を反映します。

取引ロジック

  • 軽量なローソク足ストリーム(既定は1分足)を購読し、取引がなくても市場時刻を追跡します。
  • 確定ローソク足が設定されたStartHourを示したら、AutoTradingActiveフラグを有効にしてイベントをログに記録します。
  • 確定ローソク足が設定されたStopHourを示したら、AutoTradingActiveフラグを無効にしてイベントをログに記録します。
  • 同じ時間内の重複切り替えを抑制し、その時間に複数のローソク足やティックが届いてもログがあふれないようにします。

パラメーター

パラメーター 説明
StartHour 自動取引を有効にする1日の時刻(0-23)。
StopHour 自動取引を無効にする1日の時刻(0-23)。
CandleType 市場時計を確認するための時間軸。小さい足ほど速く反応します。

使用上の注意

  • 戦略は注文を送信しません。ほかの戦略やコントロールパネルが取引送信の判断に使えるAutoTradingActiveプロパティだけを公開します。
  • 開始時刻と停止時刻が同じ場合、停止イベントが開始イベントの後に実行され、取引は無効のままになります。これは元のエキスパートアドバイザーと同じです。
  • 必要な切り替え速度に合うローソク足時間軸を選んでください。1分足は応答性とリソース使用の良いバランスです。

MetaTrader版との差異

  • MT4はWindowsメッセージでプラットフォーム全体のボタンを切り替えていました。StockSharpは代わりに戦略レベルのフラグを公開し、複雑な構成への統合を容易にします。
  • StockSharp移植版は完全に高レベルAPI内で動作し、低レベルメッセージフックなしでチャートや他の補助戦略と簡単に組み合わせられます。
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Auto Trading Publish strategy: SMA crossover + RSI confirmation.
/// Buys when close crosses above SMA and RSI is below 40.
/// Sells when close crosses below SMA and RSI is above 60.
/// </summary>
public class AutoTradingPublishStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;

	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 AutoTradingPublishStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).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");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var sma = new SimpleMovingAverage { Length = SmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		decimal? prevClose = null;
		decimal? prevSma = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, rsi, (candle, smaVal, rsiVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var close = candle.ClosePrice;

				if (prevClose.HasValue && prevSma.HasValue)
				{
					var crossUp = prevClose.Value <= prevSma.Value && close > smaVal;
					var crossDown = prevClose.Value >= prevSma.Value && close < smaVal;

					if (crossUp && rsiVal < 55m && Position <= 0)
						BuyMarket();
					else if (crossDown && rsiVal > 45m && Position >= 0)
						SellMarket();
				}

				prevClose = close;
				prevSma = smaVal;
			})
			.Start();

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