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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class aeron_jjn_strategy(Strategy):
def __init__(self):
super(aeron_jjn_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA trend filter", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._prev_open = 0.0
self._prev_close = 0.0
self._has_prev = False
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(aeron_jjn_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
self.SubscribeCandles(self.CandleType) \
.Bind(ema, self.ProcessCandle) \
.Start()
def ProcessCandle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
ema_val = float(ema_value)
if self._has_prev:
prev_bull = self._prev_close > self._prev_open
prev_bear = self._prev_close < self._prev_open
curr_bull = float(candle.ClosePrice) > float(candle.OpenPrice)
curr_bear = float(candle.ClosePrice) < float(candle.OpenPrice)
if prev_bear and curr_bull and float(candle.ClosePrice) > ema_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_bull and curr_bear and float(candle.ClosePrice) < ema_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_open = float(candle.OpenPrice)
self._prev_close = float(candle.ClosePrice)
self._has_prev = True
def OnReseted(self):
super(aeron_jjn_strategy, self).OnReseted()
self._prev_open = 0.0
self._prev_close = 0.0
self._has_prev = False
def CreateClone(self):
return aeron_jjn_strategy()