Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=5
- strategy(
- title="Nostra 6.0 with RSI & Variable MA Filters (Strict Non-Repainting)",
- shorttitle="Nostra 6.0 Strict Non-Repainting",
- overlay=false,
- format=format.price,
- precision=2,
- pyramiding=0,
- initial_capital=500,
- default_qty_type=strategy.percent_of_equity,
- default_qty_value=100,
- commission_type=strategy.commission.percent,
- commission_value=0.02,
- max_bars_back=5000
- )
- // Trading Richtung Option
- GRP_DIRECTION = "Trading Direction"
- tradingDirectionInput = input.string("Long and Short", "Trading Direction", options=["Long only", "Long and Short"], group=GRP_DIRECTION)
- GRP_RSI = "RSI Settings"
- rsiLengthInput = input.int(2, minval=1, title="RSI Length", group=GRP_RSI)
- rsiSourceInput = input.source(close, "Source", group=GRP_RSI)
- calculateDivergence = input.bool(true, title="Calculate Divergence", group=GRP_RSI, display = display.data_window)
- GRP_SMOOTH = "Smoothing"
- TT_BB = "Only applies when 'SMA + Bollinger Bands' is selected."
- maTypeInput = input.string("VWMA", "Type", options = ["None", "SMA", "SMA + Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group = GRP_SMOOTH, display = display.data_window)
- maLengthInput = input.int(2, "Length", group = GRP_SMOOTH, display = display.data_window)
- var enableMA = maTypeInput != "None"
- GRP_CALC = "Calculation"
- timeframeInput = input.timeframe("", "Timeframe", group=GRP_CALC)
- GRP_EXIT = "Exit Strategy"
- useTrailingStop = input.bool(true, "Use Trailing Stop Loss", group=GRP_EXIT)
- exitType = input.string("Percent", "Exit Type (Trailing Stop)", options=["Percent", "ATR"], group=GRP_EXIT)
- atrLength = input.int(14, "ATR Length (if used)", group=GRP_EXIT, minval=1)
- trailType = input.string("Percent", "Trailing Stop Type", options=["Percent", "ATR"], group=GRP_EXIT)
- trailPercent = input.float(1.0, "Trailing Stop %", group=GRP_EXIT, minval=0.1, step=0.1) / 100
- trailAtrMult = input.float(1.0, "Trailing Stop ATR Multiple", group=GRP_EXIT, minval=0.1, step=0.1)
- trailActivationPercent = input.float(0.1, "Trailing Activation % Profit", group=GRP_EXIT, minval=0.0, step=0.1) / 100
- trailActivationAtr = input.float(5.0, "Trailing Activation ATR Profit", group=GRP_EXIT, minval=0.0, step=0.1)
- GRP_MA_EXIT = "Variable MA Exit Condition"
- useMAExitCondition = input.bool(true, "Exit trades when price crosses Variable MA", group=GRP_MA_EXIT)
- useHardStopLoss = input.bool(true, "Use hard stop-loss independently from MA", group=GRP_MA_EXIT)
- maxLossPercent = input.float(3.0, "Maximum Loss % (Hard Stop)", minval=0.1, step=0.1, group=GRP_MA_EXIT) / 100
- GRP_SIG = "Signals (Visuals)"
- showMACrossSignals = input.bool(true, title="Show MA Crossover Signal Labels", group=GRP_SIG)
- buyColorInput = input.color(color.blue, "Buy Signal Color", group=GRP_SIG, inline="sigcol")
- sellColorInput = input.color(color.red, "Sell Signal Color", group=GRP_SIG, inline="sigcol")
- GRP_MA_FILTER = "Variable Moving Average Filter"
- useMovingAverageFilter = input.bool(true, "Use Variable MA Filter", group=GRP_MA_FILTER)
- maFilterLength = input.int(40, "MA Length", group=GRP_MA_FILTER)
- maFilterType = input.string("VWMA", "MA Type", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group=GRP_MA_FILTER)
- showInputsInStatusLine = input.bool(true, "Inputs in status line", group="INPUT VALUES")
- // Strikte Anti-Repainting Logik
- // Diese Funktion verwendet nur bestätigte historische Daten
- strict_security(_symbol, _res, _src) =>
- _res_gap = timeframe.in_seconds(_res) / timeframe.in_seconds(timeframe.period)
- _src_data = request.security(_symbol, _res, _src, lookahead=barmerge.lookahead_off)
- _need_past_value = barstate.isrealtime or barstate.islast or (barstate.ishistory and bar_index % math.round(_res_gap) == 0)
- _need_past_value ? _src_data[1] : _src_data
- // RSI-Berechnung
- f_rsi(src, len) =>
- change = ta.change(src)
- up = ta.rma(math.max(change, 0), len)
- down = ta.rma(-math.min(change, 0), len)
- down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
- // MA-Berechnung
- ma(source, length, MAtype) =>
- switch MAtype
- "SMA" => ta.sma(source, length)
- "EMA" => ta.ema(source, length)
- "SMMA (RMA)" => ta.rma(source, length)
- "WMA" => ta.wma(source, length)
- "VWMA" => ta.vwma(source, length)
- "SMA + Bollinger Bands" => ta.sma(source, length)
- => na
- // Smoothing-MA für RSI
- f_smoothingMA(rsiVal, len, type) =>
- enableMA_func = type != "None"
- enableMA_func ? ma(rsiVal, len, type) : na
- // Timeframe-Auswahl
- requestTf = timeframeInput == "" ? timeframe.period : timeframeInput
- // Berechnung der RSI und Smoothing MA Werte mit strikter anti-repainting Logik
- rsi_current = f_rsi(rsiSourceInput, rsiLengthInput)
- smoothingMA_current = f_smoothingMA(rsi_current, maLengthInput, maTypeInput)
- // RSI und Smoothing MA verwenden strikte Anti-Repainting Funktion
- rsi_mtf = strict_security(syminfo.tickerid, requestTf, rsi_current)
- smoothingMA_mtf = strict_security(syminfo.tickerid, requestTf, smoothingMA_current)
- // LongTermMA berechnen
- longTermMA_current = ma(close, maFilterLength, maFilterType)
- // LongTermMA mit strikter Anti-Repainting Funktion
- longTermMA = strict_security(syminfo.tickerid, requestTf, longTermMA_current)
- // Werte für nächste Berechnungen sichern
- rsi = rsi_mtf
- smoothingMA = smoothingMA_mtf
- // ATR für Trailing Stops
- atrValue = ta.atr(atrLength)
- // Plot RSI mit Bändern
- rsiPlot = plot(rsi, "RSI", color=#7E57C2)
- rsiUpperBand = hline(70, "RSI Upper Band", color=#787B86)
- midline = hline(50, "RSI Middle Band", color=color.new(#787B86, 50))
- rsiLowerBand = hline(30, "RSI Lower Band", color=#787B86)
- fill(rsiUpperBand, rsiLowerBand, color=color.rgb(126, 87, 194, 90), title="RSI Background Fill")
- midLinePlot = plot(50, color = na, editable = false, display = display.none)
- fill(rsiPlot, midLinePlot, 100, 70, top_color = color.new(color.green, 90), bottom_color = color.new(color.green, 100), title = "Overbought Gradient Fill")
- fill(rsiPlot, midLinePlot, 30, 0, top_color = color.new(color.red, 100), bottom_color = color.new(color.red, 90), title = "Oversold Gradient Fill")
- plot(enableMA and not na(smoothingMA) ? smoothingMA : na, "RSI-based MA", color=color.yellow, editable = true)
- // Überarbeitete Pivot-Berechnung für strikte Anti-Repainting-Unterstützung
- lookbackRight = 5
- lookbackLeft = 5
- rangeUpper = 60
- rangeLower = 5
- _inRange(cond) =>
- bars = ta.barssince(cond)
- rangeLower <= bars and bars <= rangeUpper
- // Feste Verzögerung für Pivot-Berechnung - Entscheidend gegen Repainting
- var rsi_history = array.new_float(300, 0.0)
- array.unshift(rsi_history, rsi)
- if array.size(rsi_history) > 300
- array.pop(rsi_history)
- get_historical_rsi(offset) =>
- index = math.min(offset, array.size(rsi_history) - 1)
- array.get(rsi_history, index)
- // Sehr strikte Pivot-Berechnung mit festen Verzögerungen
- // Declare the pivotLow and pivotHigh as float variables with initial na value
- var float pivotLow = na
- var float pivotHigh = na
- // Nur berechnen, wenn genügend Daten vorhanden sind und wir uns auf einem bestätigten Balken befinden
- if barstate.isconfirmed and array.size(rsi_history) >= (lookbackLeft + lookbackRight + 1)
- isLowest = true
- isHighest = true
- for i = 0 to (lookbackLeft + lookbackRight)
- if i != lookbackRight
- val = get_historical_rsi(i)
- mid = get_historical_rsi(lookbackRight)
- if val < mid
- isHighest := false
- if val > mid
- isLowest := false
- if isLowest
- pivotLow := get_historical_rsi(lookbackRight)
- if isHighest
- pivotHigh := get_historical_rsi(lookbackRight)
- // Divergenz-Werte speichern
- var rsiLows = array.new_float(10, 0.0)
- var priceLows = array.new_float(10, 0.0)
- var rsiHighs = array.new_float(10, 0.0)
- var priceHighs = array.new_float(10, 0.0)
- // Neue Pivots in Array einfügen
- if not na(pivotLow) and barstate.isconfirmed
- array.unshift(rsiLows, pivotLow)
- array.unshift(priceLows, low[lookbackRight])
- if array.size(rsiLows) > 10
- array.pop(rsiLows)
- array.pop(priceLows)
- if not na(pivotHigh) and barstate.isconfirmed
- array.unshift(rsiHighs, pivotHigh)
- array.unshift(priceHighs, high[lookbackRight])
- if array.size(rsiHighs) > 10
- array.pop(rsiHighs)
- array.pop(priceHighs)
- // Divergenz-Prüfung
- bullDivergence = false
- bearDivergence = false
- if calculateDivergence and array.size(rsiLows) >= 2 and array.size(priceLows) >= 2 and barstate.isconfirmed
- rsi_current_low = array.get(rsiLows, 0)
- rsi_prev_low = array.get(rsiLows, 1)
- price_current_low = array.get(priceLows, 0)
- price_prev_low = array.get(priceLows, 1)
- // Reguläre bullische Divergenz: Preis macht niedrigere Tiefs, RSI macht höhere Tiefs
- if price_current_low < price_prev_low and rsi_current_low > rsi_prev_low
- bullDivergence := true
- if calculateDivergence and array.size(rsiHighs) >= 2 and array.size(priceHighs) >= 2 and barstate.isconfirmed
- rsi_current_high = array.get(rsiHighs, 0)
- rsi_prev_high = array.get(rsiHighs, 1)
- price_current_high = array.get(priceHighs, 0)
- price_prev_high = array.get(priceHighs, 1)
- // Reguläre bärische Divergenz: Preis macht höhere Hochs, RSI macht niedrigere Hochs
- if price_current_high > price_prev_high and rsi_current_high < rsi_prev_high
- bearDivergence := true
- // Divergenz-Plots mit Verzögerung
- if bullDivergence and barstate.isconfirmed
- label.new(bar_index - lookbackRight, rsi, text="BullDiv", color=color.green, textcolor=color.white, size=size.tiny)
- if bearDivergence and barstate.isconfirmed
- label.new(bar_index - lookbackRight, rsi, text="BearDiv", color=color.red, textcolor=color.white, size=size.tiny)
- // Signal-Berechnung mit strikten Anti-Repainting-Mechanismen
- bool buySignalConfirmed = false
- bool sellSignalConfirmed = false
- // Crossover- und Crossunder-Berechnungen
- crossoverDetected = ta.crossover(rsi, smoothingMA)
- crossunderDetected = ta.crossunder(rsi, smoothingMA)
- // Signal nur als bestätigt betrachten, wenn es auf einem abgeschlossenen Balken stattfindet
- if barstate.isconfirmed
- maFilterBuy = not useMovingAverageFilter or (useMovingAverageFilter and close > longTermMA)
- maFilterSell = not useMovingAverageFilter or (useMovingAverageFilter and close < longTermMA)
- buySignalConfirmed := enableMA and not na(smoothingMA) and crossoverDetected and not na(rsi) and maFilterBuy
- sellSignalConfirmed := enableMA and not na(smoothingMA) and crossunderDetected and not na(rsi) and maFilterSell and tradingDirectionInput == "Long and Short"
- // Signale plotten, nur auf bestätigten Balken
- if showMACrossSignals and buySignalConfirmed
- label.new(bar_index, rsi, text="BUY", color=buyColorInput, textcolor=color.white, size=size.small)
- if showMACrossSignals and sellSignalConfirmed
- label.new(bar_index, rsi, text="SELL", color=sellColorInput, textcolor=color.white,size=size.small)
- // Trade-Eintrittslogik - Nur auf bestätigten Balken
- if buySignalConfirmed and strategy.position_size <= 0
- strategy.entry("RSI_Long", strategy.long, comment="RSI MA Cross Long")
- if sellSignalConfirmed and strategy.position_size >= 0
- strategy.entry("RSI_Short", strategy.short, comment="RSI MA Cross Short")
- // Exit-Logik
- entryPrice = strategy.position_avg_price
- longHardStopLevel = entryPrice * (1 - maxLossPercent)
- shortHardStopLevel = entryPrice * (1 + maxLossPercent)
- // Trailing Stop Logik
- trailPointsLong = if useTrailingStop and strategy.position_size > 0 and not na(entryPrice) and not na(atrValue)
- trailType == "Percent" ? entryPrice * trailPercent / syminfo.mintick : atrValue * trailAtrMult / syminfo.mintick
- else
- na
- trailPointsShort = if useTrailingStop and strategy.position_size < 0 and not na(entryPrice) and not na(atrValue)
- trailType == "Percent" ? entryPrice * trailPercent / syminfo.mintick : atrValue * trailAtrMult / syminfo.mintick
- else
- na
- activationOffsetLong = if useTrailingStop and strategy.position_size > 0 and not na(entryPrice) and not na(atrValue)
- trailType == "Percent" ? entryPrice * trailActivationPercent / syminfo.mintick : atrValue * trailActivationAtr / syminfo.mintick
- else
- na
- activationOffsetShort = if useTrailingStop and strategy.position_size < 0 and not na(entryPrice) and not na(atrValue)
- trailType == "Percent" ? entryPrice * trailActivationPercent / syminfo.mintick : atrValue * trailActivationAtr / syminfo.mintick
- else
- na
- // MA-basierte Exits, nur auf bestätigten Balken
- longExitOnMA = useMAExitCondition and strategy.position_size > 0 and close < longTermMA and barstate.isconfirmed
- shortExitOnMA = useMAExitCondition and strategy.position_size < 0 and close > longTermMA and barstate.isconfirmed
- if longExitOnMA
- strategy.close("RSI_Long", comment="Exit Long (Price < Variable MA)")
- if shortExitOnMA
- strategy.close("RSI_Short", comment="Exit Short (Price > Variable MA)")
- // Exit-Logik für Trailing-Stops und harte Stop-Loss
- if strategy.position_size > 0
- strategy.exit(id="Long_Exit", from_entry="RSI_Long",
- stop=useHardStopLoss ? longHardStopLevel : na,
- trail_points=trailPointsLong,
- trail_offset=activationOffsetLong)
- if strategy.position_size < 0
- strategy.exit(id="Short_Exit", from_entry="RSI_Short",
- stop=useHardStopLoss ? shortHardStopLevel : na,
- trail_points=trailPointsShort,
- trail_offset=activationOffsetShort)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement