GitHub で見る

Aeron JJNブレイクアウト戦略

この戦略はオリジナルのAeron JJNエキスパートアドバイザーのロジックを再現します。強い反転ローソク足を監視し、最後の反対方向のローソク足の始値にストップ注文を配置します。ストップと目標は1ATR離れた位置に設定され、オプションのトレーリングストップがオープンポジションを保護します。

テストでは1分足ローソク足を使用した主要Forex通貨ペアで最も効果的であることが示されています。

前のローソク足がDojiDiff1より大きい実体の弱気線で、現在のローソク足が強気線であるが最後の重要な弱気線の始値を下回っている場合に、ロングストップ注文が配置されます。ショートストップ注文は反対の条件を使用します。未執行のままの保留中の注文はResetTime分後に削除されます。

詳細

  • エントリー条件:
    • ロング: 前のローソク足が弱気、現在のローソク足が強気で最後の弱気始値を下回って終値。
    • ショート: 前のローソク足が強気、現在のローソク足が弱気で最後の強気始値を上回って終値。
  • ロング/ショート: 両方。
  • エグジット条件:
    • ATRベースのストップロスとテイクプロフィット。
    • オプションのpipsでのトレーリングストップ。
  • ストップ: はい、ATRに基づく初期ストップと目標にオプションのトレーリングを加算。
  • フィルター:
    • 保留中の注文は設定された時間後に期限切れになります。

パラメーター

  • AtrPeriod – ATR計算期間。
  • DojiDiff1 – 前のローソク足の実体サイズ閾値。
  • DojiDiff2 – 最後の反対ローソク足を検索する際の実体サイズ閾値。
  • TrailSl – トレーリングストップを有効化。
  • TrailPips – pipsでのトレーリング距離。
  • ResetTime – ストップ注文をキャンセルするまでの分数。
  • CandleType – 作業時間軸。
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Aeron JJN breakout strategy.
/// Buys when candle reverses from bearish to bullish with body confirmation.
/// Sells when candle reverses from bullish to bearish.
/// </summary>
public class AeronJjnStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevOpen;
	private decimal _prevClose;
	private bool _hasPrev;

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

	public AeronJjnStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA trend filter", "Indicator");

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

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevOpen = 0;
		_prevClose = 0;
		_hasPrev = false;
	}

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

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		SubscribeCandles(CandleType)
			.Bind(ema, ProcessCandle)
			.Start();
	}

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

		if (_hasPrev)
		{
			var prevBull = _prevClose > _prevOpen;
			var prevBear = _prevClose < _prevOpen;
			var currBull = candle.ClosePrice > candle.OpenPrice;
			var currBear = candle.ClosePrice < candle.OpenPrice;

			// Buy: bearish to bullish reversal with price above EMA
			if (prevBear && currBull && candle.ClosePrice > emaValue && Position <= 0)
			{
				if (Position < 0) BuyMarket();
				BuyMarket();
			}
			// Sell: bullish to bearish reversal with price below EMA
			else if (prevBull && currBear && candle.ClosePrice < emaValue && Position >= 0)
			{
				if (Position > 0) SellMarket();
				SellMarket();
			}
		}

		_prevOpen = candle.OpenPrice;
		_prevClose = candle.ClosePrice;
		_hasPrev = true;
	}
}