GitHub で見る

ナンセンスなテスター戦略は禁止

概要

No Nonsense Tester 戦略 は、MQL4 の「NoNonsenseTester」エキスパート アドバイザーの StockSharp 移植です。この実装は、トレンドのベースラインを検証し、2 つの確認インジケーターを待機し、ATR を使用してボラティリティをチェックし、厳密な終了ロジックで取引を監視するコアの NNFX ワークフローに焦点を当てています。この戦略は複数パラメータの実験用に設計されているため、すべての重要なしきい値が StrategyParam オブジェクトを通じて公開され、StockSharp 内で最適化できるようになります。

取引ロジック

  1. ベースライン フィルター – 構成可能な長さを持つ EMA は、主要なトレンドの方向を定義します。エントリーは、価格がベースラインを超えて終了した場合にのみ考慮されます。
  2. 確認 #1 – ベースラインブレイクを確認するには、RSI が強気 (しきい値を上回る) または弱気 (補完しきい値を下回る) 側にある必要があります。
  3. 確認 #2 – CCI は傾向と一致し、弱い信号をブロックするために設定された絶対振幅を超える必要があります。
  4. ボラティリティ フィルター – ATR は AtrMinimum の値より大きくなければならず、市場が十分なレンジを示した場合にのみ取引が行われるようにします。
  5. エントリー – ベースラインが交差し、2 つの確認とボラティリティ フィルターが一致すると、戦略は移動方向にポジションをオープンします。ポジションサイズは、オプションで、AtrEntryMultiplier パラメータを介して ATR に応じてスケーリングできます。
  6. ストップ アンド ターゲット – エントリー直後、戦略は ATR ベースのストップロスとテイクプロフィットのレベルを計算します。オプションの ATR トレーリングは、取引が有利に推移している間、保護ストップを更新し続けます。
  7. Exit オーバーレイ – 期間が短い追加の RSI がオープン取引を監視します。ロングの場合は下側のバンドを下回るか、ショートの場合は上側のバンドを超えると、価格が保護レベルに達していなくてもポジションはクローズされます。

パラメーター

パラメータ 説明
BaselineLength EMA ベースラインの期間。
ConfirmationRsiLength RSI 確認インジケーターの長さ。
ConfirmationRsiThreshold RSI レベルが強気と弱気の確認を分けます。
ConfirmationCciLength CCI 確認インジケーターの長さ。
ConfirmationCciThreshold 信号を受け入れるための最小絶対値 CCI 振幅。
AtrPeriod ATR のルックバック期間。
AtrEntryMultiplier 取引量を調整するオプションの ATR 乗数。
AtrTakeProfitMultiplier 利食いレベルの ATR 乗数。
AtrStopLossMultiplier ストップロスレベルの ATR 乗数。
AtrTrailingMultiplier 動的トレーリングに使用される ATR 乗数。無効にするには、0 に設定します。
AtrMinimum 取引を開始する前に、最小値 ATR が必要です。
ExitRsiLength 出口 RSI オーバーレイの長さ。
ExitRsiUpperLevel ショートイグジットを強制する RSI レベル。
ExitRsiLowerLevel 長時間の終了を強制する RSI レベル。
CandleType 計算に使用されるローソク足のタイプ (時間枠)。

チャートオブジェクト

戦略は自動的に以下を描画します。

  • ソースキャンドル。
  • EMA ベースライン。
  • 実行された取引マーカー。

最適化に関するメモ

ロジックで使用されるすべての StrategyParam は、元のテスターの柔軟性を反映した最適化範囲を公開します。 StockSharp 最適化ツールを使用してベースラインの長さ、確認しきい値、リスク設定をスイープし、MQL バージョンで提供されるパラメータ グリッド テストを再現します。

使用のヒント

  • カスタム ツールに一致するようにしきい値を調整して、戦略を NNFX インジケーターのプリセットと組み合わせます。
  • ATR フィルターに注目してください。ゼロ以外の AtrMinimum は、低ボラティリティセッション中の取引を禁止します。
  • 継続取引をテストする場合は、AtrTrailingMultiplier をゼロより大きく設定して、利益を確保しながら収益性の高いポジションを確保します。
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// No Nonsense Tester strategy: EMA baseline + RSI confirmation + CCI confirmation.
/// Buys when price above EMA, RSI above 50, CCI above 0.
/// Sells when price below EMA, RSI below 50, CCI below 0.
/// </summary>
public class NoNonsenseTesterStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _cciPeriod;
	private bool _wasBullish;
	private bool _hasPrevSignal;

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

	public NoNonsenseTesterStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 25)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA baseline period", "Indicators");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI confirmation period", "Indicators");
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI confirmation period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasBullish = false;
		_hasPrevSignal = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrevSignal = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, rsi, cci, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal ema, decimal rsi, decimal cci)
	{
		if (candle.State != CandleStates.Finished) return;
		var close = candle.ClosePrice;
		var isBullish = close > ema && rsi > 50 && cci > 0;

		if (_hasPrevSignal && isBullish != _wasBullish)
		{
			if (isBullish && Position <= 0)
				BuyMarket();
			else if (!isBullish && close < ema && rsi < 50 && cci < 0 && Position >= 0)
				SellMarket();
		}

		_wasBullish = isBullish;
		_hasPrevSignal = true;
	}
}