GitHub で見る
安倍 BE RSI 戦略
概要
ABE BE RSI 戦略 は、MetaTrader エキスパート アドバイザー Expert_ABE_BE_RSI の移植版です。このシステムは、古典的なローソク足反転パターンと相対強度指数 (RSI) からの勢い確認を組み合わせたものです。 2 つの連続するローソク足は強気または弱気の巻き込みパターンを形成する必要があり、最後に完了したローソク足は、事前に定義されたしきい値内の RSI の読み取り値を示さなければなりません。追加の RSI クロス ルールは、既存のポジションをフラット化または反転するために適用され、元の MQL 実装の決定ロジックを厳密に反映しています。
取引ロジック
- 飲み込みパターンの検出
この戦略は、最後に完了した 2 つのローソク足を評価します。強気シグナルには以下が必要です。
- ローソク足 t-2 は始値よりも低く閉じます (弱気な実体)。
- ローソク足 t-1 は始値よりも高く終了します (強気の実体)。
- ローソク足 t-1 の実体サイズは、最近の実体サイズ (デフォルトの 5 つのバー) の移動平均を超えています。
- ローソク足 t-1 はローソク足 t-2 の始値より上で閉じ、終値より下で開き、真の巻き込みイベントを保証します。
- ローソク足の中間点 t-2 は終値の移動平均を下回っており、短期的な下降トレンドを裏付けています。
弱気巻き込みシグナルは対称的な条件を使用します。つまり、古いローソク足は強気で、新しいローソク足は弱気で実体が平均よりも大きく、新しいローソク足が以前の実体を完全に飲み込む一方、古い足の中点が移動平均より上に位置して下降トレンドの枯渇を確認します。
RSI 確認
- ロングエントリーでは、最も最近閉じたローソク足の RSI が設定された強気エントリーレベル (デフォルト 40) を下回っている必要があります。
- ショートエントリーでは、最近閉じたローソク足の RSI が弱気エントリーレベル (デフォルト 60) を超えている必要があります。
出口管理
既存のポジションを決済するために、2 つのレベルにわたる RSI 個のクロスオーバーが監視されます。
- RSI が、前のローソク足で下限値 (デフォルト 30) または上限値 (デフォルト 70) の出口しきい値を下回った後、その値を上回ると、ショート ポジションがカバーされます。
- RSI が前のローソク足でいずれかのしきい値を上回った後、それを下回った場合、ロング ポジションはクローズされます。
注文の実行
成行注文はエントリーとエグジットの両方に使用されます。反転する場合、戦略はまず現在のエクスポージャを閉じてから、設定されたベースボリュームで新しい方向に入ります。ポジションサイジングは、MQL エキスパートの固定ロット モデルを模倣しています。
パラメーター
| 名前 |
説明 |
デフォルト |
Volume |
Order size in contracts. |
0.1 |
RsiPeriod |
RSI フィルターで使用されるバーの数。 |
11 |
MovingAveragePeriod |
ローソク足の実体サイズと終値移動平均の期間。 |
5 |
BullishEntryLevel |
強気の巻き込みエントリーを依然として検証する最大値 RSI 。 |
40 |
BearishEntryLevel |
弱気の巻き込みエントリーに必要な最小値 RSI 。 |
60 |
ExitLowerLevel |
フラットな位置にするには、RSI 交差点のレベルを下げます。 |
30 |
ExitUpperLevel |
平地位置の上部 RSI 交差点レベル。 |
70 |
CandleType |
戦略的に加工されたキャンドルシリーズ。 |
1 hour time frame |
StrategyParam ラッパーのおかげで、すべてのパラメータをデザイナーまたはランナー内で最適化できます。
インジケーターパイプライン
- 相対強度指数 (RSI) – 設定可能な
RsiPeriod を超える勢いを計算し、エントリー/エグジットのしきい値を提供します。
- 終値の単純移動平均 – 巻き込みパターンを検証するために使用されるトレンドのコンテキストを提供します。
- ローソク足の実体サイズの単純移動平均 – 巻き込むローソク足が最後の
MovingAveragePeriod バーにわたる平均実体サイズよりも大きいことを確認します。
使用上の注意
- この戦略は、完全に完了したローソク足 (
CandleStates.Finished) にのみ作用します。時期尚早のシグナルを避けるために、部分的なバー データは無視されます。
- キャンドル履歴は内部的に保存され、プロジェクト全体の変換ガイドラインを尊重し、大規模なコレクションを走査することなく飲み込み状況を評価します。
StartProtection() が有効になっているため、位置露出がゼロ以外の場合に基本の StockSharp 保護メカニズムがアクティブになります。
元のExpert Advisorとの違い
- オリジナルの Expert Advisor は、MetaTrader のシグナル投票システムに依存しています。このポートでは、投票は同じ条件を再現する直接の開始アクションと終了アクションに変換されます。
- 資金管理は単一の
Volume パラメータに簡素化され、ソース エキスパートが使用する固定ロット サイズ (Money_FixLot_Lots) を反映しています。
- MT5 バージョンでは「トレーリングなし」モジュールが使用されていたため、トレーリングストップのサポートは含まれていません。
推奨されるテスト
- デザイナーまたは API ランナーのチャートに、歴史的に巻き込み反転に反応するシンボル (例: 主要 FX ペア) を使用して戦略を添付します。
- ライブセッションを実行する前に、RSI と移動平均パラメータを確認してください。デフォルトは公開されたエキスパートアドバイザー設定を再現します。
- 組み込みの最適化機能を使用して、さまざまな市場の代替の RSI しきい値や平均期間を調べます。
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// ABE BE RSI strategy: Engulfing pattern with RSI confirmation.
/// Bullish engulfing + oversold RSI for long, bearish engulfing + overbought RSI for short.
/// </summary>
public class AbeBeRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _oversold;
private readonly StrategyParam<decimal> _overbought;
private readonly StrategyParam<int> _signalCooldownCandles;
private readonly List<ICandleMessage> _candles = new();
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public AbeBeRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_oversold = Param(nameof(Oversold), 40m)
.SetDisplay("Oversold", "RSI oversold level", "Signals");
_overbought = Param(nameof(Overbought), 60m)
.SetDisplay("Overbought", "RSI overbought level", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candles.Clear();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candles.Clear();
_candlesSinceTrade = SignalCooldownCandles;
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;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
_candles.Add(candle);
if (_candles.Count > 5)
_candles.RemoveAt(0);
if (_candles.Count >= 2)
{
var curr = _candles[^1];
var prev = _candles[^2];
var bullishEngulfing = prev.OpenPrice > prev.ClosePrice
&& curr.ClosePrice > curr.OpenPrice
&& curr.OpenPrice <= prev.ClosePrice
&& curr.ClosePrice >= prev.OpenPrice;
var bearishEngulfing = prev.ClosePrice > prev.OpenPrice
&& curr.OpenPrice > curr.ClosePrice
&& curr.OpenPrice >= prev.ClosePrice
&& curr.ClosePrice <= prev.OpenPrice;
if (bullishEngulfing && rsiValue < Oversold && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (bearishEngulfing && rsiValue > Overbought && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class abe_be_rsi_strategy(Strategy):
def __init__(self):
super(abe_be_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._oversold = self.Param("Oversold", 40.0)
self._overbought = self.Param("Overbought", 60.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles = []
self._candles_since_trade = 6
@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
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def Oversold(self):
return self._oversold.Value
@Oversold.setter
def Oversold(self, value):
self._oversold.Value = value
@property
def Overbought(self):
return self._overbought.Value
@Overbought.setter
def Overbought(self, value):
self._overbought.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(abe_be_rsi_strategy, self).OnReseted()
self._candles.clear()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(abe_be_rsi_strategy, self).OnStarted2(time)
self._candles.clear()
self._candles_since_trade = self.SignalCooldownCandles
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
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
rsi_val = float(rsi_value)
self._candles.append(candle)
if len(self._candles) > 5:
self._candles.pop(0)
if len(self._candles) >= 2:
curr = self._candles[-1]
prev = self._candles[-2]
bullish_engulfing = (float(prev.OpenPrice) > float(prev.ClosePrice)
and float(curr.ClosePrice) > float(curr.OpenPrice)
and float(curr.OpenPrice) <= float(prev.ClosePrice)
and float(curr.ClosePrice) >= float(prev.OpenPrice))
bearish_engulfing = (float(prev.ClosePrice) > float(prev.OpenPrice)
and float(curr.OpenPrice) > float(curr.ClosePrice)
and float(curr.OpenPrice) >= float(prev.ClosePrice)
and float(curr.ClosePrice) <= float(prev.OpenPrice))
if bullish_engulfing and rsi_val < self.Oversold and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif bearish_engulfing and rsi_val > self.Overbought and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return abe_be_rsi_strategy()