GitHub で見る

NNFX 自動車取引戦略

概要

NNFX 自動取引戦略 は、StockSharp 内の元の NNFX MetaTrader 4 パネルのリスク評価と管理ワークフローを複製します。この戦略では、グラフィカル インターフェイスの代わりに、パラメータを通じて手動コマンドを公開します。トレーダーはロングまたはショートのエントリーをリクエストしたり、エクスポージャーを即座に平坦化したり、エキスパートアドバイザーを反映した損益分岐点ロジックやトレーリングロジックを適用したりできます。

主な特徴:

  • ATR 主導のボラティリティ サイジング。手動ストップとテイクプロフィット距離のオプションのオーバーライドを備えています。
  • ポジションエントリーは 2 つの部分に分割されます。1 つは予測されたターゲットを含むもの、もう 1 つは裁量管理のために残されたランナーです。
  • 損益分岐点コマンドとトレーリング コマンドはオンデマンドで動作し、足ごとに自動的に実行することなく、保存されているストップ レベルを更新します。
  • MQL スクリプトの動作に合わせて、金銭的リスクを計算するときに追加の資本を含めることができます。

取引ロジック

  1. ATR コレクション – ストラテジーは、設定されたローソク足タイプをサブスクライブし、平均トゥルー レンジ インジケーターを処理します。 UsePreviousDailyAtr が有効な場合、元のスクリプトを模倣して、新しい取引日の最初の 12 時間に前日の ATR の値がコピーされます。
  2. リスクベースのサイジング – 手動の Buy または Sell コマンドで、エンジンは保護停止距離を使用してユニットあたりの金銭的リスクを計算し、必要なリスクのパーセンテージを実行可能なボリュームに変換します。
  3. ポジション分割 – エントリーボリュームは 2 つの半分に分割されます。前半部分は、投影されたターゲットに触れると自動的に清算されますが、後半部分はトレーダーがさらにコマンドを発行するまで残ります。
  4. ストップの処理 – 最初のストップは内部に保存され、完成したキャンドルごとに評価されます。手動コマンドにより、ストップを損益分岐点までプッシュしたり、NNFX トレーリングフォーミュラに従ってストップを進めることができます。
  5. 出口コントロールCloseAll はすぐに帳簿をフラットにしますが、ストップ違反または部分的なターゲットは、計算されたボリュームを尊重して市場からの出口を引き起こします。

パラメーター

パラメータ デフォルト 説明
RiskPercent 2.0 取引ごとにリスクを負うアカウント資本(+ AdditionalCapital)の割合。
AdditionalCapital 0 ポジションのサイジング時に資本ベースに追加資本が追加されます。
UseAdvancedTargets false リスク距離を ATR の倍数から手動の pip 値に切り替えます。
AdvancedStopPips 0 アドバンスモードがアクティブな場合の停止距離 (pips)。
AdvancedTakeProfitPips 0 詳細モードがアクティブな場合の部分的な終了のターゲット距離 (ピップ単位)。
UsePreviousDailyAtr true 新しい日の最初の 12 時間に、前の毎日の ATR をコピーします。
AtrPeriod 14 ATR ルックバックの長さ。
AtrStopMultiplier 1.5 停止距離を計算するときに ATR に適用される乗数。
AtrTakeProfitMultiplier 1.0 利食い距離を計算するときに ATR に適用される乗数。
CandleType 1 Minute ATR と価格監視に使用されるローソクの種類。
BuyCommand false 手動フラグ – 長いエントリを要求するには、true に設定します。自動的にリセットされます。
SellCommand false 手動フラグ – 短いエントリを要求するには、true に設定します。自動的にリセットされます。
BreakevenCommand false 手動フラグ – 保護ストップをエントリー価格に移動します。自動的にリセットされます。
TrailingCommand false 手動フラグ – NNFX トレーリング式を 1 回適用します。自動的にリセットされます。
CloseAllCommand false 手動フラグ – すべてのオープンポジションを即座にクローズします。自動的にリセットされます。

使用上の注意

  • この戦略では、正確なリスク計算のために、有効な StepStepPrice、および VolumeStep メタデータを備えた接続されたポートフォリオとセキュリティが必要です。
  • コマンドは終了したローソク足で評価されるため、手動パラメータを切り替えた後に新しいバー (またはローソク足の更新) を受信する必要があります。
  • 高度な距離を使用する場合は、AdvancedStopPipsAdvancedTakeProfitPips の両方が入力されていることを確認してください。それ以外の場合は、ATR ベースのデフォルトが有効のままになります。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// NNFX Auto Trade strategy: ATR-based trend following with EMA filter.
/// Enters on EMA direction with ATR-based trailing stop management.
/// </summary>
public class NnfxAutoTradeStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<decimal> _atrMultiplier;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _entryPrice;
	private decimal _bestPrice;
	private bool _wasBullish;
	private bool _hasPrevSignal;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public decimal AtrMultiplier { get => _atrMultiplier.Value; set => _atrMultiplier.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public NnfxAutoTradeStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(120).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 100)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Period", "ATR period", "Indicators");
		_atrMultiplier = Param(nameof(AtrMultiplier), 2.5m)
			.SetDisplay("ATR Multiplier", "ATR multiplier for stop", "Risk");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 12)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_entryPrice = 0m;
		_bestPrice = 0m;
		_wasBullish = false;
		_hasPrevSignal = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_entryPrice = 0;
		_bestPrice = 0;
		_hasPrevSignal = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var atr = new AverageTrueRange { Length = AtrPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, atr, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal atrValue)
	{
		if (candle.State != CandleStates.Finished) return;

		var close = candle.ClosePrice;
		var stopDist = atrValue * AtrMultiplier;
		var isBullish = close > emaValue;

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		// Trailing stop check
		if (Position > 0)
		{
			if (close > _bestPrice) _bestPrice = close;
			if (_bestPrice - close > stopDist)
			{
				SellMarket();
				_entryPrice = 0;
				_bestPrice = 0;
				_candlesSinceTrade = 0;
				return;
			}
		}
		else if (Position < 0)
		{
			if (close < _bestPrice) _bestPrice = close;
			if (close - _bestPrice > stopDist)
			{
				BuyMarket();
				_entryPrice = 0;
				_bestPrice = 0;
				_candlesSinceTrade = 0;
				return;
			}
		}

		// Entry signals
		if (_hasPrevSignal && isBullish != _wasBullish && _candlesSinceTrade >= SignalCooldownCandles)
		{
			if (isBullish && Position <= 0)
			{
				BuyMarket();
				_entryPrice = close;
				_bestPrice = close;
				_candlesSinceTrade = 0;
			}
			else if (!isBullish && Position >= 0)
			{
				SellMarket();
				_entryPrice = close;
				_bestPrice = close;
				_candlesSinceTrade = 0;
			}
		}

		_wasBullish = isBullish;
		_hasPrevSignal = true;
	}
}