GitHub で見る

Exp Sinewave2 X2戦略

概要

Exp Sinewave2 X2はJohn EhlersのSinewave分析に着想を得たマルチタイムフレームのトレンドフォロー戦略です。高い時間軸フィルターが支配的な方向を定義し、低い時間軸が正確なエントリーとエグジットのトリガーを提供します。すべての計算は再構築されたSinewave2インジケーターを使用し、これは内部で適応CyclePeriodモジュールに依存します。

インジケーター

  • 高い時間軸Sinewave2(リードラインvsサインライン) – リードサインが主サインコンポーネントを交差することで強気または弱気バイアスを検出します。
  • 低い時間軸Sinewave2 – 高い時間軸方向と一致したトレードをトリガーするために最新のクロスオーバーイベントを監視します。

取引ロジック

  1. トレンドフィルター
    • 高い時間軸でSinewave2を計算します。
    • SignalBarHighバー前のリードとメインラインを評価します。
    • Lead > Sineの場合は強気トレンド、Lead < Sineの場合は弱気トレンド、それ以外はニュートラルです。
  2. エントリーシグナル
    • 低い時間軸で完了したロウソク足を待ちます。
    • SignalBarLow(現在)とSignalBarLow + 1(前)で定義されたオフセットでリードとサインの値を取得します。
    • ロングエントリー:前のクロスオーバーが下向き(以前はLead > Sine、現在はLead <= Sine)で、高い時間軸のトレンドが強気かつEnableBuyOpenが有効。
    • ショートエントリー:前のクロスオーバーが上向き(以前はLead < Sine、現在はLead >= Sine)で、高い時間軸のトレンドが弱気かつEnableSellOpenが有効。
  3. エグジットルール
    • 低い時間軸の出口ブール値EnableBuyCloseLowerEnableSellCloseLowerは反対のクロスオーバーでポジションを決済します。
    • 高い時間軸の出口ブール値EnableBuyCloseTrendEnableSellCloseTrendは主要トレンドがオープン方向に反転するたびにポジションを即座に決済します。
    • 保護ストップロスとテイクプロフィットはイントラバーの高値/安値と価格ステップで表されたStopLossPoints / TakeProfitPoints距離を使用して各ロウソク足で評価されます。
  4. リスク管理
    • ポジションリバーサルは新しい注文をVolume + |Position|としてサイジングし、新しいものを確立する前に既存のポジションをフラット化します。
    • 各エントリー後、SetRiskLevelsSecurity.PriceStepを使用して絶対的なストップ/ターゲット価格を再計算します(利用不可の場合はフォールバック1)。

パラメーター

名前 説明
AlphaHigh 高い時間軸Sinewave2フィルターのアルファ係数。
AlphaLow 低い時間軸Sinewave2トリガーのアルファ係数。
SignalBarHigh トレンド状態を読み取るために高い時間軸で遡るバー数。
SignalBarLow クロスオーバー状態を読み取るために低い時間軸で遡るバー数。
EnableBuyOpen / EnableSellOpen 低い時間軸シグナルからのロング/ショートエントリーを許可。
EnableBuyCloseTrend / EnableSellCloseTrend 高い時間軸がポジションに反転したときの強制出口。
EnableBuyCloseLower / EnableSellCloseLower 低い時間軸の反対のクロスオーバーでポジションを決済。
StopLossPoints インジケーターの価格ステップで表されたストップロス距離。
TakeProfitPoints インジケーターの価格ステップで表されたテイクプロフィット距離。
HigherCandleType / LowerCandleType フィルターとトリガーストリームのロウソク足データタイプ(時間軸)。

注意事項

  • 戦略は完了したロウソク足のみを処理し、部分的な更新は無視します。
  • 適応Sinewave2実装はMQLバージョンに忠実であるために元のCyclePeriodアルゴリズムを使用します。
  • 高い時間軸と低い時間軸のロウソク足タイプが同一の場合、冗長なデータリクエストを避けるために両方のインジケーターが1つのロウソク足サブスクリプションを共有します。
  • デプロイ前にベースStrategyVolumeを調整してトレードサイズを制御します。
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>
/// Ehlers Sinewave X2 strategy (simplified). Uses CCI oscillator for entries.
/// </summary>
public class ExpSinewave2X2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciLength;
	private readonly StrategyParam<int> _emaLength;

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

	public int CciLength
	{
		get => _cciLength.Value;
		set => _cciLength.Value = value;
	}

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

	public ExpSinewave2X2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candles", "General");

		_cciLength = Param(nameof(CciLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Length", "CCI period", "Indicators");

		_emaLength = Param(nameof(EmaLength), 30)
			.SetGreaterThanZero()
			.SetDisplay("EMA Length", "Trend filter EMA", "Indicators");
	}

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

		var cci = new CommodityChannelIndex { Length = CciLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };

		decimal prevCci = 0;
		bool hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(cci, ema, (ICandleMessage candle, decimal cciValue, decimal emaValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevCci = cciValue;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevCci = cciValue;
					return;
				}

				// CCI crosses above -100 with price above EMA
				if (prevCci < -100 && cciValue >= -100 && candle.ClosePrice > emaValue && Position <= 0)
				{
					BuyMarket();
				}
				// CCI crosses below 100 with price below EMA
				else if (prevCci > 100 && cciValue <= 100 && candle.ClosePrice < emaValue && Position >= 0)
				{
					SellMarket();
				}

				prevCci = cciValue;
			})
			.Start();

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