GitHub で見る

簡単ロボット戦略

概要

Easy Robot は、完了した 1 時間ごとのローソク足ごとに 1 回取引する、勢いに従うエキスパートアドバイザーです。前のローソク足が強気で閉じると、戦略は新しいロングポジションを開きます。弱気で閉じるとショートが始まります。常に 1 つのポジションのみをアクティブにでき、元の MetaTrader 4 ロジックを完全にミラーリングします。

取引ルール

  1. CandleType パラメーターで選択された時間ごとのローソク足タイプをサブスクライブします (デフォルトは H1)。
  2. ローソク足が完成したら、終値と始値を比較します。
    • クローズ > オープン: オープンなポジションがない場合は成行買い注文を送信します。
    • クローズ < オープン: 横ばいの場合は成行売り注文を送信します。
  3. ポジション サイズは、デフォルト 0.01 ロットの CheckVolumeValue に依存する MQL バージョンとまったく同じように、戦略 Volume プロパティを使用します。
  4. ストップロスとテイクプロフィットのレベルは、期間 AtrPeriod (デフォルトは 14) の 平均トゥルー レンジ インジケーターに依存します。
    • 停止距離 = ATR * StopFactor
    • 距離 = ATR * TakeFactor を取得します。
    • 両方の距離は最小ティック/ピップス距離によって正規化されるため、ブローカーが許可するよりも近くに保護注文が発注されることはありません。
  5. 保護注文は、成行注文の直後に SetStopLoss および SetTakeProfit を通じて登録され、sl および tp パラメーターを備えた OrderSend と同じ動作を提供します。
  6. UseTrailingStop が true の場合、オプションのトレーリングがアクティブになります。取引で TrailingStartPips の利益 (MetaTrader ピップ、つまり 3/5 小数点の相場に調整されたポイント) が蓄積された後、ストップは TrailingStepPips だけ近づき、新たな利益の極値に達した場合にのみさらに押し上げられます。トレーリングは無効な変更を避けるためにブローカーの最小停止距離を尊重します。
  7. ストップ計算の見積りでは、可能な場合は最高の買値/売値が使用され、元の Bid/Ask 参照と一致する、最後の価格またはローソク足の終値に戻ります。

パラメーター

名前 デフォルト 説明
TakeFactor 4.2 利食い距離の ATR 乗数 (MQL の TakeFactor 入力にマップされます)。
StopFactor 4.9 ストップロス距離の ATR 乗数 (StopFactor にマッピング)。
UseTrailingStop 本当の MetaTrader スタイルの末尾 (UseTstop) を有効にします。
TrailingStartPips 40 トレーリングが開始されるまでのピップ単位の利益 (Tstart)。
TrailingStepPips 19 末尾の更新時に適用される PIP ステップ (Tstep)。
AtrPeriod 14 ボラティリティサイジングの計算期間は ATR です。
CandleType H1 信号と ATR 入力に使用されるキャンドル シリーズ。

注意事項

  • この戦略は、ポジションがゼロに戻るたびに保存されたエントリー価格とストップ価格をリセットし、次のシグナルに向けてクリーンな状態を保証します。
  • 最小停止距離は、商品のピップサイズ (またはピップサイズが利用できない場合は価格ステップ) によって推定されます。これにより、MQL インクルード ファイルから SC ヘルパーが再現されます。
  • StartProtection() は開始時に 1 回呼び出されるため、プラットフォームは必要に応じて非常口を管理できます。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Easy Robot strategy: simple EMA + RSI trend following.
/// Buys when close above EMA and RSI above 50.
/// Sells when close below EMA and RSI below 50.
/// </summary>
public class EasyRobotStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private bool _wasBullish;
	private bool _hasPrevSignal;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }

	public EasyRobotStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period", "Indicators");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasBullish = false;
		_hasPrevSignal = false;
	}

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

	private void ProcessCandle(ICandleMessage candle, decimal ema, decimal rsi)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		var isBullish = close > ema && rsi > 50;

		if (_hasPrevSignal && isBullish != _wasBullish)
		{
			if (isBullish && Position <= 0)
				BuyMarket();
			else if (!isBullish && close < ema && rsi < 50 && Position >= 0)
				SellMarket();
		}

		_wasBullish = isBullish;
		_hasPrevSignal = true;
	}
}