GitHub で見る

AIS1 取引ロボット (MQL/8700 換算)

概要

AIS1 Trading Robot は、MQL/8700/AIS1.MQ4 の MetaTrader 4 Expert Advisor を C# に直接変換したものです。オリジナルのシステムは EURUSD の日次ブレイクアウト向けに調整されており、ストップ、ターゲット、トレーリングの計算にマルチタイムフレーム範囲を使用します。この StockSharp 実装は、レガシー ロボットの構造を保持しながら、すべての構成可能な要素を戦略パラメーターとして公開します。

取引ロジック

  • 時間枠
    • プライマリローソク足: エントリー条件、ストップロス、利食い距離の 1 日足。
    • セカンダリローソク足: 動的なトレーリングストップ計算用の 4 時間足。
  • エントリー条件
    • ロングブレイクアウト: 昨日の日足の終値はバーの中間点を上回っており、現在の売値は前の日の高値を突き抜けています。
    • ショートブレイクアウト: 昨日の日次終値は中間点を下回り、現在の入札は前日の日次安値を下回ります。
    • 一度にオープンできるポジションは 1 つだけです。現在の取引が終了するまで、反対のシグナルは無視されます。
  • 初期のリスクと報酬
    • ストップロス = 以前の毎日の高値/安値 ± StopFactor × daily range
    • テイクプロフィット = エントリー価格 ± TakeFactor × daily range
    • 両方のレベルは、ブローカーの停止距離の制約を考慮して、オプションの StopBufferTicks に対して検証されます。
  • トレーリングストップ
    • 最新の 4 時間足のローソク足の範囲に TrailFactor を掛けた値を使用します。
    • 追跡更新では、価格が既存のストップを少なくとも TrailStepMultiplier × spread 超えて移動し、構成されたバッファーによってターゲットから遠ざかることを必要とします。
    • ドローダウン保護は、資本が準備金のしきい値を下回ると、トレーリングアップデートを無効にします。
  • リスク管理
    • ロットサイズは、OrderReserve × equity をエントリーとストップの間の金銭的リスクで割ったものから算出されます。
    • ボリュームは交換制限 (MinVolumeMaxVolumeVolumeStep) にクランプされます。
    • 株式モニタリングは実行最大値を追跡し、株式がそのピークの AccountReserve - OrderReserve を下回ると新規エントリーをブロックします。
  • タイミング保護機能
    • アクション (エントリまたは後続の更新) は必須の 5 秒の一時停止によって区切られ、元の EA スロットルが複製されます。

パラメーター

パラメータ デフォルト 説明
AccountReserve 0.20 そのままにしておく必要がある資本の割合。許容ドローダウンを計算するために使用されます。
OrderReserve 0.04 各取引に割り当てられた資本の割合とポジションサイジングの基準。
PrimaryCandleType 毎日 ブレイクアウトロジックと静的ターゲットに使用されるローソク足タイプ。
SecondaryCandleType 4時間 トレーリング距離を導出するために使用されるローソク足のタイプ。
TakeFactor 0.8 利益確定に適用される日次レンジの乗数。
StopFactor 1.0 ストップロスに適用される日次範囲の乗数。
TrailFactor 5.0 トレーリングストップに適用される4時間範囲の乗数。
TrailStepMultiplier 1.0 新しいトレーリングストップが設定される前に価格をどれだけ前進させる必要があるかを制御するスプレッド乗数。
StopBufferTicks 0 ストップとターゲットの周囲に安全マージンとして追加の価格ステップが追加されました。

使用上の注意

  1. 戦略を開始する前に、必要な セキュリティ (デフォルトでは EURUSD) と ポートフォリオ を割り当てます。
  2. 毎日と 4 時間の両方のキャンドル ソースが利用可能であることを確認してください。そうしないと、ブレークアウト モジュールと後続モジュールはアクティブ化できません。
  3. この戦略は、オーダーブックをサブスクライブして、現在の買値/売値を取得します。デプスフィードのない市場では、最後に取引された価格がフォールバックとして使用されます。
  4. ポジションの決済は、ストップ条件またはターゲット条件が満たされたときに成行注文を通じて実行され、サーバー側で保護注文を変更した MetaTrader EA の動作と一致します。
  5. ドローダウン リミッター、一時停止タイマー、リスクサイジング ロジックはすべて、公開されたパラメーターを通じて調整して、ロボットをさまざまなブローカーや契約仕様に適応させることができます。

オリジナルとの相違点 MQL

  • 価格が保存されたレベルを超えると、保護的なストップとターゲットが手動のポジション決済によってエミュレートされます (MT4 は注文変更を通じてこれを処理しました)。
  • リスク変換は、Security オブジェクトの PriceStepStepPrice に依存します。このようなメタデータが欠落している場合、コードは 1:1 の通貨換算に戻るため、ユーザーは契約の仕様を再確認する必要があります。
  • 明確にするため、また StockSharp の最適化ツールとの統合を改善するために、広範なコメントとパラメータの説明が追加されました。

要件

  • StockSharp の高レベルの API は、キャンドルのサブスクリプションとオーダーブックのデータにアクセスできます。
  • 注文の発注とポートフォリオの評価のために適切に構成された取引接続。
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// AIS1 breakout strategy with ATR-based stops and trailing.
/// Trades breakouts above/below EMA with ATR-based risk management.
/// </summary>
public class Ais1TradingRobotStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<decimal> _takeFactor;
	private readonly StrategyParam<decimal> _stopFactor;

	private decimal _entryPrice;

	public Ais1TradingRobotStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for analysis.", "General");

		_emaLength = Param(nameof(EmaLength), 50)
			.SetDisplay("EMA Length", "Period for trend EMA.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 20)
			.SetDisplay("ATR Length", "Period for ATR.", "Indicators");

		_takeFactor = Param(nameof(TakeFactor), 3.0m)
			.SetDisplay("Take Factor", "ATR multiplier for take profit.", "Risk");

		_stopFactor = Param(nameof(StopFactor), 1.5m)
			.SetDisplay("Stop Factor", "ATR multiplier for stop loss.", "Risk");
	}

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

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	public decimal TakeFactor
	{
		get => _takeFactor.Value;
		set => _takeFactor.Value = value;
	}

	public decimal StopFactor
	{
		get => _stopFactor.Value;
		set => _stopFactor.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_entryPrice = 0;
	}

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

		_entryPrice = 0;

		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, atr, ProcessCandle)
			.Start();

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

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

		if (atrValue <= 0)
			return;

		var close = candle.ClosePrice;
		var takeDistance = atrValue * TakeFactor;
		var stopDistance = atrValue * StopFactor;

		// Position management with ATR-based stops
		if (Position > 0)
		{
			if (_entryPrice > 0)
			{
				if (close >= _entryPrice + takeDistance || close <= _entryPrice - stopDistance)
				{
					SellMarket();
				}
			}
		}
		else if (Position < 0)
		{
			if (_entryPrice > 0)
			{
				if (close <= _entryPrice - takeDistance || close >= _entryPrice + stopDistance)
				{
					BuyMarket();
				}
			}
		}

		// Entry: breakout above/below EMA
		if (Position == 0)
		{
			if (close > emaValue + atrValue * 1.5m)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (close < emaValue - atrValue * 1.5m)
			{
				_entryPrice = close;
				SellMarket();
			}
		}
	}
}