GitHub で見る

BandOsMaカスタム戦略

概要

この戦略は、次の場所にある MetaTrader 5 Expert Advisor の直接ポートです。 MQL/45596/mql5/Experts/MQL5Book/p7/BandOsMACustom.mq5。オリジナルロボット MACD ヒストグラム (OsMA とも呼ばれます) を Bollinger バンドと組み合わせます。 生の価格の代わりにヒストグラム値に適用される移動平均。 ヒストグラムが下のバンドを突き抜けるたびに、専門家はロングトレードを開始します。 一方、上部バンドに触れるとショートエントリーがトリガーされます。を横切るヒストグラム 個別の移動平均でポジションをクローズします。保護停止と トレーリングストップステップ (ストップの 50 分の 1 に相当) により、リスクをコントロールできます。

StockSharp 実装では、高レベルの API を使用してこの動作が保持されます。 そのため、取引ロジックはフレームワーク内で読み取り可能でデバッグ可能です。

コンバージョンのハイライト

  • MACD ヒストグラムは次のように実装されています MovingAverageConvergenceDivergenceHistogram、ローソク足の価格が供給されます。 AppliedPrice によって選択された MetaTrader PRICE_* モードに対応します パラメータ。
  • Bollinger バンドと出口移動平均は、むしろ OsMA 出力を処理します 価格データよりも。コンパクトな履歴バッファは、MetaTrader shift を再現します。 両方のインジケーターの引数。
  • この戦略では、元のロング/ショート シグナリングが維持されます。 下のバンドはロングを開始し、上のバンドを超えるとショートを開始します。 OsMAが移動平均を超えて取引を終了。
  • StartProtection は、MetaTrader のストップロスとトレーリングストップのブロックをミラーリングします。 後続ステップは、MQL と同様に、StopLossPoints / 50 として計算されます。 クラス TrailingStop が行いました。

インジケーター

インジケーター 目的
MovingAverageConvergenceDivergenceHistogram MetaTrader の iOsMA の出力を再作成します。
BollingerBands ヒストグラムの上限と下限のしきい値を計算します。
移動平均 (SMA/EMA/SMMA/LWMA) ヒストグラムがフィルターを横切るとフィルターは終了します。

パラメーター

名前 デフォルト 説明
CandleType 1時間枠 すべてのインジケーターの計算に使用される主な時間枠。
FastOsmaPeriod 12 OsMA 計算による高速な EMA の長さ。
SlowOsmaPeriod 26 OsMA 計算からの EMA の長さが遅いです。
SignalPeriod 9 OsMA 計算からの信号 SMA の長さ。
AppliedPrice 典型的な ヒストグラムをフィードする MetaTrader スタイルの適用価格。
BandsPeriod 26 ヒストグラム値に描画される Bollinger バンドの長さ。
BandsShift 0 Bollinger 値に適用される右シフト (バー単位)。
BandsDeviation 2.0 バンドの標準偏差乗数。
MaPeriod 10 ヒストグラム上で計算された終了移動平均の長さ。
MaShift 0 終了移動平均に適用される右シフト (バー単位)。
MaMethod シンプル 移動平均法 (SMA、EMA、SMMA、LWMA)。
StopLossPoints 1000 価格ステップで表される保護停止距離。
OrderVolume 0.01 取引量。MetaTrader の「ロット」入力と同じです。

取引ルール

  1. 選択したローソク足シリーズを購読し、選択した適用価格をフィードします MACD ヒストグラムに変換します。
  2. 各ヒストグラム値を Bollinger バンドと終了移動平均に渡します。
  3. シフトされたバッファを使用して信号を検出します。
    • ヒストグラムが下の帯域を下回る場合は、強気シグナルを設定します。
    • ヒストグラムが上部バンドを通過して上昇する場合は、弱気シグナルを設定します。
    • ヒストグラムが終了移動平均を横切ると、アクティブな ポジションを閉じることを可能にするシグナル。
  4. ポジションの管理:
    • 強気シグナルが消えるたびに既存のロングを閉じます。ショートパンツを閉じる 弱気シグナルが消えたとき。
    • 強気シグナルがアクティブでオープンがない場合にロングをオープンする 位置。弱気シグナルがアクティブでポジションが次の場合にショートをオープンします。 平らな。
  5. 構成されたストップロス距離とトレーリングを使用して StartProtection を適用します ステップは StopLossPoints / 50 の価格ステップと同じです。

注意事項

  • リポジトリに準拠するため、ソース コード内のすべてのコメントは英語です。 ガイドライン。
  • 履歴バッファは、StockSharp バージョンが MetaTrader に準拠していることを保証します。 BandsShift パラメータと MaShift パラメータ(インジケーター値をリクエストしない) インデックス。
  • この戦略は、API の高レベルの規則に従っています: SubscribeCandles インジケーターの更新を促進し、BuyMarket/SellMarket の模倣への直接呼び出しを行います 元の専門家の発注。
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy combining the MACD histogram (OsMA) with Bollinger Bands to trade reversals.
/// Similar to BandOsMa but with customizable moving average filter for exit signals.
/// </summary>
public class BandOsMaCustomStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<int> _macdSignalPeriod;
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<int> _maPeriod;

	private BollingerBands _bollinger;
	private SMA _osmaMA;

	private decimal _prevOsma;
	private decimal _prevUpper;
	private decimal _prevLower;
	private decimal _prevMa;
	private bool _hasPrev;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int MacdFastPeriod
	{
		get => _macdFastPeriod.Value;
		set => _macdFastPeriod.Value = value;
	}

	public int MacdSlowPeriod
	{
		get => _macdSlowPeriod.Value;
		set => _macdSlowPeriod.Value = value;
	}

	public int MacdSignalPeriod
	{
		get => _macdSignalPeriod.Value;
		set => _macdSignalPeriod.Value = value;
	}

	public int BollingerPeriod
	{
		get => _bollingerPeriod.Value;
		set => _bollingerPeriod.Value = value;
	}

	public decimal BollingerDeviation
	{
		get => _bollingerDeviation.Value;
		set => _bollingerDeviation.Value = value;
	}

	public int MaPeriod
	{
		get => _maPeriod.Value;
		set => _maPeriod.Value = value;
	}

	public BandOsMaCustomStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Primary timeframe", "General");

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 20)
			.SetDisplay("MACD Fast", "Fast EMA length", "Indicators");

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 50)
			.SetDisplay("MACD Slow", "Slow EMA length", "Indicators");

		_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 12)
			.SetDisplay("MACD Signal", "Signal EMA length", "Indicators");

		_bollingerPeriod = Param(nameof(BollingerPeriod), 14)
			.SetDisplay("Bollinger Period", "OsMA Bollinger Bands period", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetDisplay("Bollinger Deviation", "Bollinger Bands deviation", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 10)
			.SetDisplay("MA Period", "OsMA moving average period for exit filter", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFastPeriod },
				LongMa = { Length = MacdSlowPeriod }
			},
			SignalMa = { Length = MacdSignalPeriod }
		};

		_bollinger = new BollingerBands
		{
			Length = BollingerPeriod,
			Width = BollingerDeviation
		};

		_osmaMA = new SMA { Length = MaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, macd);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var val = (IMovingAverageConvergenceDivergenceSignalValue)macdValue;
		if (val.Macd is not decimal macdLine || val.Signal is not decimal signalLine)
			return;

		var osma = macdLine - signalLine;

		var bbResult = (BollingerBandsValue)_bollinger.Process(new DecimalIndicatorValue(_bollinger, osma, candle.CloseTime));
		if (bbResult.UpBand is not decimal upper || bbResult.LowBand is not decimal lower)
			return;

		var maResult = _osmaMA.Process(new DecimalIndicatorValue(_osmaMA, osma, candle.CloseTime));
		if (maResult.IsEmpty)
			return;

		var ma = maResult.GetValue<decimal>();

		if (_hasPrev)
		{
			var buySignal = _prevOsma > _prevLower && osma <= lower && osma < ma;
			var sellSignal = _prevOsma < _prevUpper && osma >= upper && osma > ma;

			if (buySignal && Position <= 0)
				BuyMarket(Position < 0 ? Math.Abs(Position) + 1 : 1);
			else if (sellSignal && Position >= 0)
				SellMarket(Position > 0 ? Math.Abs(Position) + 1 : 1);
		}

		_prevOsma = osma;
		_prevUpper = upper;
		_prevLower = lower;
		_prevMa = ma;
		_hasPrev = true;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_bollinger = null;
		_osmaMA = null;
		_prevOsma = 0;
		_prevUpper = 0;
		_prevLower = 0;
		_prevMa = 0;
		_hasPrev = false;

		base.OnReseted();
	}
}