GitHub で見る
Exp Sinewave2 X2戦略
概要
Exp Sinewave2 X2はJohn EhlersのSinewave分析に着想を得たマルチタイムフレームのトレンドフォロー戦略です。高い時間軸フィルターが支配的な方向を定義し、低い時間軸が正確なエントリーとエグジットのトリガーを提供します。すべての計算は再構築されたSinewave2インジケーターを使用し、これは内部で適応CyclePeriodモジュールに依存します。
インジケーター
- 高い時間軸Sinewave2(リードラインvsサインライン) – リードサインが主サインコンポーネントを交差することで強気または弱気バイアスを検出します。
- 低い時間軸Sinewave2 – 高い時間軸方向と一致したトレードをトリガーするために最新のクロスオーバーイベントを監視します。
取引ロジック
- トレンドフィルター
- 高い時間軸でSinewave2を計算します。
SignalBarHighバー前のリードとメインラインを評価します。
Lead > Sineの場合は強気トレンド、Lead < Sineの場合は弱気トレンド、それ以外はニュートラルです。
- エントリーシグナル
- 低い時間軸で完了したロウソク足を待ちます。
SignalBarLow(現在)とSignalBarLow + 1(前)で定義されたオフセットでリードとサインの値を取得します。
- ロングエントリー:前のクロスオーバーが下向き(以前は
Lead > Sine、現在はLead <= Sine)で、高い時間軸のトレンドが強気かつEnableBuyOpenが有効。
- ショートエントリー:前のクロスオーバーが上向き(以前は
Lead < Sine、現在はLead >= Sine)で、高い時間軸のトレンドが弱気かつEnableSellOpenが有効。
- エグジットルール
- 低い時間軸の出口ブール値
EnableBuyCloseLowerとEnableSellCloseLowerは反対のクロスオーバーでポジションを決済します。
- 高い時間軸の出口ブール値
EnableBuyCloseTrendとEnableSellCloseTrendは主要トレンドがオープン方向に反転するたびにポジションを即座に決済します。
- 保護ストップロスとテイクプロフィットはイントラバーの高値/安値と価格ステップで表された
StopLossPoints / TakeProfitPoints距離を使用して各ロウソク足で評価されます。
- リスク管理
- ポジションリバーサルは新しい注文を
Volume + |Position|としてサイジングし、新しいものを確立する前に既存のポジションをフラット化します。
- 各エントリー後、
SetRiskLevelsはSecurity.PriceStepを使用して絶対的なストップ/ターゲット価格を再計算します(利用不可の場合はフォールバック1)。
パラメーター
| 名前 |
説明 |
AlphaHigh |
高い時間軸Sinewave2フィルターのアルファ係数。 |
AlphaLow |
低い時間軸Sinewave2トリガーのアルファ係数。 |
SignalBarHigh |
トレンド状態を読み取るために高い時間軸で遡るバー数。 |
SignalBarLow |
クロスオーバー状態を読み取るために低い時間軸で遡るバー数。 |
EnableBuyOpen / EnableSellOpen |
低い時間軸シグナルからのロング/ショートエントリーを許可。 |
EnableBuyCloseTrend / EnableSellCloseTrend |
高い時間軸がポジションに反転したときの強制出口。 |
EnableBuyCloseLower / EnableSellCloseLower |
低い時間軸の反対のクロスオーバーでポジションを決済。 |
StopLossPoints |
インジケーターの価格ステップで表されたストップロス距離。 |
TakeProfitPoints |
インジケーターの価格ステップで表されたテイクプロフィット距離。 |
HigherCandleType / LowerCandleType |
フィルターとトリガーストリームのロウソク足データタイプ(時間軸)。 |
注意事項
- 戦略は完了したロウソク足のみを処理し、部分的な更新は無視します。
- 適応Sinewave2実装はMQLバージョンに忠実であるために元のCyclePeriodアルゴリズムを使用します。
- 高い時間軸と低い時間軸のロウソク足タイプが同一の場合、冗長なデータリクエストを避けるために両方のインジケーターが1つのロウソク足サブスクリプションを共有します。
- デプロイ前にベース
StrategyのVolumeを調整してトレードサイズを制御します。
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);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import CommodityChannelIndex, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class exp_sinewave2_x2_strategy(Strategy):
"""
Ehlers Sinewave X2 strategy (simplified). Uses CCI oscillator for entries.
CCI crosses above -100 with price above EMA to buy, CCI crosses below 100 with price below EMA to sell.
"""
def __init__(self):
super(exp_sinewave2_x2_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candles", "General")
self._cci_length = self.Param("CciLength", 14) \
.SetDisplay("CCI Length", "CCI period", "Indicators")
self._ema_length = self.Param("EmaLength", 30) \
.SetDisplay("EMA Length", "Trend filter EMA", "Indicators")
self._prev_cci = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(exp_sinewave2_x2_strategy, self).OnReseted()
self._prev_cci = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(exp_sinewave2_x2_strategy, self).OnStarted2(time)
self._has_prev = False
cci = CommodityChannelIndex()
cci.Length = self._cci_length.Value
ema = ExponentialMovingAverage()
ema.Length = self._ema_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, ema, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, cci_val, ema_val):
if candle.State != CandleStates.Finished:
return
cci_val = float(cci_val)
ema_val = float(ema_val)
if not self._has_prev:
self._prev_cci = cci_val
self._has_prev = True
return
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_cci = cci_val
return
close = float(candle.ClosePrice)
if self._prev_cci < -100 and cci_val >= -100 and close > ema_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_cci > 100 and cci_val <= 100 and close < ema_val and self.Position >= 0:
self.SellMarket()
self._prev_cci = cci_val
def CreateClone(self):
return exp_sinewave2_x2_strategy()