GitHub で見る
Williams パーセント方向性インデックス戦略
概要
Williams パーセント方向性インデックス戦略 は、StockSharp の高レベルの API を使用して、MetaTrader 5 エキスパート「Mt5 Williams % 方向性インデックス EA」を再作成します。 Williams %R オシレーターと平均方向性インデックス (ADX) を組み合わせてモメンタムの転換を特定し、マネー フロー インデックス (MFI) と Stochastic オシレーターに依存して取引を終了します。実装では完了したローソク足のみが処理され、インジケーター バインディングが使用されるため、すべての決定は最新の完成したバーに基づいて行われます。
取引ロジック
- トレンドの調整
- Williams %R はロングトレードでは上昇するか、ショートトレードでは下落する必要があります。この戦略では、以前に完成した 2 つのバーの値を比較して、勢いの傾きを評価します。
- ADX (
+DI - -DI) の方向性の動きの成分は、最後の閉じたバーでゼロを超えている必要があります。負から正への遷移は強気の勢いを裏付け、正から負への遷移は弱気の勢いを裏付けます。
- エントリールール
- 両方の強気条件が満たされ、現在のポジションがフラットまたはショートの場合、この戦略は成行買い注文を開きます。
- 両方の弱気条件が満たされ、現在のポジションがフラットまたはロングの場合、戦略は市場売り注文を開きます。
- ロングシグナルとショートシグナルの両方が同時に現れる場合(まれではありますが、同じ値で発生する可能性があります)、命令の競合を避けるために取引はスキップされます。
- 退出ルール
- ロングポジションは、2 足前の MFI 値が買われ過ぎレベルを超えるか、Stochastic のメインラインがローカルな底値パターン (
K[−2] > K[−1] < K[0]) を形成すると閉じられます。
- 2 足前の MFI 値がミラーリングされた売られ過ぎレベル (
100 - level) を下回るか、Stochastic のメインラインがローカルピークパターンを形成する (K[−2] < K[−1] > K[0]) 場合、ショートポジションは終了します。
- リスク対応
- 変換では、元の Expert Advisor のエントリとエグジットの仕組みが維持されます。 MQL ソースのストップロスとトレーリング フィーチャは再現されません。リスク管理は外部で管理するか、必要に応じて StockSharp 保護経由で追加する必要があります。
パラメーター
| 名前 |
説明 |
デフォルト |
Candle Type |
すべてのインジケーター計算の時間枠。 |
15分の時間枠 |
Williams %R Period |
Williams %R オシレーターで使用されるルックバック期間。 |
42 |
Directional Period |
ADX 計算の期間 (+DI/−DI に影響します)。 |
20 |
MFI Period |
マネーフローインデックスの長さ。 |
19 |
MFI Level |
手仕舞いをトリガーするために使用される買われすぎのしきい値。売られすぎレベルは 100 - value として計算されます。 |
79 |
Stochastic %K |
確率発振器の %K 周期。 |
22 |
Stochastic %D |
確率発振器の %D 期間。 |
16 |
Stochastic Smoothing |
追加の平滑化 (「減速」) が確率的オシレーターに適用されます。 |
21 |
すべてのパラメータは StrategyParam 値として公開されるため、StockSharp GUI を通じて最適化または調整できます。
使用上の注意
- 開始する前にストラテジを任意のインストゥルメントにバインドし、適切なボリュームを設定します。
- この戦略は完了したローソク足 (
CandleStates.Finished) のみを処理し、インジケーター値が最終的なものであることを保証します。
- チャートのレンダリングが有効になっています: Williams %R、ADX、MFI、Stochastic、チャート領域が使用可能な場合、実行された取引がプロットされます。
- 停止管理に関する元の MT5 の動作を再作成するには、必要に応じて
StartProtection またはカスタム リスク ロジックを追加することを検討してください。
MQL バージョンとの違い
- StockSharp 変換では、手動バッファー コピーの代わりにインジケーター バインディングが使用されますが、ゼロクロス検証やマルチバー パターンを含む論理チェックは MT5 エキスパート アドバイザに従います。
- MQL コードのセッション フィルター、再試行ロジック、トレーリング ストップ管理は、この変換に要求されるコア信号エンジンに焦点を当てるために意図的に省略されています。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Williams %R Directional Index strategy: Williams %R crossover.
/// Buys when Williams %R crosses above -80, sells when crosses below -20.
/// </summary>
public class WilliamsPercentDirectionalIndexStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevWr;
private int _candlesSinceTrade;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int Period { get => _period.Value; set => _period.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public WilliamsPercentDirectionalIndexStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_period = Param(nameof(Period), 14)
.SetGreaterThanZero()
.SetDisplay("Period", "Williams %R period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevWr = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevWr = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var wr = new RelativeStrengthIndex { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(wr, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal wrValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_hasPrev)
{
if (_prevWr < 35 && wrValue >= 35 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevWr > 65 && wrValue <= 65 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevWr = wrValue;
_hasPrev = true;
}
}
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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class williams_percent_directional_index_strategy(Strategy):
def __init__(self):
super(williams_percent_directional_index_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._period = self.Param("Period", 14)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_wr = 0.0
self._candles_since_trade = 4
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def Period(self):
return self._period.Value
@Period.setter
def Period(self, value):
self._period.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(williams_percent_directional_index_strategy, self).OnReseted()
self._prev_wr = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
def OnStarted2(self, time):
super(williams_percent_directional_index_strategy, self).OnStarted2(time)
self._prev_wr = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
rsi = RelativeStrengthIndex()
rsi.Length = self.Period
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, wr_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
wr_val = float(wr_value)
if self._has_prev:
if self._prev_wr < 35 and wr_val >= 35 and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif self._prev_wr > 65 and wr_val <= 65 and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_wr = wr_val
self._has_prev = True
def CreateClone(self):
return williams_percent_directional_index_strategy()