|
| 1 | +import { compilePine as compileBase } from "./compiler-v13"; |
| 2 | +import type { StrategyConfig } from "./types"; |
| 3 | + |
| 4 | +const appendForceOverlay = (line: string): string => { |
| 5 | + if (line.includes("force_overlay=")) return line; |
| 6 | + return `${line.slice(0, -1)}, force_overlay=true)`; |
| 7 | +}; |
| 8 | + |
| 9 | +export function compilePine(config: StrategyConfig): string { |
| 10 | + let code = compileBase(config); |
| 11 | + const useIntegratedRsiPane = config.name === "Fast EMA Scalper" && config.outputMode === "indicator"; |
| 12 | + |
| 13 | + if (!useIntegratedRsiPane) return code; |
| 14 | + |
| 15 | + const declaration = `indicator("${config.name}", overlay=true, max_labels_count=500, max_lines_count=500)`; |
| 16 | + const paneDeclaration = `indicator("${config.name}", overlay=false, max_labels_count=500, max_lines_count=500)`; |
| 17 | + if (!code.includes(declaration)) { |
| 18 | + throw new Error("Compiler transform anchor missing: Fast EMA Scalper indicator declaration"); |
| 19 | + } |
| 20 | + code = code.replace(declaration, paneDeclaration); |
| 21 | + |
| 22 | + let overlayVisuals = 0; |
| 23 | + code = code.replace(/^(bgcolor|plot)\(.*\)$/gm, (line) => { |
| 24 | + overlayVisuals += 1; |
| 25 | + return appendForceOverlay(line); |
| 26 | + }); |
| 27 | + |
| 28 | + code = code.replace(/^\s*label\.new\(.*\)$/gm, (line) => { |
| 29 | + overlayVisuals += 1; |
| 30 | + return appendForceOverlay(line); |
| 31 | + }); |
| 32 | + |
| 33 | + if (config.execution.showDashboard) { |
| 34 | + const tablePattern = /var table dashboard = table\.new\(position\.top_right, 2, (\d+), border_width=1\)/; |
| 35 | + if (!tablePattern.test(code)) { |
| 36 | + throw new Error("Compiler transform anchor missing: Fast EMA Scalper dashboard table"); |
| 37 | + } |
| 38 | + code = code.replace( |
| 39 | + tablePattern, |
| 40 | + "var table dashboard = table.new(position.top_right, 2, $1, border_width=1, force_overlay=true)" |
| 41 | + ); |
| 42 | + } |
| 43 | + |
| 44 | + if (overlayVisuals === 0) { |
| 45 | + throw new Error("Compiler transform anchor missing: Fast EMA Scalper overlay visuals"); |
| 46 | + } |
| 47 | + |
| 48 | + const alertsAnchor = "// === Alerts ==="; |
| 49 | + if (!code.includes(alertsAnchor)) { |
| 50 | + throw new Error("Compiler transform anchor missing: alerts section"); |
| 51 | + } |
| 52 | + |
| 53 | + const divergencePane = `// === Integrated RSI divergence pane === |
| 54 | +divRsiLength = input.int(14, "Divergence RSI period", minval=1) |
| 55 | +divPivotLeft = input.int(5, "Divergence pivot left", minval=1) |
| 56 | +divPivotRight = input.int(5, "Divergence pivot right", minval=1) |
| 57 | +divRangeMinimum = input.int(5, "Divergence minimum pivot range", minval=1) |
| 58 | +divRangeMaximum = input.int(60, "Divergence maximum pivot range", minval=2) |
| 59 | +showRegularBullDiv = input.bool(true, "Show regular bullish divergence") |
| 60 | +showHiddenBullDiv = input.bool(true, "Show hidden bullish divergence") |
| 61 | +showRegularBearDiv = input.bool(true, "Show regular bearish divergence") |
| 62 | +showHiddenBearDiv = input.bool(true, "Show hidden bearish divergence") |
| 63 | +
|
| 64 | +divRsi = ta.rsi(close, divRsiLength) |
| 65 | +divRegularBullColor = color.green |
| 66 | +divRegularBearColor = color.red |
| 67 | +divHiddenBullColor = color.new(color.green, 35) |
| 68 | +divHiddenBearColor = color.new(color.red, 35) |
| 69 | +divTransparentColor = color.new(color.white, 100) |
| 70 | +
|
| 71 | +plot(divRsi, "RSI divergence", linewidth=2, color=color.rgb(41, 98, 255)) |
| 72 | +divMiddleLine = hline(50, "RSI middle", color=color.rgb(120, 123, 134), linestyle=hline.style_dotted) |
| 73 | +divOverboughtLine = hline(70, "RSI overbought", color=color.rgb(120, 123, 134), linestyle=hline.style_dotted) |
| 74 | +divOversoldLine = hline(30, "RSI oversold", color=color.rgb(120, 123, 134), linestyle=hline.style_dotted) |
| 75 | +fill(divOverboughtLine, divOversoldLine, "RSI divergence background", color=color.rgb(33, 150, 243, 90)) |
| 76 | +
|
| 77 | +divPivotLowFound = not na(ta.pivotlow(divRsi, divPivotLeft, divPivotRight)) |
| 78 | +divPivotHighFound = not na(ta.pivothigh(divRsi, divPivotLeft, divPivotRight)) |
| 79 | +
|
| 80 | +divInRange(condition) => |
| 81 | + divBarsSince = ta.barssince(condition) |
| 82 | + divRangeMinimum <= divBarsSince and divBarsSince <= divRangeMaximum |
| 83 | +
|
| 84 | +divPreviousLowInRange = divInRange(divPivotLowFound[1]) |
| 85 | +divRsiHigherLow = divRsi[divPivotRight] > ta.valuewhen(divPivotLowFound, divRsi[divPivotRight], 1) and divPreviousLowInRange |
| 86 | +divPriceLowerLow = low[divPivotRight] < ta.valuewhen(divPivotLowFound, low[divPivotRight], 1) |
| 87 | +divRegularBullAlert = divPriceLowerLow and divRsiHigherLow and divPivotLowFound |
| 88 | +divRegularBull = showRegularBullDiv and divRegularBullAlert |
| 89 | +plot(divPivotLowFound ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Regular bullish divergence", linewidth=2, color=divRegularBull ? divRegularBullColor : divTransparentColor) |
| 90 | +plotshape(divRegularBull ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Regular bullish label", text="Bull", style=shape.labelup, location=location.absolute, color=divRegularBullColor, textcolor=color.white) |
| 91 | +
|
| 92 | +divRsiLowerLow = divRsi[divPivotRight] < ta.valuewhen(divPivotLowFound, divRsi[divPivotRight], 1) and divPreviousLowInRange |
| 93 | +divPriceHigherLow = low[divPivotRight] > ta.valuewhen(divPivotLowFound, low[divPivotRight], 1) |
| 94 | +divHiddenBullAlert = divPriceHigherLow and divRsiLowerLow and divPivotLowFound |
| 95 | +divHiddenBull = showHiddenBullDiv and divHiddenBullAlert |
| 96 | +plot(divPivotLowFound ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Hidden bullish divergence", linewidth=2, color=divHiddenBull ? divHiddenBullColor : divTransparentColor) |
| 97 | +plotshape(divHiddenBull ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Hidden bullish label", text="H Bull", style=shape.labelup, location=location.absolute, color=divHiddenBullColor, textcolor=color.white) |
| 98 | +
|
| 99 | +divPreviousHighInRange = divInRange(divPivotHighFound[1]) |
| 100 | +divRsiLowerHigh = divRsi[divPivotRight] < ta.valuewhen(divPivotHighFound, divRsi[divPivotRight], 1) and divPreviousHighInRange |
| 101 | +divPriceHigherHigh = high[divPivotRight] > ta.valuewhen(divPivotHighFound, high[divPivotRight], 1) |
| 102 | +divRegularBearAlert = divPriceHigherHigh and divRsiLowerHigh and divPivotHighFound |
| 103 | +divRegularBear = showRegularBearDiv and divRegularBearAlert |
| 104 | +plot(divPivotHighFound ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Regular bearish divergence", linewidth=2, color=divRegularBear ? divRegularBearColor : divTransparentColor) |
| 105 | +plotshape(divRegularBear ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Regular bearish label", text="Bear", style=shape.labeldown, location=location.absolute, color=divRegularBearColor, textcolor=color.white) |
| 106 | +
|
| 107 | +divRsiHigherHigh = divRsi[divPivotRight] > ta.valuewhen(divPivotHighFound, divRsi[divPivotRight], 1) and divPreviousHighInRange |
| 108 | +divPriceLowerHigh = high[divPivotRight] < ta.valuewhen(divPivotHighFound, high[divPivotRight], 1) |
| 109 | +divHiddenBearAlert = divPriceLowerHigh and divRsiHigherHigh and divPivotHighFound |
| 110 | +divHiddenBear = showHiddenBearDiv and divHiddenBearAlert |
| 111 | +plot(divPivotHighFound ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Hidden bearish divergence", linewidth=2, color=divHiddenBear ? divHiddenBearColor : divTransparentColor) |
| 112 | +plotshape(divHiddenBear ? divRsi[divPivotRight] : na, offset=-divPivotRight, title="Hidden bearish label", text="H Bear", style=shape.labeldown, location=location.absolute, color=divHiddenBearColor, textcolor=color.white) |
| 113 | +
|
| 114 | +alertcondition(divRegularBullAlert, "Regular bullish divergence", "A new regular bullish RSI divergence was confirmed.") |
| 115 | +alertcondition(divHiddenBullAlert, "Hidden bullish divergence", "A new hidden bullish RSI divergence was confirmed.") |
| 116 | +alertcondition(divRegularBearAlert, "Regular bearish divergence", "A new regular bearish RSI divergence was confirmed.") |
| 117 | +alertcondition(divHiddenBearAlert, "Hidden bearish divergence", "A new hidden bearish RSI divergence was confirmed.") |
| 118 | +
|
| 119 | +`; |
| 120 | + |
| 121 | + return code.replace(alertsAnchor, divergencePane + alertsAnchor); |
| 122 | +} |
0 commit comments