JK BullP AutoTrader-Strategie
Überblick
JK BullP AutoTrader ist ein Expertenberater, der dem Momentum folgt und ursprünglich für MetaTrader 4 geschrieben wurde. Er überwacht die Stärke der Elder Bulls
Indikator und reagiert, wenn der Aufwärtsdruck nachlässt oder negativ wird. Der Port StockSharp behält die einfache Logik des bei
originell und bietet gleichzeitig explizite Parameter, detailliertes Trailing-Management und plattformfreundliche Risikokontrollen.
Handelslogik
- Die Strategie abonniert eine konfigurierbare Kerzenserie (standardmäßig 1-Stunden-Kerzen) und berechnet eine 13-Perioden-Exponentialfunktion
gleitender Durchschnitt (EMA), um die Bulls Power-Basislinie zu reproduzieren.
- Für jede abgeschlossene Kerze wird Bulls Power als Differenz zwischen dem Kerzenhoch und dem EMA-Wert gemessen.
- Es werden zwei aufeinanderfolgende Bulls Power-Messwerte verglichen:
- Wenn der vorherige Wert über dem neuesten Wert liegt und der letzte Wert positiv bleibt, eröffnet die Strategie eine Short-Position.
- Wenn der aktuelle Bulls Power-Wert unter Null fällt, eröffnet die Strategie eine Long-Position.
- Es kann jeweils nur eine Position aktiv sein, was dem ursprünglichen MQL-Experten entspricht, der neue Aufträge blockierte, während Geschäfte offen waren.
Risikomanagement und Exits
- Anfänglicher Stop-Loss / Take-Profit: Abstände werden in Pips konfiguriert und mithilfe der Wertpapierpreisstufe in Preiseinheiten umgerechnet.
Beide Schutzmaßnahmen werden durch den
StartProtection-Helfer von StockSharp aktiviert, wodurch das Verhalten nahe an den MetaTrader-Eingaben bleibt.
- Trailing Stop: Sobald der variable Gewinn die angegebene Trailing-Distanz überschreitet, wird der Stop-Level von Kerze zu Kerze verschoben.
Anstatt bestehende Stop-Orders zu ändern (wie in MetaTrader), gibt der Hafen eine Market-Order aus, um die Position bei Preis zu schließen
schließt über die nachlaufende Schwelle hinaus. Dies gewährleistet einen rechtzeitigen Ausgang auch dann, wenn Schutzanordnungen vom Veranstaltungsort nicht unterstützt werden.
Parameter
| Name |
Beschreibung |
Standard |
OrderVolume |
Marktauftragsgröße, die für Eingaben verwendet wird. |
8.5 |
TakeProfitPips |
Take-Profit-Distanz in Pips (umgerechnet in Preiseinheiten). |
500 |
StopLossPips |
Stop-Loss-Distanz in Pips. |
20 |
TrailingStopPips |
Gewinndistanz in Pips, die den Trailing Stop aktiviert und aufrechterhält. |
10 |
EmaPeriod |
Länge des EMA, der von der Bulls Power-Berechnung verwendet wird. |
13 |
CandleType |
Datentyp der Kerzen, die die Strategie steuern (Standardzeitrahmen: 1 Stunde). |
1-Stunden-Kerzen |
Hinweise zur Implementierung
- Die nicht verwendeten Eingaben (
Patr, Prange, Kstop, kts, Vts) aus dem ursprünglichen Skript wurden absichtlich weggelassen, da dies der Fall war
Keine Auswirkung auf die MetaTrader-Logik.
- Pip-Abstände hängen vom Instrument
PriceStep ab. Wenn keine Schrittdaten verfügbar sind, wird der Wert 1 als konservativer Standardwert verwendet.
- Die Strategie verwendet StockSharps übergeordnetes
Bind API, verarbeitet nur fertige Kerzen und behält den internen Status bei (_previousBullsPower).
passend zu den schichtbasierten MT4-Berechnungen.
- Die Trailing-Logik wird nach jedem Exit automatisch zurückgesetzt, um veraltete Stop-Levels zu vermeiden, wenn eine neue Position eröffnet wird.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// JK BullP AutoTrader: RSI momentum with EMA filter and ATR stops.
/// </summary>
public class JkBullPAutoTraderStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevRsi;
private decimal _entryPrice;
public JkBullPAutoTraderStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_rsiLength = Param(nameof(RsiLength), 13)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_emaLength = Param(nameof(EmaLength), 20)
.SetDisplay("EMA Length", "Trend filter.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = 0; _entryPrice = 0;
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ema, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
if (_prevRsi == 0 || atrVal <= 0) { _prevRsi = rsiVal; return; }
var close = candle.ClosePrice;
if (Position > 0)
{
if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 75) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 25) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (rsiVal > 55 && _prevRsi <= 55 && close > emaVal) { _entryPrice = close; BuyMarket(); }
else if (rsiVal < 45 && _prevRsi >= 45 && close < emaVal) { _entryPrice = close; SellMarket(); }
}
_prevRsi = rsiVal;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex, ExponentialMovingAverage, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class jk_bull_p_auto_trader_strategy(Strategy):
"""
JK BullP AutoTrader: RSI momentum with EMA filter and ATR-based stops.
Buys when RSI crosses above 55 with price above EMA,
sells when RSI crosses below 45 with price below EMA.
"""
def __init__(self):
super(jk_bull_p_auto_trader_strategy, self).__init__()
self._rsi_length = self.Param("RsiLength", 13) \
.SetDisplay("RSI Length", "RSI period", "Indicators")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend filter", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._prev_rsi = 0.0
self._entry_price = Decimal.Zero
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(jk_bull_p_auto_trader_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._entry_price = Decimal.Zero
def OnStarted2(self, time):
super(jk_bull_p_auto_trader_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_length.Value
ema = ExponentialMovingAverage()
ema.Length = self._ema_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, ema, atr, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, rsi_val, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
rsi = float(rsi_val)
ema_v = Decimal(float(ema_val))
atr_v = Decimal(float(atr_val))
if self._prev_rsi == 0 or atr_v <= Decimal.Zero:
self._prev_rsi = rsi
return
close = candle.ClosePrice
if self.Position > 0:
if close >= self._entry_price + atr_v * Decimal(2.5) or close <= self._entry_price - atr_v * Decimal(1.5) or rsi > 75:
self.SellMarket()
self._entry_price = Decimal.Zero
elif self.Position < 0:
if close <= self._entry_price - atr_v * Decimal(2.5) or close >= self._entry_price + atr_v * Decimal(1.5) or rsi < 25:
self.BuyMarket()
self._entry_price = Decimal.Zero
if self.Position == 0:
if rsi > 55 and self._prev_rsi <= 55 and close > ema_v:
self._entry_price = close
self.BuyMarket()
elif rsi < 45 and self._prev_rsi >= 45 and close < ema_v:
self._entry_price = close
self.SellMarket()
self._prev_rsi = rsi
def CreateClone(self):
return jk_bull_p_auto_trader_strategy()