GitHub で見る

Sidus Alligator戦略

概要

Sidus戦略はMetaTraderの古典的な「Sidus」エキスパートアドバイザーのロジックをStockSharpで再現します。Bill WilliamsのAlligatorインジケーターと14期間の相対力指数(RSI)フィルターを組み合わせています。システムはAlligatorの3つの移動平均線がすべて同じ方向に拡張している間に、RSIが中間線50を上または下にクロスするのを探します。各エントリーは即座に保護ストップとオプションのトレーリング管理を計算し、インストルメントのプライスステップを考慮したpips距離で表現されます。

インジケーターとデータ

  • Alligatorライン: ローソク足の中央価格(高値 + 安値 ÷ 2)で計算された3つのスムーズド移動平均線で、顎、歯、唇に対して独立した長さと前方シフトを持ちます。連続する値を比較して上向きまたは下向きの拡張を検出します。
  • 相対力指数(RSI): 終値で評価される14期間オシレーター。先読みバイアスを避けるために確定済みローソク足のみが決定に参加します。
  • ローソク足: CandleTypeパラメーターで任意のタイムフレームを選択できます。デフォルトでは1分タイムフレームのローソク足を使用します。

トレードロジック

  1. RSI確認
    • ロングセットアップ:RSIが50を上向きにクロス(RSI[t-2] < 50かつRSI[t-1] > 50)。
    • ショートセットアップ:RSIが50を下向きにクロス(RSI[t-2] > 50かつRSI[t-1] < 50)。
  2. Alligator傾斜フィルター
    • ロングエントリーは、前の2つの完成値(シフトを考慮)の間の顎、歯、唇の傾斜がDelta閾値を超えることを必要とします。
    • ショートエントリーは、同じ傾斜が閾値を下回ることを必要とします。圧縮または低下を示します。
  3. ポジション処理
    • ロングシグナルが現れると、CloseOpposite = trueの場合はまずショートがクローズされます。戦略は次に設定されたOrderVolumeをマーケットで購入します。
    • ショートシグナルが現れると、CloseOppositeで許可されている場合はロングがフラット化され、その後OrderVolumeのマーケット売りが続きます。

エグジットとリスク管理

  • 初期ストップロス: 前のローソク足の極値からOffsetPipsを引いた/加えた位置で計算されます(インストルメントのプライスステップを使用して変換)。計算されたレベルがトレードを無効にする場合(例:正でない距離)、ストップはスキップされます。
  • テイクプロフィット: TakeProfitPipsで定義されるオプションの距離。パラメーターをゼロに設定するとターゲットが無効になります。
  • トレーリングストップ: TrailingStopPipsTrailingStepPipsの両方が正の場合、価格がポジションに有利な方向に少なくともTrailingStopPips + TrailingStepPips移動するとストップが前進します。新しいストップはバー中に達した最高値(ロング)または最安値(ショート)からTrailingStopPips離れた位置に配置されます。
  • フラット化ロジック: ストップロス、テイクプロフィット、トレーリングロジックは各確定済みローソク足で高値/安値レンジを使用して評価され、バー内のタッチをシミュレートします。

パラメーター

  • OrderVolume(デフォルト 0.1): ロットまたはコントラクト単位のトレードサイズ。
  • OffsetPips(デフォルト 3): 前のローソク足極値からストップロスまでの距離。ゼロは初期ストップを無効にします。
  • TakeProfitPips(デフォルト 75): テイクプロフィット距離。ゼロはターゲットを無効にします。
  • TrailingStopPips(デフォルト 5): トレーリングストップ距離。トレーリングが有効な場合は正でなければなりません。
  • TrailingStepPips(デフォルト 15): トレーリングストップが前進する前に必要な追加の移動。トレーリングが有効な場合は正でなければなりません。
  • Delta(デフォルト 0.00003): 連続するサンプル間の各Alligatorラインの最小傾斜差。
  • CloseOpposite(デフォルト false): trueの場合、新しいトレードを開く前に反対側のポジションがクローズされます;falseの場合、戦略は現在のポジションが自然にフラット化されるのを待ちます。
  • JawPeriodTeethPeriodLipsPeriod: Alligatorの顎、歯、唇のスムーズド移動平均の長さ(デフォルト13/8/5)。
  • JawShiftTeethShiftLipsShift: 傾斜比較を取得する際に使用する前方シフト(デフォルト8/5/3)。
  • RsiPeriod(デフォルト 14): RSI平均化ウィンドウ。
  • CandleType: 購読するローソク足データ型/タイムフレーム(デフォルト1分)。

実装上の注意

  • pipsベースの距離はインストルメントの価格精度に自動的に適応します:5桁と3桁の商品はMQL pip定義に合わせるためにプライスステップを10倍します。
  • Alligator傾斜チェックは設定された前方シフトを考慮した保存された過去値に依存し、最小限のリングバッファを超えた手動配列管理を避けます。
  • 注文はハイレベルヘルパーBuyMarketSellMarketで実行され、StockSharpがルーティングを処理しながら戦略がシグナル生成に集中できます。
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Sidus Alligator strategy using triple EMA alignment.
/// </summary>
public class SidusAlligatorStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _jawPeriod;
	private readonly StrategyParam<int> _teethPeriod;
	private readonly StrategyParam<int> _lipsPeriod;

	private decimal? _prevLips;
	private decimal? _prevTeeth;

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

	public int JawPeriod
	{
		get => _jawPeriod.Value;
		set => _jawPeriod.Value = value;
	}

	public int TeethPeriod
	{
		get => _teethPeriod.Value;
		set => _teethPeriod.Value = value;
	}

	public int LipsPeriod
	{
		get => _lipsPeriod.Value;
		set => _lipsPeriod.Value = value;
	}

	public SidusAlligatorStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe", "General");

		_jawPeriod = Param(nameof(JawPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("Jaw Period", "Slow EMA (Jaw)", "Indicators");

		_teethPeriod = Param(nameof(TeethPeriod), 25)
			.SetGreaterThanZero()
			.SetDisplay("Teeth Period", "Medium EMA (Teeth)", "Indicators");

		_lipsPeriod = Param(nameof(LipsPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Lips Period", "Fast EMA (Lips)", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevLips = null;
		_prevTeeth = null;
	}

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

		_prevLips = null;
		_prevTeeth = null;

		var jaw = new ExponentialMovingAverage { Length = JawPeriod };
		var teeth = new ExponentialMovingAverage { Length = TeethPeriod };
		var lips = new ExponentialMovingAverage { Length = LipsPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(jaw, teeth, lips, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal jawVal, decimal teethVal, decimal lipsVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevLips = lipsVal;
			_prevTeeth = teethVal;
			return;
		}

		if (_prevLips == null || _prevTeeth == null)
		{
			_prevLips = lipsVal;
			_prevTeeth = teethVal;
			return;
		}

		// Lips crosses above teeth with alligator aligned (lips > teeth > jaw)
		if (_prevLips.Value <= _prevTeeth.Value && lipsVal > teethVal && lipsVal > jawVal)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Lips crosses below teeth with alligator aligned (lips < teeth < jaw)
		else if (_prevLips.Value >= _prevTeeth.Value && lipsVal < teethVal && lipsVal < jawVal)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevLips = lipsVal;
		_prevTeeth = teethVal;
	}
}