Auf GitHub ansehen

Aeron JJN Ausbruch-Strategie

Diese Strategie repliziert die Logik des originalen Aeron JJN Expert Advisors. Sie beobachtet eine starke Umkehrkerze und platziert eine Stop-Order am Eröffnungskurs der letzten entgegengesetzten Kerze. Stop und Ziel werden einen ATR entfernt gesetzt, und ein optionaler Trailing-Stop schützt offene Positionen.

Tests zeigen, dass die Idee am besten bei wichtigen Forex-Paaren mit 1-Minuten-Kerzen funktioniert.

Eine Long-Stop-Order wird platziert, wenn die vorherige Kerze bärisch mit einem Körper größer als DojiDiff1 ist und die aktuelle Kerze bullisch, aber noch unterhalb der letzten signifikanten bärischen Eröffnung liegt. Eine Short-Stop-Order verwendet die Spiegelbedingungen. Ausstehende Orders werden nach ResetTime Minuten entfernt, wenn sie nicht ausgeführt wurden.

Details

  • Einstiegskriterien:
    • Long: Vorherige Kerze bärisch, aktuelle Kerze bullisch und schließt unterhalb der letzten bärischen Eröffnung.
    • Short: Vorherige Kerze bullisch, aktuelle Kerze bärisch und schließt oberhalb der letzten bullischen Eröffnung.
  • Long/Short: Beide.
  • Ausstiegskriterien:
    • ATR-basierter Stop-Loss und Take-Profit.
    • Optionaler Trailing-Stop in Pips.
  • Stops: Ja, anfänglicher Stop und Ziel basierend auf ATR plus optionalem Trailing.
  • Filter:
    • Ausstehende Orders laufen nach der konfigurierten Zeit ab.

Parameter

  • AtrPeriod – ATR-Berechnungsperiode.
  • DojiDiff1 – Körpergrößenschwelle für die vorherige Kerze.
  • DojiDiff2 – Körpergrößenschwelle bei der Suche nach der letzten entgegengesetzten Kerze.
  • TrailSl – Trailing-Stop aktivieren.
  • TrailPips – Trailing-Abstand in Pips.
  • ResetTime – Minuten bis zur Stornierung von Stop-Orders.
  • CandleType – Arbeitszeitrahmen.
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;
	}
}