GitHub で見る

AIS2 トレーディングロボット

概要

AIS2トレーディングロボットは、MetaTrader 5のオリジナルエキスパートアドバイザーから変換されたマルチタイムフレームブレイクアウトシステムです。方向性のブレイクアウトを検出するために高いタイムフレーム(デフォルト15分ローソク足)をスキャンしながら、より速いタイムフレーム(デフォルト1分ローソク足)がアダプティブトレーリングストップを提供します。注文の配置、リスク予算、トレーリングロジックはレガシーMQ5バージョンにコード化されたルールに従いますが、StockSharpの高レベル戦略APIの上に実装されています。

トレードロジック

  • プライマリシグナルローソク足: プライマリタイムフレームの完成した各ローソク足について、戦略は高値、安値、終値、中点、レンジを取得します。
  • ロングセットアップ:
    • 前のローソク足の終値がローソク足の中点より上にあり、強気の圧力を示している必要があります。
    • 現在のask価格は測定されたスプレッドを加えた前の高値より上で取引される必要があります(ブレイクアウトの確認)。
    • エントリー価格は現在のask。ストップロスはhigh + spread - (range × StopFactor)に等しい。テイクプロフィットはask + (range × TakeFactor)に等しい。
    • 追加のブローカーセーフティチェックで、リスクとリワードの両方が設定されたストップバッファー距離より大きいことを確認します。
  • ショートセットアップ:
    • 前のローソク足の終値が中点より下にあり、弱気の圧力を示している必要があります。
    • 現在のbidは前の安値より下に印刷される必要があります(下方向のブレイクアウト)。
    • エントリー価格は現在のbid。ストップロスはlow + (range × StopFactor)に等しい。テイクプロフィットはbid - (range × TakeFactor)に等しい。
  • コンフリクト解決: 新しいトレードは戦略がフラットまたは反対方向にポジションを持っている場合のみ取得されます(エントリーボリュームは新しいポジションを開く前に既存の露出を自動的に相殺します)。

注文管理

  • トレーリングストップ: セカンダリタイムフレームのレンジにTrailFactorを掛けてダイナミックなトレールを構築します。ロングポジションの場合、ストップはbid - trailDistanceに引き寄せられます;ショートの場合、ask + trailDistanceに押されます。価格が利益にない場合や要求された変更が設定されたトレールステップとフリーズバッファーより小さい場合、トレーリング更新はスキップされます。
  • 利益確定とストップ退出: bid/ask価格が保存されたストップロスまたはテイクプロフィットレベルを越えるたびに、ロングとショートの両ポジションは成行注文で清算されます。
  • 注文ブックフィード: ライブの注文ブックサブスクリプションが現在の最良bid/ask価格を追跡し、SymbolInfo.Ask/Bid値に依存していたMQ5ロジックを戦略が再現できるようにします。

ポジションサイジングとリスクコントロール

  • アカウントリザーブ: ポートフォリオ資本の設定可能な部分がロックされ、取引に使用できません。これはオリジナルEAのInp_aed_AccountReserveパラメーターを複製します。
  • 注文リザーブ: 残りの資本は、取引ごとの最大リスク予算を制限する注文割り当て部分によってさらに制限されます。
  • リスクチェック:
    • 予約された資本が割り当て限度(Equity × OrderReserve)より小さい場合、戦略は新しいトレードを断ります。
    • ポジションサイズはriskBudget / |entry - stop|として計算され、セキュリティボリュームステップに揃えられます。ポートフォリオ情報が利用できない場合はフォールバックパラメーターBaseVolumeが使用されます。

パラメーター

パラメーター 説明
AccountReserve 取引から保留される資本の割合(0–0.95)。
OrderReserve 取引ごとのリスク予算を定義する取引可能資本の割合(0–1)。
PrimaryCandleType ブレイクアウト検出の作業タイムフレーム(デフォルト15分)。
SecondaryCandleType トレーリングストップ更新を駆動する高速タイムフレーム(デフォルト1分)。
TakeFactor テイクプロフィット距離を計算するためのプライマリレンジに適用される乗数。
StopFactor ストップロス距離を計算するためのプライマリレンジに適用される乗数。
TrailFactor トレーリング距離を計算するためのセカンダリレンジに適用される乗数。
BaseVolume ポートフォリオメトリクスが利用できない場合に使用されるフォールバック注文サイズ。
StopBufferTicks 取引所のストップ制約を超えて必要な追加距離(ティック単位)。
FreezeBufferTicks フリーズレベル近くの小さなトレーリング調整を防ぐ追加バッファー。
TrailStepMultiplier トレーリング更新間の最小増分を定義するスプレッド乗数。

注記

  • すべてのロジックブランチをアンロックするために、プライマリとセカンダリの両方のローソク足シリーズとライブの注文ブックストリームで常に戦略を提供してください。
  • ブレイクアウトチェックはbid/ask価格に依存しているため、最終取引価格のみでのペーパートレードは実際の環境と比較して異なる動作をする可能性があります。
  • 戦略が実行されると、MQ5バージョンに存在するセーフティルーティンを反映してポジション保護が自動的に開始されます。
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// AIS2 Trading Robot strategy (simplified).
/// Breakout strategy using candle range with ATR filter.
/// Buys when close is near high of candle and ATR shows volatility.
/// Sells when close is near low of candle.
/// </summary>
public class Ais2TradingRobotStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<decimal> _breakoutThreshold;

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

	public int AtrPeriod
	{
		get => _atrPeriod.Value;
		set => _atrPeriod.Value = value;
	}

	public decimal BreakoutThreshold
	{
		get => _breakoutThreshold.Value;
		set => _breakoutThreshold.Value = value;
	}

	public Ais2TradingRobotStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Source candles", "General");

		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Period", "ATR period for volatility", "Indicators");

		_breakoutThreshold = Param(nameof(BreakoutThreshold), 0.85m)
			.SetDisplay("Breakout Threshold", "Candle body ratio threshold (0-1)", "Signals");
	}

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

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind((ICandleMessage candle) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				var range = candle.HighPrice - candle.LowPrice;
				if (range <= 0)
					return;

				var bodyRatio = (candle.ClosePrice - candle.LowPrice) / range;

				// Buy on strong bullish candle (close near high)
				if (bodyRatio > BreakoutThreshold && candle.ClosePrice > candle.OpenPrice && Position <= 0)
				{
					BuyMarket();
				}
				// Sell on strong bearish candle (close near low)
				else if (bodyRatio < (1m - BreakoutThreshold) && candle.ClosePrice < candle.OpenPrice && Position >= 0)
				{
					SellMarket();
				}
			})
			.Start();

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