GitHub で見る

Bollinger RSI MA 戦略

概要

Bollinger RSI MA 戦略は、MetaTrader エキスパート BolRSIMAs を StockSharp のハイレベル API に移植します。このシステムは、 Bollinger バンド ブレイクアウト、RSI フィルター、およびプルバック取引を識別するためのより高いタイムフレームの指数移動平均 (EMA) 支配的なトレンドの方向。自動ロットサイジングは維持されます。有効にすると、戦略は設定されたリスクを変換します。 現在の価格、Bollinger のストップ距離、商品契約サイズを使用して、ポートフォリオの資本の割合を出来高に換算します。

取引ロジック

  1. プライマリローソク足シリーズ (デフォルト: 1 時間) をサブスクライブし、同じ時間枠で Bollinger バンドと RSI を計算します。
  2. 毎日のローソク足を購読し、その終値を 200 期間 EMA にフィードして、使用されるより高い時間枠フィルターを再現します オリジナルの EA で。
  3. 最新のローソク足が下限バンドを下回って終了し、RSI の値が売られすぎのしきい値を下回ったときに、ロング セットアップを生成します そして終値は日足のEMAを上回ったままです。 ショート セットアップは、アッパーバンド、RSI を上回る終値によってトリガーされます。 買われすぎのしきい値と価格が毎日の EMA を下回っています。
  4. アクティブなエクスポージャがない場合にのみポジションをオープンします。すべての新しい取引には、 以前の Bollinger の値: ロングは lowerBand - StopLossOffset を使用し、中間帯域をターゲットにします。ショーツ使用 upperBand + StopLossOffset と同様にミドルバンドもターゲットにします。
  5. 完成した各ローソク足について、戦略は保護レベルに対してローソク足の極値をチェックします。安値/高値が接触した場合 ストップまたはターゲットの場合、ポジションは即座にクローズされ、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 自動ロットサイジングが無効になっている場合の注文サイズ。

お金の管理

  • UseAutoLottrue の場合、音量は (equity * RiskPerTrade) / (StopLossOffset * price * contractSize) に四捨五入されます。 交換制限。これは、リスク量を現金の停止距離で割る MetaTrader 自動ロット ルーチンを反映しています。 契約サイズ。
  • 株式情報または価格が利用できない場合、戦略は引き続き FixedVolume に戻ります。 楽器の音量制限。

MetaTrader エキスパートとの違い

  • ストップロスとテイクプロフィットの注文は、サーバー側の注文ではなく、ローソク足の高値と安値を通じてシミュレートされ、 同期注文送信に依存せずに、元の EA の結果を確認できます。
  • EMA フィルタは、StockSharp のキャンドル サブスクリプションを使用します。 MetaTrader 固有の毎日のデータ呼び出しには依存しません。
  • リスクサイジングでは、取引所で注文が拒否されるのを避けるために、StockSharp のセキュリティ制限 (MinVolumeMaxVolumeVolumeStep) が考慮されます。

使い方のヒント

  • 異なる価格スケールのシンボルを取引する場合は、距離が元の 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;
		}
	}
}