GitHub で見る
Bollinger RSI MA 戦略
概要
Bollinger RSI MA 戦略は、MetaTrader エキスパート BolRSIMAs を StockSharp のハイレベル API に移植します。このシステムは、
Bollinger バンド ブレイクアウト、RSI フィルター、およびプルバック取引を識別するためのより高いタイムフレームの指数移動平均 (EMA)
支配的なトレンドの方向。自動ロットサイジングは維持されます。有効にすると、戦略は設定されたリスクを変換します。
現在の価格、Bollinger のストップ距離、商品契約サイズを使用して、ポートフォリオの資本の割合を出来高に換算します。
取引ロジック
- プライマリローソク足シリーズ (デフォルト: 1 時間) をサブスクライブし、同じ時間枠で Bollinger バンドと RSI を計算します。
- 毎日のローソク足を購読し、その終値を 200 期間 EMA にフィードして、使用されるより高い時間枠フィルターを再現します
オリジナルの EA で。
- 最新のローソク足が下限バンドを下回って終了し、RSI の値が売られすぎのしきい値を下回ったときに、ロング セットアップを生成します
そして終値は日足のEMAを上回ったままです。 ショート セットアップは、アッパーバンド、RSI を上回る終値によってトリガーされます。
買われすぎのしきい値と価格が毎日の EMA を下回っています。
- アクティブなエクスポージャがない場合にのみポジションをオープンします。すべての新しい取引には、
以前の Bollinger の値: ロングは
lowerBand - StopLossOffset を使用し、中間帯域をターゲットにします。ショーツ使用
upperBand + StopLossOffset と同様にミドルバンドもターゲットにします。
- 完成した各ローソク足について、戦略は保護レベルに対してローソク足の極値をチェックします。安値/高値が接触した場合
ストップまたはターゲットの場合、ポジションは即座にクローズされ、MetaTrader バージョンによって発行された保護命令をエミュレートします。
パラメーター
| 名前 |
デフォルト |
説明 |
CandleType |
1時間キャンドル |
プライマリ タイムフレームは Bollinger バンドと RSI によって処理されます。 |
DailyCandleType |
1dayキャンドル |
EMA トレンド フィルターにフィードするより高い時間枠。 |
BollingerPeriod |
20 |
Bollinger バンドの構築に使用されるキャンドルの数。 |
BollingerDeviation |
2 |
帯域幅の乗数。 |
RsiPeriod |
13 |
RSI のスムージング長さ。 |
RsiUpperLevel |
70 |
ショートトレードに必要な買われすぎの閾値。 |
RsiLowerLevel |
30 |
ロングトレードには売られ過ぎの閾値が必要です。 |
MaPeriod |
200 |
上位のタイムフレーム EMA の長さ。 |
StopLossOffset |
0.0238 |
ストップロスを配置する前に、バンドの外側に追加された追加のバッファー。 |
UseAutoLot |
true |
リスクベースのポジションサイジングを可能にします。 |
RiskPerTrade |
0.05 |
自動ロットがアクティブなときに各取引に割り当てられる株式の割合。 |
FixedVolume |
0.1 |
自動ロットサイジングが無効になっている場合の注文サイズ。 |
お金の管理
UseAutoLot が true の場合、音量は (equity * RiskPerTrade) / (StopLossOffset * price * contractSize) に四捨五入されます。
交換制限。これは、リスク量を現金の停止距離で割る MetaTrader 自動ロット ルーチンを反映しています。
契約サイズ。
- 株式情報または価格が利用できない場合、戦略は引き続き
FixedVolume に戻ります。
楽器の音量制限。
- ストップロスとテイクプロフィットの注文は、サーバー側の注文ではなく、ローソク足の高値と安値を通じてシミュレートされ、
同期注文送信に依存せずに、元の EA の結果を確認できます。
- EMA フィルタは、StockSharp のキャンドル サブスクリプションを使用します。 MetaTrader 固有の毎日のデータ呼び出しには依存しません。
- リスクサイジングでは、取引所で注文が拒否されるのを避けるために、StockSharp のセキュリティ制限 (
MinVolume、MaxVolume、VolumeStep) が考慮されます。
使い方のヒント
- 異なる価格スケールのシンボルを取引する場合は、距離が元の EA を反映するように
StopLossOffset を調整します。
Bollinger バンドを超えると 2.38% のバッファ。
- 金融商品が異なる日次時間枠を使用している場合(仮想通貨取引所など)、それに応じて
DailyCandleType を変更して、EMA が
意図したトレンドフィルターを反映します。
- ミドルバンド目標に到達した後に動的に終了することを希望する場合は、この戦略と外部トレーリングストップを組み合わせてください。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Bollinger + RSI + MA strategy.
/// Buys when price at lower BB and RSI oversold, sells at upper BB and RSI overbought.
/// </summary>
public class BollingerRsiMaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<decimal> _bandPercent;
private readonly StrategyParam<int> _signalCooldownCandles;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int BbPeriod { get => _bbPeriod.Value; set => _bbPeriod.Value = value; }
public decimal BandPercent { get => _bandPercent.Value; set => _bandPercent.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public BollingerRsiMaStrategy()
{
_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");
_bbPeriod = Param(nameof(BbPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bandPercent = Param(nameof(BandPercent), 0.01m)
.SetGreaterThanZero()
.SetDisplay("Band Percent", "MA percentage band width", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candlesSinceTrade = SignalCooldownCandles;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var ma = new SimpleMovingAverage { Length = BbPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ma, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal maValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
var close = candle.ClosePrice;
var upper = maValue * (1 + BandPercent);
var lower = maValue * (1 - BandPercent);
// Mean reversion: buy at lower band, sell at upper band
if (close < lower && rsiValue < 35 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (close > upper && rsiValue > 65 && 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, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class bollinger_rsi_ma_strategy(Strategy):
def __init__(self):
super(bollinger_rsi_ma_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._bb_period = self.Param("BbPeriod", 20)
self._band_percent = self.Param("BandPercent", 0.01)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
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 BbPeriod(self):
return self._bb_period.Value
@BbPeriod.setter
def BbPeriod(self, value):
self._bb_period.Value = value
@property
def BandPercent(self):
return self._band_percent.Value
@BandPercent.setter
def BandPercent(self, value):
self._band_percent.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(bollinger_rsi_ma_strategy, self).OnReseted()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(bollinger_rsi_ma_strategy, self).OnStarted2(time)
self._candles_since_trade = self.SignalCooldownCandles
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
ma = SimpleMovingAverage()
ma.Length = self.BbPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, ma, self._process_candle).Start()
def _process_candle(self, candle, rsi_value, ma_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
close = float(candle.ClosePrice)
rsi_val = float(rsi_value)
ma_val = float(ma_value)
upper = ma_val * (1.0 + self.BandPercent)
lower = ma_val * (1.0 - self.BandPercent)
if close < lower and rsi_val < 35 and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif close > upper and rsi_val > 65 and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return bollinger_rsi_ma_strategy()