GitHub で見る

Bago EA 戦略

この戦略はMetaTraderの「Bago EA」エキスパートアドバイザーを複製します。移動平均とRSIのクロスオーバーで確認されたトレンドフォロー ブレイクアウトで取引し、Vegasトンネル(EMA 144/169ペア)が空間フィルターとトレーリングアンカーを提供します。

取引ロジック

  1. インジケーター準備
    • 2本のEMA(期間FastPeriodSlowPeriod、メソッドMaMethod、価格MaAppliedPrice)。
    • Vegasトンネルの EMA(期間144と169、同じメソッド/価格)で方向チャンネルを検出。
    • RSI(RsiPeriodRsiAppliedPrice)による確認。
    • すべての価格対pip変換は元のEAと同様に3/5桁調整付きの銘柄PriceStepを使用します。
  2. クロスオーバー状態マシン
    • EMAの上下クロスおよびRSIの50上下クロスはタイマーで追跡されます。各状態はCrossEffectiveBars足間アクティブのままで、 反対クロスまたはタイムアウトでリセットされます。
    • トンネルクロスは価格がVegasトンネルの一方から他方に移動するときをマークします。
  3. エントリー条件
    • ロング:EMAとRSIの両方の上向きクロスがアクティブ かつ 価格が:
      • 少なくともTunnelBandWidthPipsだがTunnelSafeZonePipsを超えずにトンネル上でクローズ、強気の足ボディあり、または
      • TunnelBandWidthPipsだけトンネル下でクローズ、下からの反発を示す。
    • ショート:EMA/RSIの下向きクロスで鏡像ロジック。
    • 取引は有効なセッション内(ロンドン07–16、ニューヨーク12–21、東京00–08、または23:00以降にクローズする任意のバー)でのみ 許可されます。
  4. 注文処理
    • 新規ポジションはボリュームTradeVolumeで開かれます。反転前に反対ポジションが閉じられます。
    • 初期ストップはクローズ価格からStopLossPipsに設定されます。ストップ対トンネルオフセットはStopLossToFiboPipsを使用。
  5. トレーリングと部分決済
    • 価格がVegasトンネルレベルを超えて前進するにつれてストップが動きます:
      • トンネル内では、ストップはtunnel ± (TrailingStepX + StopLossToFibo)に止まります。
      • トンネル外では、価格の後ろにTrailingStopPipsのハードトレーリングが適用されます。
    • 部分決済は価格がエントリーから十分に動いたらTrailingStep1PipsPartialClose1VolumeTrailingStep2PipsPartialClose2Volumeを閉じます。
    • 反対のEMA/RSIクロスは即座にポジション全体を閉じます。
  6. ストップ
    • 保護注文は成行ストップ注文として維持されます。ポジションが閉じられるたびにキャンセルされます。

パラメーター

パラメーター デフォルト 説明
TradeVolume decimal 3 ロット単位の注文サイズ。
StopLossPips decimal 30 初期ストップロス距離。
StopLossToFiboPips decimal 20 Vegasトンネル周辺にストップを止める際の追加バッファ。
TrailingStopPips decimal 30 価格がトンネルを離れた後のトレーリングストップ距離。
TrailingStep1Pips decimal 55 部分決済とストップ再配置の最初の利益レイヤー。
TrailingStep2Pips decimal 89 部分決済とトレーリングの2番目の利益レイヤー。
TrailingStep3Pips decimal 144 純粋なトレーリングが使用される前の最終レイヤー。
PartialClose1Volume decimal 1 TrailingStep1Pipsで閉じるボリューム。
PartialClose2Volume decimal 1 TrailingStep2Pipsで閉じるボリューム。
CrossEffectiveBars int 2 EMA/RSIクロスが有効なままになる足数。
TunnelBandWidthPips decimal 5 取引しないVegasトンネル周辺の中立ゾーン。
TunnelSafeZonePips decimal 120 ロングエントリーのトンネル上の最大距離(ショートはトンネル下)。
EnableLondonSession bool true ロンドン時間中のシグナルを許可。
EnableNewYorkSession bool true ニューヨーク時間中のシグナルを許可。
EnableTokyoSession bool false 東京時間中のシグナルを許可。
FastPeriod int 5 高速EMAの長さ。
SlowPeriod int 12 低速EMAの長さ。
MaShift int 0 すべてのEMAに適用される水平シフト。
MaMethod MovingAverageType Exponential 移動平均の平滑化モード。
MaAppliedPrice AppliedPriceType Close EMAに送られる足の価格。
RsiPeriod int 21 RSIの平均化長さ。
RsiAppliedPrice AppliedPriceType Close RSIに送られる足の価格。
CandleType DataType H1タイムフレーム 計算に使用する足シリーズ。

注意事項

  • 戦略はトレーディング時間外でもインジケーター状態を維持します、元のEAとまったく同様に。
  • ストップ注文は MetaTrader のPositionModify呼び出しを模倣するために高レベルAPI(SellStop/BuyStop)を通じて管理されます。
  • すべてのコメントと構造はリポジトリガイドライン(インデントにタブ、英語インラインコメント)に従います。
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Bago EA trend-following strategy using EMA crossover with RSI confirmation.
/// Buys when fast EMA crosses above slow EMA and RSI above 50.
/// Sells on reverse conditions.
/// </summary>
public class BagoEaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	/// <summary>
	/// Fast EMA period.
	/// </summary>
	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	/// <summary>
	/// Slow EMA period.
	/// </summary>
	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	/// <summary>
	/// Stop-loss distance in price steps.
	/// </summary>
	public int StopLossPoints
	{
		get => _stopLossPoints.Value;
		set => _stopLossPoints.Value = value;
	}

	/// <summary>
	/// Take-profit distance in price steps.
	/// </summary>
	public int TakeProfitPoints
	{
		get => _takeProfitPoints.Value;
		set => _takeProfitPoints.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the <see cref="BagoEaStrategy"/> class.
	/// </summary>
	public BagoEaStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicator");

		_slowPeriod = Param(nameof(SlowPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicator");

		_stopLossPoints = Param(nameof(StopLossPoints), 200)
			.SetNotNegative()
			.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");

		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400)
			.SetNotNegative()
			.SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

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

		_fast = null;
		_slow = null;
		_prevFast = 0;
		_prevSlow = 0;
		_entryPrice = 0;
		_cooldown = 0;
	}

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

		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

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

		if (!_fast.IsFormed || !_slow.IsFormed)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		if (_cooldown > 0)
		{
			_cooldown--;
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		// Check SL/TP
		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}

			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step)
			{
				SellMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}

			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step)
			{
				BuyMarket();
				_entryPrice = 0;
				_cooldown = 80;
				_prevFast = fastValue;
				_prevSlow = slowValue;
				return;
			}
		}

		// EMA crossover
		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();

			BuyMarket();
			_entryPrice = close;
			_cooldown = 80;
		}
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{
			if (Position > 0)
				SellMarket();

			SellMarket();
			_entryPrice = close;
			_cooldown = 80;
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}
}