GitHub で見る
MACD ダイバーと RSI 戦略
概要
この戦略は、「Macd diver and rsi」 MetaTrader 5 Expert Advisor を C# に変換したものです。元の 2 段階のシグナルの概念が維持されています。相対強度指数 (RSI) は売られすぎまたは買われすぎの極値を検出し、MACD ヒストグラムは取引の方向に勢いが戻っていることを確認します。長辺と短辺は独立して設定されるため、強気と弱気の設定に合わせて動作を個別に調整できます。
この戦略は、単一のキャンドル サブスクリプション (設定可能な時間枠) で動作し、成行注文を通じてチャートに記載された証券を直接取引します。すべてのインジケーター処理は、プロジェクト ルールに一致する、BindEx 経由で高レベルの StockSharp API を使用します。
取引ロジック
インジケーターの準備
- 2 つの RSI インジケーターが作成されます。1 つはロングレッグ用、もう 1 つはショートレッグ用で、それぞれ長さとしきい値が設定されています。
- 2 つの
MovingAverageConvergenceDivergenceSignal インジケーターは、ロング取引とショート取引の MACD 設定を反映しています。それらのヒストグラム コンポーネントは、運動量の反転を確認するために使用されます。
エントリールール
- ロングセットアップ: ロングの RSI 値が売られすぎのしきい値以下で かつ ロングの MACD ヒストグラムがゼロを超える (符号がマイナスからプラスに変わる) 場合、強気ポジションがオープンします。ショートポジションがアクティブな場合、同じ市場注文でクローズされ、反転されます。
- ショートセットアップ: ショートの RSI 値が買われすぎのしきい値以上で、かつ ショートの MACD ヒストグラムがゼロを下回ると、弱気のポジションがオープンされます。既存の長時間露光は、新しい短時間露光が確立される前にフラット化されます。
リスク管理
- 各エントリーの後、ストラテジーはシグナルバーの終値を参照価格として記録します。
- ストップロスとテイクプロフィットのレベルは、ロングトレードとショートトレードで個別に定義されたピップ距離を使用して、その価格から予測されます。
- ピップは商品
PriceStep を使用して価格単位に変換され、MT5 の動作を反映するために小数点以下 3 桁または 5 桁のシンボルの場合は 10 ずつ自動的にスケーリングされます。
- 完了したすべてのキャンドルについて、高値/低値の範囲がこれらのレベルに対してチェックされます。いずれかのレベルに到達すると、成行注文でポジションが即座にクローズされます。
貿易管理
- ポジションの状態は、ポジション サイズがゼロに戻るたびにクリアされます (ストップ/テイクプロフィットに達したか、反対のシグナルによって戦略が反転されたため)。
- 部分的な終了や後続調整は実行されません。ポジションは静的なストップロスとテイクプロフィットのレベルによってのみ管理されます。
パラメーター
| パラメータ |
説明 |
CandleType |
シグナルに使用されるローソク足サブスクリプションのタイムフレーム。 |
LongRsiPeriod, ShortRsiPeriod |
長いものと短いものを検出する場合は、RSI の長さです。 |
LongRsiThreshold, ShortRsiThreshold |
エントリーを可能にする RSI しきい値 (ロングの場合は売られすぎ、ショートの場合は買われすぎ)。 |
LongMacdFastLength, LongMacdSlowLength, LongMacdSignalLength |
MACD EMA の長さは強気レッグです。 |
ShortMacdFastLength, ShortMacdSlowLength, ShortMacdSignalLength |
MACD EMA の長さは弱気レッグです。 |
LongVolume, ShortVolume |
シグナルごとの取引量。反転する場合、この戦略では絶対オープン量が追加されるため、単一の注文でクローズと新規オープンが実行されます。 |
LongStopLossPips, LongTakeProfitPips, ShortStopLossPips, ShortTakeProfitPips |
ストップロス注文とテイクプロフィット注文の距離 (ピップ単位)。ゼロを指定すると、それぞれのレベルが無効になります。 |
注意事項
- この戦略には、ゼロ以外の
PriceStep を持つインストゥルメントが必要です。ステップが欠落している場合、ピップ計算はゼロ除算を防ぐために 0.0001 に戻ります。
- 双方が独立したインジケーター インスタンスを使用するため、たとえば買われすぎのしきい値を厳しくしながら売られすぎの側をより寛容に保つなど、強気と弱気の動作を個別に調整できます。
- このコードには、取引プロセスを明確にし、プロジェクト ガイドラインを満たすために英語のコメントとドキュメントが追加されています。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// MACD Diver And RSI strategy: RSI extremes + MACD histogram crossover.
/// Buys when RSI below 30 and MACD histogram crosses above zero.
/// Sells when RSI above 70 and MACD histogram crosses below zero.
/// </summary>
public class MacdDiverAndRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private decimal _prevHistogram;
private decimal _prevRsi;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public MacdDiverAndRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevHistogram = 0;
_prevRsi = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd = { ShortMa = { Length = 12 }, LongMa = { Length = 26 } },
SignalMa = { Length = 9 }
};
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(macd, rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue, IIndicatorValue rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (!macdValue.IsFinal || !rsiValue.IsFinal) return;
if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;
var histogram = macdMain - signal;
var rsi = rsiValue.ToDecimal();
if (_hasPrev)
{
if (_prevHistogram <= 0 && histogram > 0 && _prevRsi < 35 && Position <= 0)
BuyMarket();
else if (_prevHistogram >= 0 && histogram < 0 && _prevRsi > 65 && Position >= 0)
SellMarket();
}
_prevHistogram = histogram;
_prevRsi = rsi;
_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 MovingAverageConvergenceDivergenceSignal, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class macd_diver_and_rsi_strategy(Strategy):
def __init__(self):
super(macd_diver_and_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._prev_histogram = 0.0
self._prev_rsi = 0.0
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 RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
def OnReseted(self):
super(macd_diver_and_rsi_strategy, self).OnReseted()
self._prev_histogram = 0.0
self._prev_rsi = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(macd_diver_and_rsi_strategy, self).OnStarted2(time)
self._has_prev = False
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = 12
macd.Macd.LongMa.Length = 26
macd.SignalMa.Length = 9
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(macd, rsi, self._process_candle).Start()
def _process_candle(self, candle, macd_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFinal or not rsi_value.IsFinal:
return
if macd_value.Macd is None or macd_value.Signal is None:
return
macd_main = float(macd_value.Macd)
signal = float(macd_value.Signal)
histogram = macd_main - signal
rsi_val = float(rsi_value)
if self._has_prev:
if self._prev_histogram <= 0 and histogram > 0 and self._prev_rsi < 35 and self.Position <= 0:
self.BuyMarket()
elif self._prev_histogram >= 0 and histogram < 0 and self._prev_rsi > 65 and self.Position >= 0:
self.SellMarket()
self._prev_histogram = histogram
self._prev_rsi = rsi_val
self._has_prev = True
def CreateClone(self):
return macd_diver_and_rsi_strategy()