5 分 RSI 認定された戦略
概要
5min RSI 限定戦略 は、MetaTrader エキスパート アドバイザー「5min_rsi_qual_01a」を直接変換したものです。オリジナルのロボットは、28 期間の相対強度指数 (RSI) を使用して、5 分間のローソク足で疲労度を調べました。オシレーターが事前定義されたバー数の間極端なゾーンに留まると、EA は逆張りポジションを開き、前のローソク足の終値に続くトレーリングストップを付けました。 StockSharp ポートは、高レベルのローソク足サブスクリプション API に依存しながら、正確な確認ロジック、価格オフセット、単一ポジション制限を維持します。
デフォルトでは、この戦略は 5 分足のローソク足で動作しますが、CandleType パラメーターは、商品がサポートする他の時間枠を受け入れます。すべてのインジケーターのしきい値と停止距離は MetaTrader の「ポイント」で表されるため、ユーザーはさらに調整することなく、テストした設定を再適用できます。
取引ロジック
- RSI の計算 – 28 期間の RSI は、完成したローソクごとに更新されます。完了したキャンドルのみが、MQL4
Close[1] 参照と一致するように処理されます。
- 資格カウンタ – 2 つのカウンタは、RSI が買われすぎしきい値 (
UpperThreshold) を上回った、または売られすぎしきい値 (LowerThreshold) を下回ったローソク足の連続数を追跡します。これは、最後の 12 バーを検査した MQL ループを反映しています。
- エントリー条件 – オープンなポジションがなく、買われ過ぎカウンターが
QualificationLength に達した場合、ストラテジーは成行で売却されます。逆に、売られすぎカウンターが要件に達すると、市場で買いが行われます。これにより、シンボルごとに最大 1 つの取引を保持する EA の動作が再現されます。
- トレーリング ストップ – ポジションがアクティブである間、ストップ レベルは、絶対価格に変換された前の終値マイナス/プラス
StopLossPoints を使用して、終了したローソク足ごとに再計算されます。元のコードの OrderModify 呼び出しとまったく同じように、ストップは取引の方向にのみ移動します。
- 初期停止 – 各充填後に、戦略は
InitialStopPoints を使用して初期停止を設定します。初期値がトレーリング距離よりも狭い場合、トレーリング ロジックは初期値を緩めず、最初の停止がトレーリング距離よりも近くなる可能性がある MetaTrader の動作を維持します。
リスク管理
- 停止距離は、EA と一致するように MetaTrader ポイントで定義されます。これらは、商品の
PriceStep (または、プライマリ ステップが利用できない場合は MinStep) を使用して絶対価格増分に変換されます。
- この戦略は決してピラミッド取引ではありません。新しいポジションは、前のポジションが完全にクローズされた後にのみオープンされます。
StartProtection() は起動時に呼び出され、StockSharp の保護インフラストラクチャが手動で管理される停止レベルと同期した状態を保ちます。
パラメーター
| パラメータ |
説明 |
デフォルト |
RsiPeriod |
RSI ルックバックの長さ。 |
28 |
QualificationLength |
シグナルが確認されるまでに、RSI が極端なゾーンに留まらなければならない連続ローソク足の数。 |
12 |
UpperThreshold |
RSI レベルは弱気のセットアップに適格です。 |
55 |
LowerThreshold |
RSI レベルは強気のセットアップに適格です。 |
45 |
StopLossPoints |
トレーリング ストップの距離 (MetaTrader ポイント)。すべてのローソク足の絶対価格に変換されます。末尾を無効にするには、0 に設定します。 |
21 |
InitialStopPoints |
進入直後に適用される初期保護停止距離 (MetaTrader ポイント)。最初の停止をスキップするには、0 に設定します。 |
11 |
CandleType |
信号評価に使用されるキャンドル タイプ (デフォルトでは 5 分)。 |
5-minute time frame |
使用ガイドライン
- 商品の価格ステップが、MetaTrader の最適化中に使用されるポイント サイズと一致していることを確認してください。 5 桁の FX シンボルの場合、1 ポイントは 0.00010 (1 ピップ) に等しいため、デフォルトの距離は EA の 11/21 ポイントのオフセットを再現します。
- この手法は逆張りであるため、レンジ相場ではシグナルの信頼性が高くなります。トレンドアセットのしきい値を広げるか、
QualificationLength を増やすことを検討してください。
- この戦略では、注文サイズに基本クラスの
Volume プロパティを使用します。戦略を開始する前に、UI またはコード経由で設定します。
SetCanOptimize() フラグを使用すると、RSI のしきい値、認定の長さ、停止距離で最適化を実行できます。
変換メモ
- ローソクの処理、RSI の計算、および 1 ポジション制限は、MetaTrader の実装を反映しています。追加のフィルターは導入されませんでした。
- トレーリングストップは、MQL4
Close[1] ロジックと同様に、前のローソク足の終値でストップレベルを更新し、反転が発生したときに両方のバージョンが同じ価格で終了することを保証します。
- StockSharp はデータの準備状況とポートフォリオの可用性を内部で処理するため、MQL4 スクリプトからのエラー チェック (バー数、空きマージン) は意図的に省略されています。
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>
/// 5-minute RSI qualified strategy.
/// Counts consecutive candles in RSI extreme zones.
/// Buys after sustained oversold, sells after sustained overbought.
/// </summary>
public class FiveMinRsiQualifiedStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _qualificationLength;
private readonly StrategyParam<decimal> _upperThreshold;
private readonly StrategyParam<decimal> _lowerThreshold;
private readonly StrategyParam<DataType> _candleType;
private int _overboughtCount;
private int _oversoldCount;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int QualificationLength { get => _qualificationLength.Value; set => _qualificationLength.Value = value; }
public decimal UpperThreshold { get => _upperThreshold.Value; set => _upperThreshold.Value = value; }
public decimal LowerThreshold { get => _lowerThreshold.Value; set => _lowerThreshold.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FiveMinRsiQualifiedStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI lookback", "Indicators");
_qualificationLength = Param(nameof(QualificationLength), 3)
.SetDisplay("Qual Length", "Consecutive candles in extreme zone", "Indicators");
_upperThreshold = Param(nameof(UpperThreshold), 65m)
.SetDisplay("Upper", "RSI overbought threshold", "Indicators");
_lowerThreshold = Param(nameof(LowerThreshold), 35m)
.SetDisplay("Lower", "RSI oversold threshold", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_overboughtCount = 0;
_oversoldCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_overboughtCount = 0;
_oversoldCount = 0;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
// Track consecutive overbought candles
if (rsiValue >= UpperThreshold)
_overboughtCount++;
else
_overboughtCount = 0;
// Track consecutive oversold candles
if (rsiValue <= LowerThreshold)
_oversoldCount++;
else
_oversoldCount = 0;
// After qualified oversold period, buy (contrarian)
if (_oversoldCount >= QualificationLength && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_oversoldCount = 0;
}
// After qualified overbought period, sell (contrarian)
else if (_overboughtCount >= QualificationLength && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_overboughtCount = 0;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class five_min_rsi_qualified_strategy(Strategy):
"""5-minute RSI qualified strategy.
Counts consecutive candles in RSI extreme zones.
Buys after sustained oversold, sells after sustained overbought."""
def __init__(self):
super(five_min_rsi_qualified_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI lookback", "Indicators")
self._qualification_length = self.Param("QualificationLength", 3) \
.SetDisplay("Qual Length", "Consecutive candles in extreme zone", "Indicators")
self._upper_threshold = self.Param("UpperThreshold", 65.0) \
.SetDisplay("Upper", "RSI overbought threshold", "Indicators")
self._lower_threshold = self.Param("LowerThreshold", 35.0) \
.SetDisplay("Lower", "RSI oversold threshold", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._overbought_count = 0
self._oversold_count = 0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@property
def QualificationLength(self):
return self._qualification_length.Value
@property
def UpperThreshold(self):
return self._upper_threshold.Value
@property
def LowerThreshold(self):
return self._lower_threshold.Value
def OnReseted(self):
super(five_min_rsi_qualified_strategy, self).OnReseted()
self._overbought_count = 0
self._oversold_count = 0
def OnStarted2(self, time):
super(five_min_rsi_qualified_strategy, self).OnStarted2(time)
self._overbought_count = 0
self._oversold_count = 0
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._process_candle).Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_value)
upper = float(self.UpperThreshold)
lower = float(self.LowerThreshold)
qual = int(self.QualificationLength)
# Track consecutive overbought candles
if rsi_val >= upper:
self._overbought_count += 1
else:
self._overbought_count = 0
# Track consecutive oversold candles
if rsi_val <= lower:
self._oversold_count += 1
else:
self._oversold_count = 0
# After qualified oversold period, buy (contrarian)
if self._oversold_count >= qual and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._oversold_count = 0
# After qualified overbought period, sell (contrarian)
elif self._overbought_count >= qual and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._overbought_count = 0
def CreateClone(self):
return five_min_rsi_qualified_strategy()