
Das auf Kernschliff-Multiple-Mean basierende Adaptive Trend-Tracking-System ist eine fortgeschrittene quantitative Handelsstrategie, die fünf benutzerdefinierte Moving Averages, mehrere Schichten von Filtern und Bestätigungsmechanismen integriert, um anhaltende Markttrends zu erkennen und zu nutzen. Die Strategie verwendet Kernschliff-Technologien anstelle von herkömmlichen Moving Averages und bietet eine flexiblere Schliffwirkung und Anpassungsfähigkeit, um sich an verschiedene Marktbedingungen und Zeitrahmen anzupassen.
Die Kernfunktionen umfassen: die visuelle Darstellung des aktuellen Markttrends mit Hilfe eines “Gleichlinienbands” aus fünf Moving Averages; die Reduzierung von Noise und Falschsignalen durch RSI-Filter, Trendstärkenfilter und Trendbestätigungsphasen; das Triggern von Einstiegssignalen nur bei Erfüllung bestimmter Bedingungen; und die Verwendung von mehreren Ausstiegsoptionen (wie Prozentsatzstop, ATR-Stopp, ATR-Gewinnziel und Hardnessstop) zur Risikomanagement und Gewinnschutz.
Die Kernlogik der Strategie basiert auf folgenden Schlüsselkomponenten:
KernschleifdurchschnitteStrategie: Die Verwendung von Kernschlifftechniken anstelle von Standard Moving Averages bietet eine Schliffwirkung, die flexibler und anpassungsfähiger ist als die herkömmliche MA. Unterstützt werden drei Kerntypen:
alphaUndbetaDie Parameter werden unabhängig von der Positiv-Negativ-Lagerung gesteuert, so dass der MA unterschiedlich schnell auf Preisanstiege und -rückgänge reagiert.bandwidthDie Parameter steuern die Breite der Glockenkurve.bandwidthParameterDurchschnittDie fünf MA bilden die “Gleichgewichtsstreifen” auf dem Chart, deren Anordnung und relative Position eine visuelle Angabe der Trendstärke und -richtung bietet.
KreuzungStrategie zur Überwachung von Kreuzungen zwischen aufeinanderfolgenden MA im Gleichschnur-Band. Der Benutzer kann die Anzahl der Kreuzungen festlegen, die zur Erzeugung eines potenziellen Signals erforderlich sind.
RSI-FilterDer RSI muss unterhalb des Überverkaufs liegen, wenn der Markt überlänger ist, und der RSI muss über dem Überkauf liegen, wenn der Markt leer ist.
TrendstärkefilterDer RSI wird als Maß für die Stärke eines Trends verwendet, um sicherzustellen, dass der Handel in Richtung eines starken, etablierten Trends erfolgt.
Trends bestätigt: Falschsignale weiter zu reduzieren, Eintrittsvoraussetzungen (MA-Kreuzung, RSI und Trendstärke) müssen eine bestimmte Anzahl von K-Linien in Folge erfüllt werden, bevor der Handel tatsächlich ausgelöst wird.
Aus der LogikDie Strategie priorisiert den Ausstieg in der folgenden Reihenfolge: Hardness-Stop, Tracking-Stop (Prozent oder ATR-basiert) und Profit (ATR-basiert). Dies sorgt dafür, dass Verluste minimiert und Gewinne geschützt werden.
Anpassbare Höhe der KernflächeDer Einsatz von Kern-Schleifungen (insbesondere Beta-Kern) bietet ein Maß an Kontrolle über die Reaktionsfähigkeit des MA, das in einem Standard-MA nicht verfügbar ist. Dies erlaubt eine anpassungsfähiger und feinfühligere Methode zur Trendverfolgung.
Zusammenfassung von Trendstärke und BestätigungDie Kombination aus einem Trendstärkefilter (RSI mit MA) und einer Trendbestätigungsphase bietet einen starken Filtermechanismus, der über einfache MA-Kreuzungen oder RSI-Lesungen hinausgeht. Dies hilft, schwache Trends und Erschütterungen zu filtern.
Mehrfache Prioritäts-Opt-Out-OptionenDie Strategie hat eine sehr komplexe Ausstiegslogik, die eine Kombination aus festen und dynamischen Stop-Loss- und Gewinnniveaus bietet. Priorisierung, um sicherzustellen, dass der konservativste Ausstieg (Hardness Stop-Loss) zuerst ausgelöst wird, gefolgt von einem Tracking-Stop-Loss und schließlich einem Gewinnziel.
Gesamtgruppe der EingabenAlle Eingaben sind in Gruppen für bestimmte Aspekte der Steuerungsstrategie klassifiziert, so dass der Benutzer die Eingaben schnell und einfach lokalisieren und anpassen kann.
Handelsrichtung kontrolliertDie Strategie erlaubt es, mehrköpfige und leere Transaktionen unabhängig voneinander zu aktivieren oder zu deaktivieren.
Allgemeine TrendsystemeDer Indikator kombiniert mehrere Aspekte, die für den Handel erforderlich sind: Einstiegssignale, Stop-Loss-Berechnung, Gewinnberechnung.
Herausforderungen bei der Optimierung von ParameternEs besteht die Gefahr, dass eine Strategie mit einer hohen Anzahl von Parametern über-passt. Eine zu feine Anpassung der Parameter kann dazu führen, dass die Strategie bei der Rückmessung gut funktioniert, aber im realen Handel nicht funktioniert. Es wird empfohlen, robuste Cross-Verifizierung und Off-Sample-Tests durchzuführen, um sicherzustellen, dass die Parameter-Einstellungen universell sind.
Die Reaktion auf die Trendänderung verzögert sichDie Strategie zielt darauf ab, anhaltende Trends zu identifizieren, kann jedoch bei starken Marktumdrehungen nicht schnell genug reagieren, was zu einem teilweisen Rückzug führt. Die Empfindlichkeit für Trendänderungen und die Fähigkeit, Geräusch zu filtern, können durch Anpassung der MA-Länge und der Kernparameter ausgeglichen werden.
MA-KreuzfalschsignaleEs ist empfehlenswert, diese Strategie in bestimmten Trendmärkten zu verwenden oder die Trendbestätigungszeit zu erhöhen, um falsche Signale zu verringern.
Die Schadensbegrenzung wird zu früh ausgelöst.In einem großen, schwankenden Markt kann ein Stop-Loss zu früh ausgelöst werden, was zu einer verpassten nachfolgenden Kursrückführung und Trendwiederholung führt. Ein Stop-Loss auf Basis des ATR kann berücksichtigt und entsprechend angepasst werden, um der Marktvolatilität gerecht zu werden.
KomplexitätsrisikenDie Komplexität der Strategie kann die Fehlerbehebung und die Überwachung in Echtzeit erschweren. Es wird empfohlen, mit einer einfachen Konfiguration zu beginnen und schrittweise komplexe Funktionen hinzuzufügen, um sicherzustellen, dass die Rolle jeder Komponente vollständig verstanden wird.
Anpassungsfähigkeit des ZeitrahmensDie aktuelle Strategie kann weiter optimiert werden, so dass sie die Parameter automatisch an die verschiedenen Zeiträume anpasst. Zum Beispiel kann die automatische Parameteranpassung auf der Grundlage der Zeiträume hinzugefügt werden, so dass die Strategie auf den Tages-, Stunden- oder Minutenlinien effektiv funktioniert.
MarktumfeldprüfungErhöhung der automatischen Detektionsmechanismen für die Marktumgebung (Trends, Bandbreiten oder hohe Volatilität) und Anpassung der Handelsparameter an die Ergebnisse. Zum Beispiel Erhöhung der Filterintensität oder Anpassung der Gewinnziele in Bandmärkten und Lockerung der Filterbedingungen in Trends.
Dynamische RSI-TermineDie Überkauf-Überverkauf-Schwelle des RSI ist so konzipiert, dass sie dynamisch und nicht statisch ist und sich automatisch an die jüngste Marktvolatilität anpasst. Dies verbessert die Anpassungsfähigkeit der Strategie unter verschiedenen Marktbedingungen.
Integrierte Quantifizierung von SchwankungenStrategie und Volatilitätsindikatoren (z. B. Bollinger Bandbreite) zu integrieren, um Stop-Loss- und Profit-Zielpunkte in einem sehr volatilen Umfeld anzupassen und das Risiko zu verringern, dass ein effektiver Trend ausgelöst wird.
Mehrfache ZeitrahmenbestätigungTrendbestätigung für einen höheren Zeitrahmen hinzufügen, um sicherzustellen, dass die Handelsrichtung mit einer größeren Trendrichtung übereinstimmt. Zum Beispiel wird nur gehandelt, wenn die Tageszeitenrichtung mit der Stundenzeitenrichtung übereinstimmt.
Leistungsüberwachung und AnpassungDas System ermöglicht die Echtzeit-Überwachung der Strategie-Performance, um Indikatoren wie die Gewinn- und Verlustquote und die maximale Rücknahme zu verfolgen. Die Parameter werden automatisch angepasst oder der Handel wird ausgesetzt, wenn die Performance-Indikatoren unter die vorgegebene Schwelle fallen.
Maschinelles Lernen verstärkt: Erforschung der Integration von Machine-Learning-Algorithmen in den Parameteroptimierungsprozess, um Strategien zu ermöglichen, die beste Parameterkombination aus historischen Daten zu lernen und mit der Ansammlung neuer Daten zu verbessern.
Das Adaptive Trend-Tracking-System, basierend auf einer Kern-Gleichung-Mehrfach-Mittellinie, ist ein leistungsfähiges und flexibles Trend-Tracking-Tool, das die visuelle Klarheit des Moving Average-Bands mit der Kern-Gleichung, dem RSI, der Trendstärke und den erweiterten Filterungs- und Risikomanagement-Fähigkeiten für verschiedene Ausstiegsoptionen kombiniert. Es wurde für Händler entwickelt, die ein maßgeschneidertes und leistungsfähiges Tool haben möchten, um anhaltende Markttrends zu erkennen und zu handeln.
Der größte Vorteil dieser Strategie liegt in ihrer hohen Anpassbarkeit und Anpassungsfähigkeit, die es ermöglicht, sich an verschiedene Marktbedingungen anzupassen. Durch die Kernschmierung bietet sie eine noch feinere Kontrolle als herkömmliche Moving Averages, während mehrere Filter- und Bestätigungsmechanismen dazu beitragen, falsche Signale zu reduzieren. Gleichzeitig bietet das integrierte Risikomanagementsystem mehrere Ausstiegsstrategien, die sicherstellen, dass Verluste minimiert und Gewinne geschützt werden.
Benutzer sollten jedoch auf die Herausforderungen bei der Optimierung der Parameter achten, übermäßige Anpassung vermeiden und die Strategie an die spezifischen Marktbedingungen anpassen. Es wird empfohlen, ausreichend Rückmeldung und Tests vorwärts durchzuführen, um sicherzustellen, dass die Strategie unter verschiedenen Marktbedingungen stabil funktioniert. Durch regelmäßige Bewertung und Optimierung hat die Strategie das Potenzial, ein wertvolles Gut im Werkzeugkasten eines erfolgreichen Trendtraders zu werden.
/*backtest
start: 2024-03-28 00:00:00
end: 2025-03-27 00:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
*/
//@version=5
strategy("B4100 - NW Trend Ribbon Strategy", overlay=true, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.02)
// === Optimized Functions ===
f_calculate_beta_kernel(length, alpha, beta) =>
kernel = array.new_float(length, 0)
sum = 0.0
for i = 0 to length - 1
x = i / (length - 1)
w = math.pow(x, alpha - 1) * math.pow(1 - x, beta - 1)
array.set(kernel, i, w)
sum += w
for i = 0 to length - 1
array.set(kernel, i, array.get(kernel, i) / sum)
kernel
f_calculate_gaussian_kernel(length, bandwidth) =>
kernel = array.new_float(length, 0)
sum = 0.0
for i = 0 to length - 1
x = i / (length - 1)
w = math.exp(-0.5 * math.pow((x - 0.5) / bandwidth, 2))
array.set(kernel, i, w)
sum += w
for i = 0 to length - 1
array.set(kernel, i, array.get(kernel, i) / sum)
kernel
f_calculate_epanechnikov_kernel(length, bandwidth) =>
kernel = array.new_float(length, 0)
sum = 0.0
for i = 0 to length - 1
x = i / (length - 1)
w = math.max(0.0, 1 - math.pow((x - 0.5) / bandwidth, 2))
array.set(kernel, i, w)
sum += w
for i = 0 to length - 1
array.set(kernel, i, array.get(kernel, i) / sum)
kernel
f_apply_kernel_ma(src, kernel, length) =>
sum = 0.0
for i = 0 to length - 1
sum += src[i] * array.get(kernel, i)
sum
f_trend_strength(ma, length) =>
ts = ta.rsi(ma, length) / 100
ts
// === Inputs ===
src = input.source(close, title="Price Source", tooltip="Select the price data used for calculations. 'Close' is the most common, but you can also use 'Open', 'High', 'Low', 'HL2' (typical price), etc.")
// MA Parameters
maGroup = "Moving Average Settings"
maCrossoverGroup = "Moving Average Crossover Settings"
rsiFilterGroup = "RSI Filter Settings"
trendStrengthGroup = "Trend Strength Filter Settings"
trendConfirmGroup = "Trend Confirmation Settings"
trailingStopGroup = "Trailing Stop Settings"
atrTrailingStopGroup = "ATR Trailing Stop Settings"
atrTakeProfitGroup = "ATR Take Profit Settings"
hardStopGroup = "Hard Stop Loss Settings"
tradeDirectionGroup = "Trade Direction Control"
length1 = input.int(20, title="MA1 Length", minval=1, tooltip="Number of bars used to calculate the first Moving Average.", group=maGroup)
kernelType1 = input.string(title="MA1 Kernel Type", defval="Beta", options=["Beta", "Gaussian", "Epanechnikov"], tooltip="Select the type of smoothing kernel for MA1. 'Beta' allows for lag adjustment. 'Gaussian' and 'Epanechnikov' use a bandwidth.", group=maGroup)
alpha1 = input.float(3.0, title="MA1 Beta Kernel +Lag", minval=1, maxval=10, tooltip="For Beta kernel only: Higher values increase *positive* lag (MA reacts *slower* to price increases).", group=maGroup)
beta1 = input.float(3.0, title="MA1 Beta Kernel -Lag", minval=1, maxval=10, tooltip="For Beta kernel only: Higher values increase *negative* lag (MA reacts *slower* to price decreases).", group=maGroup)
bandwidth1 = input.float(0.3, title="MA1 Bandwidth", minval=0.1, maxval=10.0, tooltip="For Gaussian/Epanechnikov kernels: Smaller values create a *tighter* fit to the price (more sensitive). Larger values create a *smoother*, less sensitive MA.", group=maGroup)
length2 = input.int(100, title="MA2 Length", minval=1, tooltip="Number of bars for the second Moving Average.", group=maGroup)
kernelType2 = input.string(title="MA2 Kernel Type", defval="Gaussian", options=["Beta", "Gaussian", "Epanechnikov"], tooltip="Kernel type for MA2 (see MA1 Kernel Type for details).", group=maGroup)
alpha2 = input.float(3.0, title="MA2 Beta Kernel +Lag", minval=1, maxval=10, tooltip="Beta kernel positive lag for MA2 (see MA1 Beta Kernel +Lag for details).", group=maGroup)
beta2 = input.float(3.0, title="MA2 Beta Kernel -Lag", minval=1, maxval=10, tooltip="Beta kernel negative lag for MA2 (see MA1 Beta Kernel -Lag for details).", group=maGroup)
bandwidth2 = input.float(0.3, title="MA2 Bandwidth", minval=0.1, maxval=10.0, tooltip="Bandwidth for MA2 (see MA1 Bandwidth for details).", group=maGroup)
length3 = input.int(150, title="MA3 Length", minval=1, tooltip="Number of bars for the third Moving Average.", group=maGroup)
kernelType3 = input.string(title="MA3 Kernel Type", defval="Epanechnikov", options=["Beta", "Gaussian", "Epanechnikov"], tooltip="Kernel type for MA3.", group=maGroup)
alpha3 = input.float(3.0, title="MA3 Beta Kernel +Lag", minval=1, maxval=10, tooltip="Beta kernel positive lag for MA3.", group=maGroup)
beta3 = input.float(3.0, title="MA3 Beta Kernel -Lag", minval=1, maxval=10, tooltip="Beta kernel negative lag for MA3.", group=maGroup)
bandwidth3 = input.float(0.3, title="MA3 Bandwidth", minval=0.1, maxval=10.0, tooltip="Bandwidth for MA3.", group=maGroup)
length4 = input.int(200, title="MA4 Length", minval=1, tooltip="Number of bars for the fourth Moving Average.", group=maGroup)
kernelType4 = input.string(title="MA4 Kernel Type", defval="Beta", options=["Beta", "Gaussian", "Epanechnikov"], tooltip="Kernel type for MA4.", group=maGroup)
alpha4 = input.float(3.0, title="MA4 Beta Kernel +Lag", minval=1, maxval=10, tooltip="Beta kernel positive lag for MA4.", group=maGroup)
beta4 = input.float(3.0, title="MA4 Beta Kernel -Lag", minval=1, maxval=10, tooltip="Beta kernel negative lag for MA4.", group=maGroup)
bandwidth4 = input.float(0.3, title="MA4 Bandwidth", minval=0.1, maxval=10.0, tooltip="Bandwidth for MA4.", group=maGroup)
length5 = input.int(250, title="MA5 Length", minval=1, tooltip="Number of bars for the fifth Moving Average.", group=maGroup)
kernelType5 = input.string(title="MA5 Kernel Type", defval="Gaussian", options=["Beta", "Gaussian", "Epanechnikov"], tooltip="Kernel type for MA5.", group=maGroup)
alpha5 = input.float(3.0, title="MA5 Beta Kernel +Lag", minval=1, maxval=10, tooltip="Beta kernel positive lag for MA5.", group=maGroup)
beta5 = input.float(3.0, title="MA5 Beta Kernel -Lag", minval=1, maxval=10, tooltip="Beta kernel negative lag for MA5.", group=maGroup)
bandwidth5 = input.float(0.3, title="MA5 Bandwidth", minval=0.1, maxval=10.0, tooltip="Bandwidth for MA5.", group=maGroup)
// Entry Logic
maCrossoversRequired = input.int(3, title="MA Crossovers Required", minval=1, maxval=5, tooltip="How many moving averages must cross each other to generate a potential trade signal. A higher number means a stronger (but potentially later) signal.", group=maCrossoverGroup)
useRsiFilter = input.bool(true, title="Use RSI Filter", tooltip="If enabled, the RSI must also be in overbought/oversold territory for a signal to be valid.", group=rsiFilterGroup)
rsiLength = input.int(7, title="RSI Length", minval=2, tooltip="Number of bars used to calculate the RSI.", group=rsiFilterGroup)
rsiOverbought = input.int(60, title="RSI Overbought", minval=50, maxval=100, tooltip="RSI level considered overbought (for short entries).", group=rsiFilterGroup)
rsiOversold = input.int(40, title="RSI Oversold", minval=0, maxval=50, tooltip="RSI level considered oversold (for long entries).", group=rsiFilterGroup)
// Trend Strength Filter
useTrendStrengthFilter = input.bool(true, title="Use Trend Strength Filter", tooltip="If enabled, the trend strength (measured by the RSI of a selected MA) must be above/below a threshold.", group=trendStrengthGroup)
trendStrengthLength = input.int(7, title="Trend Strength Length", minval=1, tooltip="Number of bars for the trend strength calculation (RSI of the selected MA).", group=trendStrengthGroup)
trendStrengthMa = input.int(1, title="Trend Strength MA", minval=1, maxval=5, tooltip="Which moving average (1-5) to use for calculating trend strength. 1 = MA1, 2 = MA2, etc.", group=trendStrengthGroup)
minTrendStrength = input.float(0.5, title="Min Trend Strength (Longs)", minval=0.0, maxval=1.0, step=0.01, tooltip="Minimum trend strength (0.0 - 1.0) required for long entries. 0.5 means the selected MA's RSI must be above 50.", group=trendStrengthGroup)
maxTrendStrength = input.float(0.5, title="Max Trend Strength (Shorts)", minval=0.0, maxval=1.0, step=0.01, tooltip="Maximum trend strength (0.0 - 1.0) required for short entries. 0.5 means the selected MA's RSI must be below 50.", group=trendStrengthGroup)
// Trend Confirmation
trendConfirmationPeriod = input.int(4, title="Trend Confirmation Period", minval=1, tooltip="Number of consecutive bars the entry conditions must be met before a trade is taken. This helps filter out false signals.", group=trendConfirmGroup)
// Exit Logic
useTrailingStop = input.bool(true, title="Use Percentage Trailing Stop", tooltip="Enable a percentage-based trailing stop loss.", group=trailingStopGroup)
trailingStopActivationPercent = input.float(2.0, title="Activation (%)", minval=0.1, step=0.1, tooltip="Percentage above/below the entry price at which the trailing stop activates.", group=trailingStopGroup) / 100
trailingStopOffsetPercent = input.float(1.0, title="Offset (%)", minval=0.1, step=0.1, tooltip="Percentage offset from the highest/lowest price reached since entry. This determines how tightly the stop trails the price.", group=trailingStopGroup) / 100
useAtrTrailingStop = input.bool(true, title="Use ATR Trailing Stop", tooltip="Enable a trailing stop based on the Average True Range (ATR).", group=atrTrailingStopGroup)
atrTrailingStopLength = input.int(1, title="ATR Length", minval=1, tooltip="Number of bars used to calculate the ATR.", group=atrTrailingStopGroup)
atrTrailingStopMult = input.float(200.0, title="ATR Multiplier", minval=0.1, tooltip="Multiplier for the ATR value. A larger multiplier creates a wider stop.", group=atrTrailingStopGroup)
useAtrTakeProfit = input.bool(false, title="Use ATR Take Profit", tooltip="Enable a take profit level based on the Average True Range (ATR).", group=atrTakeProfitGroup)
atrTakeProfitLength = input.int(14, title="ATR Length", minval=1, tooltip="Number of bars used to calculate the ATR for take profit.", group=atrTakeProfitGroup)
atrTakeProfitMultiplier = input.float(3.0, title="ATR Multiplier", minval=0.1, tooltip="Multiplier for the ATR value. A larger multiplier sets a further take profit target.", group=atrTakeProfitGroup)
useHardStopLoss = input.bool(false, title="Use Hard Stop Loss", tooltip="Enable a fixed stop loss.", group=hardStopGroup)
hardStopLossPercent = input.float(0.0, title="Hard Stop Loss (%)", minval=0.0, step=0.1, tooltip="Percentage below (long) or above (short) the entry price for the hard stop loss.", group=hardStopGroup) / 100
useAtrHardStopLoss = input.bool(false, title="Use ATR Hard Stop Loss", tooltip="Use ATR to calculate hard stop loss", group=hardStopGroup)
atrHardStopLossLength = input.int(14, title="ATR Hard Stop Loss Length", minval=1, tooltip="Length of the ATR for the hard stop loss", group=hardStopGroup)
atrHardStopLossMult = input.float(1.5, title="ATR Hard Stop Loss Multiplier", minval=0.1, tooltip="Multiplier of ATR for the hard stop loss", group=hardStopGroup)
// *** Trade Direction Control ***
enableLongs = input.bool(true, title="Enable Long Trades", group=tradeDirectionGroup)
enableShorts = input.bool(true, title="Enable Short Trades", group=tradeDirectionGroup)
// === Pre-calculate kernels (do this only once) ===
var kernel1 = array.new_float(length1, 0.0)
var kernel2 = array.new_float(length2, 0.0)
var kernel3 = array.new_float(length3, 0.0)
var kernel4 = array.new_float(length4, 0.0)
var kernel5 = array.new_float(length5, 0.0)
if barstate.isfirst
if kernelType1 == "Beta"
kernel1 := f_calculate_beta_kernel(length1, alpha1, beta1)
else if kernelType1 == "Gaussian"
kernel1 := f_calculate_gaussian_kernel(length1, bandwidth1)
else // Epanechnikov
kernel1 := f_calculate_epanechnikov_kernel(length1, bandwidth1)
if kernelType2 == "Beta"
kernel2 := f_calculate_beta_kernel(length2, alpha2, beta2)
else if kernelType2 == "Gaussian"
kernel2 := f_calculate_gaussian_kernel(length2, bandwidth2)
else // Epanechnikov
kernel2 := f_calculate_epanechnikov_kernel(length2, bandwidth2)
if kernelType3 == "Beta"
kernel3 := f_calculate_beta_kernel(length3, alpha3, beta3)
else if kernelType3 == "Gaussian"
kernel3 := f_calculate_gaussian_kernel(length3, bandwidth3)
else // Epanechnikov
kernel3 := f_calculate_epanechnikov_kernel(length3, bandwidth3)
if kernelType4 == "Beta"
kernel4 := f_calculate_beta_kernel(length4, alpha4, beta4)
else if kernelType4 == "Gaussian"
kernel4 := f_calculate_gaussian_kernel(length4, bandwidth4)
else // Epanechnikov
kernel4 := f_calculate_epanechnikov_kernel(length4, bandwidth4)
if kernelType5 == "Beta"
kernel5 := f_calculate_beta_kernel(length5, alpha5, beta5)
else if kernelType5 == "Gaussian"
kernel5 := f_calculate_gaussian_kernel(length5, bandwidth5)
else // Epanechnikov
kernel5 := f_calculate_epanechnikov_kernel(length5, bandwidth5)
// === Apply pre-calculated kernels to data ===
nw_ma1 = f_apply_kernel_ma(src, kernel1, length1)
nw_ma2 = f_apply_kernel_ma(src, kernel2, length2)
nw_ma3 = f_apply_kernel_ma(src, kernel3, length3)
nw_ma4 = f_apply_kernel_ma(src, kernel4, length4)
nw_ma5 = f_apply_kernel_ma(src, kernel5, length5)
// MA Array for easier iteration
ma_array = array.new_float(5)
array.set(ma_array, 0, nw_ma1)
array.set(ma_array, 1, nw_ma2)
array.set(ma_array, 2, nw_ma3)
array.set(ma_array, 3, nw_ma4)
array.set(ma_array, 4, nw_ma5)
// Calculate ATR values *unconditionally*
atrTrailingValue = ta.atr(atrTrailingStopLength)
atrTakeProfitValue = ta.atr(atrTakeProfitLength)
atrHardStopLossValue = ta.atr(atrHardStopLossLength)
// Calculate Trend Strength *unconditionally* (and only once)
trendStrengthValue = useTrendStrengthFilter ? f_trend_strength(array.get(ma_array, trendStrengthMa - 1), trendStrengthLength) : 0.0
// === Entry Logic ===
// MA Crossovers
longMaCrossovers = 0
shortMaCrossovers = 0
for i = 0 to 3
if array.get(ma_array, i) > array.get(ma_array, i + 1)
longMaCrossovers := longMaCrossovers + 1
if array.get(ma_array, i) < array.get(ma_array, i + 1)
shortMaCrossovers := shortMaCrossovers + 1
longCrossoverCondition = longMaCrossovers >= maCrossoversRequired
shortCrossoverCondition = shortMaCrossovers >= maCrossoversRequired
// RSI Filter
rsiValue = ta.rsi(src, rsiLength)
longRsiCondition = not useRsiFilter or (rsiValue < rsiOversold)
shortRsiCondition = not useRsiFilter or (rsiValue > rsiOverbought)
// Trend Strength Filter - Simplified Logic
longTrendStrengthCondition = not useTrendStrengthFilter or trendStrengthValue >= minTrendStrength
shortTrendStrengthCondition = not useTrendStrengthFilter or trendStrengthValue <= maxTrendStrength
// --- Trend Confirmation Logic ---
var int long_confirm_count = 0
var int short_confirm_count = 0
var bool confirmedLong = false
var bool confirmedShort = false
// Update confirmation counters
if longCrossoverCondition and longRsiCondition and longTrendStrengthCondition
long_confirm_count := long_confirm_count + 1
short_confirm_count := 0 // Reset opposite counter
else
long_confirm_count := 0
if shortCrossoverCondition and shortRsiCondition and shortTrendStrengthCondition
short_confirm_count := short_confirm_count + 1
long_confirm_count := 0 // Reset opposite counter
else
short_confirm_count := 0
// Check for confirmed trend
confirmedLong := long_confirm_count >= trendConfirmationPeriod
confirmedShort := short_confirm_count >= trendConfirmationPeriod
// Combined Entry Conditions (using confirmed trend)
longCondition = confirmedLong and enableLongs // Added trade direction check
shortCondition = confirmedShort and enableShorts // Added trade direction check
// === Exit Logic ===
var float longTrail = na
var float shortTrail = na
var float longTakeProfitPrice = na
var float shortTakeProfitPrice = na
var float longHardStopLossPrice = na
var float shortHardStopLossPrice = na
// Hard Stop Loss and Take Profit calculation on entry
if longCondition or shortCondition
// Calculate Hard Stop Loss
if useHardStopLoss
if useAtrHardStopLoss
longHardStopLossPrice := close - (atrHardStopLossValue * atrHardStopLossMult)
shortHardStopLossPrice := close + (atrHardStopLossValue * atrHardStopLossMult)
else
longHardStopLossPrice := close * (1 - hardStopLossPercent)
shortHardStopLossPrice := close * (1 + hardStopLossPercent)
else
longHardStopLossPrice := na
shortHardStopLossPrice := na
// Calculate Take Profit
if useAtrTakeProfit
longTakeProfitPrice := close + (atrTakeProfitValue * atrTakeProfitMultiplier)
shortTakeProfitPrice := close - (atrTakeProfitValue * atrTakeProfitMultiplier)
else
longTakeProfitPrice := na
shortTakeProfitPrice := na
// Trailing Stop Logic - updated for each bar
if strategy.position_size > 0
// Calculate trailing stop
float tempTrail = na
if useTrailingStop
if close > strategy.position_avg_price * (1 + trailingStopActivationPercent)
tempTrail := close * (1 - trailingStopOffsetPercent)
if na(longTrail) or tempTrail > longTrail
longTrail := tempTrail
if useAtrTrailingStop
float atrTrail = close - (atrTrailingValue * atrTrailingStopMult)
if na(longTrail) or atrTrail > longTrail
longTrail := atrTrail
if strategy.position_size < 0
// Calculate trailing stop
float tempTrail = na
if useTrailingStop
if close < strategy.position_avg_price * (1 - trailingStopActivationPercent)
tempTrail := close * (1 + trailingStopOffsetPercent)
if na(shortTrail) or tempTrail < shortTrail
shortTrail := tempTrail
if useAtrTrailingStop
float atrTrail = close + (atrTrailingValue * atrTrailingStopMult)
if na(shortTrail) or atrTrail < shortTrail
shortTrail := atrTrail
// === Strategy Execution ===
if longCondition
strategy.entry("Long", strategy.long)
longTrail := na // Reset on new entry
shortTrail := na // Reset on new entry
if shortCondition
strategy.entry("Short", strategy.short)
shortTrail := na // Reset on new entry
longTrail := na // Reset on new entry
// Unified exit logic with proper ordering
if strategy.position_size > 0
// Define effective stop level (combining hard stop and trailing stop)
float effectiveStopLevel = na
if not na(longHardStopLossPrice) and useHardStopLoss
effectiveStopLevel := longHardStopLossPrice
if not na(longTrail) and (useTrailingStop or useAtrTrailingStop)
if na(effectiveStopLevel) or longTrail > effectiveStopLevel
effectiveStopLevel := longTrail
// Combined exit strategy with proper parameters
strategy.exit("Long Exit", "Long",
limit = useAtrTakeProfit ? longTakeProfitPrice : na,
stop = effectiveStopLevel)
if strategy.position_size < 0
// Define effective stop level (combining hard stop and trailing stop)
float effectiveStopLevel = na
if not na(shortHardStopLossPrice) and useHardStopLoss
effectiveStopLevel := shortHardStopLossPrice
if not na(shortTrail) and (useTrailingStop or useAtrTrailingStop)
if na(effectiveStopLevel) or shortTrail < effectiveStopLevel
effectiveStopLevel := shortTrail
// Combined exit strategy with proper parameters
strategy.exit("Short Exit", "Short",
limit = useAtrTakeProfit ? shortTakeProfitPrice : na,
stop = effectiveStopLevel)
// === Plotting ===
plotColorMa1 = nw_ma1 > nw_ma1[1] ? color.rgb(100, 250, 120) : color.rgb(255, 100, 120)
plotColorMa2 = nw_ma2 > nw_ma2[1] ? color.rgb(100, 250, 120) : color.rgb(255, 100, 120)
plotColorMa3 = nw_ma3 > nw_ma3[1] ? color.rgb(100, 250, 120) : color.rgb(255, 100, 120)
plotColorMa4 = nw_ma4 > nw_ma4[1] ? color.rgb(100, 250, 120) : color.rgb(255, 100, 120)
plotColorMa5 = nw_ma5 > nw_ma5[1] ? color.rgb(100, 250, 120) : color.rgb(255, 100, 120)
plot(nw_ma1, title="NW MA 1", color=plotColorMa1, linewidth=2)
plot(nw_ma2, title="NW MA 2", color=plotColorMa2, linewidth=2)
plot(nw_ma3, title="NW MA 3", color=plotColorMa3, linewidth=2)
plot(nw_ma4, title="NW MA 4", color=plotColorMa4, linewidth=2)
plot(nw_ma5, title="NW MA 5", color=plotColorMa5, linewidth=2)