Advertisement
Seko96

Untitled

May 11th, 2025 (edited)
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.77 KB | None | 0 0
  1. //@version=5
  2.  
  3. strategy(
  4.      title="Nostra 6.0 with RSI & Variable MA Filters (Strict Non-Repainting)",
  5.      shorttitle="Nostra 6.0 Strict Non-Repainting",
  6.      overlay=false,
  7.      format=format.price,
  8.      precision=2,
  9.      pyramiding=0,
  10.      initial_capital=500,
  11.      default_qty_type=strategy.percent_of_equity,
  12.      default_qty_value=100,
  13.      commission_type=strategy.commission.percent,
  14.      commission_value=0.02,
  15.      max_bars_back=5000
  16.      )
  17.  
  18. // Trading Richtung Option
  19. GRP_DIRECTION = "Trading Direction"
  20. tradingDirectionInput = input.string("Long and Short", "Trading Direction", options=["Long only", "Long and Short"], group=GRP_DIRECTION)
  21.  
  22. GRP_RSI = "RSI Settings"
  23. rsiLengthInput = input.int(2, minval=1, title="RSI Length", group=GRP_RSI)
  24. rsiSourceInput = input.source(close, "Source", group=GRP_RSI)
  25. calculateDivergence = input.bool(true, title="Calculate Divergence", group=GRP_RSI, display = display.data_window)
  26.  
  27. GRP_SMOOTH = "Smoothing"
  28. TT_BB = "Only applies when 'SMA + Bollinger Bands' is selected."
  29. maTypeInput = input.string("VWMA", "Type", options = ["None", "SMA", "SMA + Bollinger Bands", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group = GRP_SMOOTH, display = display.data_window)
  30. maLengthInput = input.int(2, "Length", group = GRP_SMOOTH, display = display.data_window)
  31. var enableMA = maTypeInput != "None"
  32.  
  33. GRP_CALC = "Calculation"
  34. timeframeInput = input.timeframe("", "Timeframe", group=GRP_CALC)
  35.  
  36. GRP_EXIT = "Exit Strategy"
  37. useTrailingStop = input.bool(true, "Use Trailing Stop Loss", group=GRP_EXIT)
  38.  
  39. exitType = input.string("Percent", "Exit Type (Trailing Stop)", options=["Percent", "ATR"], group=GRP_EXIT)
  40. atrLength = input.int(14, "ATR Length (if used)", group=GRP_EXIT, minval=1)
  41.  
  42. trailType = input.string("Percent", "Trailing Stop Type", options=["Percent", "ATR"], group=GRP_EXIT)
  43. trailPercent = input.float(1.0, "Trailing Stop %", group=GRP_EXIT, minval=0.1, step=0.1) / 100
  44. trailAtrMult = input.float(1.0, "Trailing Stop ATR Multiple", group=GRP_EXIT, minval=0.1, step=0.1)
  45. trailActivationPercent = input.float(0.1, "Trailing Activation % Profit", group=GRP_EXIT, minval=0.0, step=0.1) / 100
  46. trailActivationAtr = input.float(5.0, "Trailing Activation ATR Profit", group=GRP_EXIT, minval=0.0, step=0.1)
  47.  
  48. GRP_MA_EXIT = "Variable MA Exit Condition"
  49. useMAExitCondition = input.bool(true, "Exit trades when price crosses Variable MA", group=GRP_MA_EXIT)
  50. useHardStopLoss = input.bool(true, "Use hard stop-loss independently from MA", group=GRP_MA_EXIT)
  51. maxLossPercent = input.float(3.0, "Maximum Loss % (Hard Stop)", minval=0.1, step=0.1, group=GRP_MA_EXIT) / 100
  52.  
  53. GRP_SIG = "Signals (Visuals)"
  54. showMACrossSignals = input.bool(true, title="Show MA Crossover Signal Labels", group=GRP_SIG)
  55. buyColorInput = input.color(color.blue, "Buy Signal Color", group=GRP_SIG, inline="sigcol")
  56. sellColorInput = input.color(color.red, "Sell Signal Color", group=GRP_SIG, inline="sigcol")
  57.  
  58. GRP_MA_FILTER = "Variable Moving Average Filter"
  59. useMovingAverageFilter = input.bool(true, "Use Variable MA Filter", group=GRP_MA_FILTER)
  60. maFilterLength = input.int(40, "MA Length", group=GRP_MA_FILTER)
  61. maFilterType = input.string("VWMA", "MA Type", options=["SMA", "EMA", "SMMA (RMA)", "WMA", "VWMA"], group=GRP_MA_FILTER)
  62.  
  63. showInputsInStatusLine = input.bool(true, "Inputs in status line", group="INPUT VALUES")
  64.  
  65. // Strikte Anti-Repainting Logik
  66. // Diese Funktion verwendet nur bestätigte historische Daten
  67. strict_security(_symbol, _res, _src) =>
  68.     _res_gap = timeframe.in_seconds(_res) / timeframe.in_seconds(timeframe.period)
  69.     _src_data = request.security(_symbol, _res, _src, lookahead=barmerge.lookahead_off)
  70.     _need_past_value = barstate.isrealtime or barstate.islast or (barstate.ishistory and bar_index % math.round(_res_gap) == 0)
  71.     _need_past_value ? _src_data[1] : _src_data
  72.  
  73. // RSI-Berechnung
  74. f_rsi(src, len) =>
  75.     change = ta.change(src)
  76.     up = ta.rma(math.max(change, 0), len)
  77.     down = ta.rma(-math.min(change, 0), len)
  78.     down == 0 ? 100 : up == 0 ? 0 : 100 - (100 / (1 + up / down))
  79.  
  80. // MA-Berechnung
  81. ma(source, length, MAtype) =>
  82.     switch MAtype
  83.         "SMA" => ta.sma(source, length)
  84.         "EMA" => ta.ema(source, length)
  85.         "SMMA (RMA)" => ta.rma(source, length)
  86.         "WMA" => ta.wma(source, length)
  87.         "VWMA" => ta.vwma(source, length)
  88.         "SMA + Bollinger Bands" => ta.sma(source, length)
  89.         => na
  90.  
  91. // Smoothing-MA für RSI
  92. f_smoothingMA(rsiVal, len, type) =>
  93.     enableMA_func = type != "None"
  94.     enableMA_func ? ma(rsiVal, len, type) : na
  95.  
  96. // Timeframe-Auswahl
  97. requestTf = timeframeInput == "" ? timeframe.period : timeframeInput
  98.  
  99. // Berechnung der RSI und Smoothing MA Werte mit strikter anti-repainting Logik
  100. rsi_current = f_rsi(rsiSourceInput, rsiLengthInput)
  101. smoothingMA_current = f_smoothingMA(rsi_current, maLengthInput, maTypeInput)
  102.  
  103. // RSI und Smoothing MA verwenden strikte Anti-Repainting Funktion
  104. rsi_mtf = strict_security(syminfo.tickerid, requestTf, rsi_current)
  105. smoothingMA_mtf = strict_security(syminfo.tickerid, requestTf, smoothingMA_current)
  106.  
  107. // LongTermMA berechnen
  108. longTermMA_current = ma(close, maFilterLength, maFilterType)
  109. // LongTermMA mit strikter Anti-Repainting Funktion
  110. longTermMA = strict_security(syminfo.tickerid, requestTf, longTermMA_current)
  111.  
  112. // Werte für nächste Berechnungen sichern
  113. rsi = rsi_mtf
  114. smoothingMA = smoothingMA_mtf
  115.  
  116. // ATR für Trailing Stops
  117. atrValue = ta.atr(atrLength)
  118.  
  119. // Plot RSI mit Bändern
  120. rsiPlot = plot(rsi, "RSI", color=#7E57C2)
  121. rsiUpperBand = hline(70, "RSI Upper Band", color=#787B86)
  122. midline = hline(50, "RSI Middle Band", color=color.new(#787B86, 50))
  123. rsiLowerBand = hline(30, "RSI Lower Band", color=#787B86)
  124. fill(rsiUpperBand, rsiLowerBand, color=color.rgb(126, 87, 194, 90), title="RSI Background Fill")
  125. midLinePlot = plot(50, color = na, editable = false, display = display.none)
  126. fill(rsiPlot, midLinePlot, 100, 70, top_color = color.new(color.green, 90), bottom_color = color.new(color.green, 100), title = "Overbought Gradient Fill")
  127. fill(rsiPlot, midLinePlot, 30, 0, top_color = color.new(color.red, 100), bottom_color = color.new(color.red, 90), title = "Oversold Gradient Fill")
  128. plot(enableMA and not na(smoothingMA) ? smoothingMA : na, "RSI-based MA", color=color.yellow, editable = true)
  129.  
  130. // Überarbeitete Pivot-Berechnung für strikte Anti-Repainting-Unterstützung
  131. lookbackRight = 5
  132. lookbackLeft = 5
  133. rangeUpper = 60
  134. rangeLower = 5
  135.  
  136. _inRange(cond) =>
  137.     bars = ta.barssince(cond)
  138.     rangeLower <= bars and bars <= rangeUpper
  139.  
  140. // Feste Verzögerung für Pivot-Berechnung - Entscheidend gegen Repainting
  141. var rsi_history = array.new_float(300, 0.0)
  142. array.unshift(rsi_history, rsi)
  143. if array.size(rsi_history) > 300
  144.     array.pop(rsi_history)
  145.  
  146. get_historical_rsi(offset) =>
  147.     index = math.min(offset, array.size(rsi_history) - 1)
  148.     array.get(rsi_history, index)
  149.  
  150. // Sehr strikte Pivot-Berechnung mit festen Verzögerungen
  151. // Declare the pivotLow and pivotHigh as float variables with initial na value
  152. var float pivotLow = na
  153. var float pivotHigh = na
  154.  
  155. // Nur berechnen, wenn genügend Daten vorhanden sind und wir uns auf einem bestätigten Balken befinden
  156. if barstate.isconfirmed and array.size(rsi_history) >= (lookbackLeft + lookbackRight + 1)
  157.     isLowest = true
  158.     isHighest = true
  159.  
  160.     for i = 0 to (lookbackLeft + lookbackRight)
  161.         if i != lookbackRight
  162.             val = get_historical_rsi(i)
  163.             mid = get_historical_rsi(lookbackRight)
  164.             if val < mid
  165.                 isHighest := false
  166.             if val > mid
  167.                 isLowest := false
  168.    
  169.     if isLowest
  170.         pivotLow := get_historical_rsi(lookbackRight)
  171.     if isHighest
  172.         pivotHigh := get_historical_rsi(lookbackRight)
  173.  
  174. // Divergenz-Werte speichern
  175. var rsiLows = array.new_float(10, 0.0)
  176. var priceLows = array.new_float(10, 0.0)
  177. var rsiHighs = array.new_float(10, 0.0)
  178. var priceHighs = array.new_float(10, 0.0)
  179.  
  180. // Neue Pivots in Array einfügen
  181. if not na(pivotLow) and barstate.isconfirmed
  182.     array.unshift(rsiLows, pivotLow)
  183.     array.unshift(priceLows, low[lookbackRight])
  184.     if array.size(rsiLows) > 10
  185.         array.pop(rsiLows)
  186.         array.pop(priceLows)
  187.  
  188. if not na(pivotHigh) and barstate.isconfirmed
  189.     array.unshift(rsiHighs, pivotHigh)
  190.     array.unshift(priceHighs, high[lookbackRight])
  191.     if array.size(rsiHighs) > 10
  192.         array.pop(rsiHighs)
  193.         array.pop(priceHighs)
  194.  
  195. // Divergenz-Prüfung
  196. bullDivergence = false
  197. bearDivergence = false
  198.  
  199. if calculateDivergence and array.size(rsiLows) >= 2 and array.size(priceLows) >= 2 and barstate.isconfirmed
  200.     rsi_current_low = array.get(rsiLows, 0)
  201.     rsi_prev_low = array.get(rsiLows, 1)
  202.     price_current_low = array.get(priceLows, 0)
  203.     price_prev_low = array.get(priceLows, 1)
  204.    
  205.     // Reguläre bullische Divergenz: Preis macht niedrigere Tiefs, RSI macht höhere Tiefs
  206.     if price_current_low < price_prev_low and rsi_current_low > rsi_prev_low
  207.         bullDivergence := true
  208.  
  209. if calculateDivergence and array.size(rsiHighs) >= 2 and array.size(priceHighs) >= 2 and barstate.isconfirmed
  210.     rsi_current_high = array.get(rsiHighs, 0)
  211.     rsi_prev_high = array.get(rsiHighs, 1)
  212.     price_current_high = array.get(priceHighs, 0)
  213.     price_prev_high = array.get(priceHighs, 1)
  214.    
  215.     // Reguläre bärische Divergenz: Preis macht höhere Hochs, RSI macht niedrigere Hochs
  216.     if price_current_high > price_prev_high and rsi_current_high < rsi_prev_high
  217.         bearDivergence := true
  218.  
  219. // Divergenz-Plots mit Verzögerung
  220. if bullDivergence and barstate.isconfirmed
  221.     label.new(bar_index - lookbackRight, rsi, text="BullDiv", color=color.green, textcolor=color.white, size=size.tiny)
  222.  
  223. if bearDivergence and barstate.isconfirmed
  224.     label.new(bar_index - lookbackRight, rsi, text="BearDiv", color=color.red, textcolor=color.white, size=size.tiny)
  225.  
  226. // Signal-Berechnung mit strikten Anti-Repainting-Mechanismen
  227. bool buySignalConfirmed = false
  228. bool sellSignalConfirmed = false
  229.  
  230. // Crossover- und Crossunder-Berechnungen
  231. crossoverDetected = ta.crossover(rsi, smoothingMA)
  232. crossunderDetected = ta.crossunder(rsi, smoothingMA)
  233.  
  234. // Signal nur als bestätigt betrachten, wenn es auf einem abgeschlossenen Balken stattfindet
  235. if barstate.isconfirmed
  236.     maFilterBuy = not useMovingAverageFilter or (useMovingAverageFilter and close > longTermMA)
  237.     maFilterSell = not useMovingAverageFilter or (useMovingAverageFilter and close < longTermMA)
  238.    
  239.     buySignalConfirmed := enableMA and not na(smoothingMA) and crossoverDetected and not na(rsi) and maFilterBuy
  240.     sellSignalConfirmed := enableMA and not na(smoothingMA) and crossunderDetected and not na(rsi) and maFilterSell and tradingDirectionInput == "Long and Short"
  241.  
  242. // Signale plotten, nur auf bestätigten Balken
  243. if showMACrossSignals and buySignalConfirmed
  244.     label.new(bar_index, rsi, text="BUY", color=buyColorInput, textcolor=color.white, size=size.small)
  245.  
  246. if showMACrossSignals and sellSignalConfirmed
  247.     label.new(bar_index, rsi, text="SELL", color=sellColorInput, textcolor=color.white,size=size.small)
  248.  
  249. // Trade-Eintrittslogik - Nur auf bestätigten Balken
  250. if buySignalConfirmed and strategy.position_size <= 0
  251.     strategy.entry("RSI_Long", strategy.long, comment="RSI MA Cross Long")
  252.  
  253. if sellSignalConfirmed and strategy.position_size >= 0
  254.     strategy.entry("RSI_Short", strategy.short, comment="RSI MA Cross Short")
  255.  
  256. // Exit-Logik
  257. entryPrice = strategy.position_avg_price
  258. longHardStopLevel = entryPrice * (1 - maxLossPercent)
  259. shortHardStopLevel = entryPrice * (1 + maxLossPercent)
  260.  
  261. // Trailing Stop Logik
  262. trailPointsLong = if useTrailingStop and strategy.position_size > 0 and not na(entryPrice) and not na(atrValue)
  263.     trailType == "Percent" ? entryPrice * trailPercent / syminfo.mintick : atrValue * trailAtrMult / syminfo.mintick
  264. else
  265.     na
  266.  
  267. trailPointsShort = if useTrailingStop and strategy.position_size < 0 and not na(entryPrice) and not na(atrValue)
  268.     trailType == "Percent" ? entryPrice * trailPercent / syminfo.mintick : atrValue * trailAtrMult / syminfo.mintick
  269. else
  270.     na
  271.  
  272. activationOffsetLong = if useTrailingStop and strategy.position_size > 0 and not na(entryPrice) and not na(atrValue)
  273.     trailType == "Percent" ? entryPrice * trailActivationPercent / syminfo.mintick : atrValue * trailActivationAtr / syminfo.mintick
  274. else
  275.     na
  276.  
  277. activationOffsetShort = if useTrailingStop and strategy.position_size < 0 and not na(entryPrice) and not na(atrValue)
  278.     trailType == "Percent" ? entryPrice * trailActivationPercent / syminfo.mintick : atrValue * trailActivationAtr / syminfo.mintick
  279. else
  280.     na
  281.  
  282. // MA-basierte Exits, nur auf bestätigten Balken
  283. longExitOnMA = useMAExitCondition and strategy.position_size > 0 and close < longTermMA and barstate.isconfirmed
  284. shortExitOnMA = useMAExitCondition and strategy.position_size < 0 and close > longTermMA and barstate.isconfirmed
  285.  
  286. if longExitOnMA
  287.     strategy.close("RSI_Long", comment="Exit Long (Price < Variable MA)")
  288.  
  289. if shortExitOnMA
  290.     strategy.close("RSI_Short", comment="Exit Short (Price > Variable MA)")
  291.  
  292. // Exit-Logik für Trailing-Stops und harte Stop-Loss
  293. if strategy.position_size > 0
  294.     strategy.exit(id="Long_Exit", from_entry="RSI_Long",
  295.          stop=useHardStopLoss ? longHardStopLevel : na,
  296.          trail_points=trailPointsLong,
  297.          trail_offset=activationOffsetLong)
  298.  
  299. if strategy.position_size < 0
  300.     strategy.exit(id="Short_Exit", from_entry="RSI_Short",
  301.          stop=useHardStopLoss ? shortHardStopLevel : na,
  302.          trail_points=trailPointsShort,
  303.          trail_offset=activationOffsetShort)
  304.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement