GitHub で見る

FrBestExp02 マローマ Mod 戦略

この戦略は、MetaTrader 4 エキスパート Frbestexp02_1_maloma_mod.mq4 の C# ポートです。これは、OsMA モメンタム、フラクタル反転、ティックボリューム確認、ローリングデイリーピボットフィルターを組み合わせて、M15 タイムフレームでの使い果たされた動きをフェードアウトします。

取引ロジック

  • セッション ピボット – ローリング ピボット ポイントは、設定可能なウィンドウ (デフォルトでは 96 ローソク足、M15 の 1 取引日に等しい) 内の最高値、最低値、および最も古い終値から計算されます。ピボット バイアスに同意する取引のみが許可されます。つまり、ピボットより上のショートとピボットより下のロングです。
  • フラクタル パターン – この戦略は、ビル Williams フラクタルが 3 キャンドル戻ってくるのを待ちます。ダウンフラクタル (スイング安値) はショートを可能にし、アップフラクタル (スイング高値) はロングを可能にします。
  • OsMA ヒストグラム – MACD ヒストグラム (デフォルトでは高速 12、低速 26、シグナル 9) は、ショートの場合はさらにマイナスの領域に傾斜し、ロングの場合はさらにプラスの領域に傾斜する必要があります。以前のヒストグラムの読み取り値もゼロの同じ側にある必要があります。
  • ボリュームフィルター – 前回完成したキャンドルのボリュームは、設定可能なしきい値を超え、2 つ前のキャンドルのボリュームより大きくなければなりません。これは、元の専門家からのティック ボリュームのスパイク要件を再現します。
  • 注文のタイミング – 取引はエントリー間の最小間隔 (デフォルトでは 20 秒) によって抑制されます。
  • リスク管理 – 設定可能なストップロス、テイクプロフィット、およびオプションのトレーリングストップはポイントで表され、商品価格に変換されます。保護命令は、組み込みの SetStopLoss/SetTakeProfit ヘルパーを使用して更新されます。

パラメーター

名前 説明 デフォルト
Volume 各エントリーに使用される注文量。 1
StopLossPoints 計器ポイントでのストップロス距離。 1000
TakeProfitPoints 商品ポイントでのテイクプロフィット距離。 1000
TrailingStopPoints オプションのトレーリング ストップ距離 (ポイント単位) (0 はトレーリングを無効にします)。 0
VolumeThreshold シグナルを有効にするために必要な前回のローソク足の最小ボリューム。 50
OsmaFastPeriod / OsmaSlowPeriod / OsmaSignalPeriod OsMA ヒストグラムの計算に使用される MACD パラメータ。 12/26/9
PivotWindow ピボット計算に含まれる完成したキャンドルの数。 96
MinTradeIntervalSeconds 新しいエントリ間の最小秒数。 20
CandleType 主要な時間枠 (デフォルトは 15 分足のローソク足)。 M15

MQL4 エキスパートとの違い

  • 元のコードは、kh を乗算したヘッジ注文と複雑な利益リサイクル ロジックをサポートしていました。 StockSharp バージョンは、単一方向のポジションを実行し、新しい取引を開始する前にそれをクローズまたは反転します。
  • トレーリング ストップの処理は、ティックごとの注文を手動で変更する代わりに、標準の SetStopLoss ヘルパーを使用するように簡素化されています。
  • 利益の集計とマーチンゲール形式の回収ブロックは省略されています。イグジット管理はストップロス、テイクプロフィット、またはトレーリングストップに依存します。
  • すべてのインジケーターの計算は、完成したローソク足に対してイベント駆動型で行われます。バー内注文の変更はありません。

使用上の注意

  1. ボリュームフィルターが元の動作と一致する必要がある場合は、ティックボリュームデータを提供するインストゥルメントにストラテジーをアタッチします。
  2. ピボット ウィンドウとフラクタル ルックバックの元のキャリブレーションを再現するには、タイムフレームを 15 分に保ちます。
  3. VolumeThreshold と OsMA の期間を調整して、異なるボラティリティまたは出来高プロファイルのシンボルに適合させます。
  4. トレーリングストップは、よりタイトな出口が必要な場合にのみ有効にします。それ以外の場合は、静的なストップ/ターゲットに依存するためにゼロのままにしておきます。

このコードは、StockSharp API の高レベルのガイドラインに従っています。つまり、SubscribeCandles を介したローソク足予約、MACD ヒストグラムのインジケーター バインディング、自動保護注文による BuyMarket/SellMarket を介した安全な執行です。

using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// FrBestExp02 Maloma Mod strategy - MACD histogram crossover with EMA trend filter.
/// Buys when MACD histogram crosses above zero while price is above EMA.
/// Sells when MACD histogram crosses below zero while price is below EMA.
/// </summary>
public class FrBestExp02MalomaModStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevMacd;
	private decimal _prevSignal;
	private bool _hasPrev;

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

	public FrBestExp02MalomaModStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetDisplay("EMA Period", "EMA trend filter", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevMacd = 0m; _prevSignal = 0m; _hasPrev = false; _currentEma = 0m; }

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_hasPrev = false;

		var macd = new MovingAverageConvergenceDivergenceSignal();
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, ProcessMacd)
			.Bind(ema, ProcessEma)
			.Start();
	}

	private decimal _currentEma;

	private void ProcessEma(ICandleMessage candle, decimal ema)
	{
		if (candle.State != CandleStates.Finished)
			return;

		_currentEma = ema;
	}

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

		if (!value.IsFinal || value.IsEmpty)
			return;

		var macdVal = value as MovingAverageConvergenceDivergenceSignalValue;
		if (macdVal == null)
			return;

		var macdLine = macdVal.Macd;
		var signalLine = macdVal.Signal;

		if (macdLine == null || signalLine == null)
			return;

		var histogram = macdLine.Value - signalLine.Value;

		if (!_hasPrev)
		{
			_prevMacd = macdLine.Value;
			_prevSignal = signalLine.Value;
			_hasPrev = true;
			return;
		}

		var prevHist = _prevMacd - _prevSignal;
		var close = candle.ClosePrice;

		// Histogram crosses above zero + bullish trend
		if (prevHist <= 0 && histogram > 0 && close > _currentEma && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Histogram crosses below zero + bearish trend
		else if (prevHist >= 0 && histogram < 0 && close < _currentEma && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevMacd = macdLine.Value;
		_prevSignal = signalLine.Value;
	}
}