techwitheddie

blackdaddy edge

Sep 3rd, 2026
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
TypeScript 25.58 KB | Cryptocurrency | 0 0
  1. //@version=6
  2. strategy("Black Edge Strategy V5.10.2b",
  3. overlay=true,
  4. pyramiding=0,
  5. calc_on_every_tick=true)
  6.  
  7.  
  8. // ============================================================
  9. // CHANGELOG V5.10.2b (vs V5.10.2)
  10. // ------------------------------------------------------------
  11. // CHANGE — EMA 9 added
  12. //          New ema9Len input + ema9 series, plotted on-chart.
  13. //          Informational only — not referenced by any setup's
  14. //          detection logic. For Eddie's discretionary reading.
  15. //
  16. // REMOVE — S1 and S1+ removed entirely
  17. //          Deleted the S1+ Hammer/Shooting Star structure block,
  18. //          the SETUP 1 (Pullback + Rejection + Confirmation)
  19. //          block, and the SETUP 1+ (Hammer/Shooting Star +
  20. //          Volume + Confirmation) block. longS1/shortS1 and
  21. //          longS1Plus/shortS1Plus no longer exist as variables.
  22. //          Removed downstream: S1/S1+ from FINAL SIGNALS,
  23. //          PREVIEW vs CONFIRMED state, on-chart LABELS, and
  24. //          WEBHOOK ALERTS. Also removed the now-dangling
  25. //          `not longS1 and not longS1Plus` / `not shortS1 and
  26. //          not shortS1Plus` clauses from the S2R exclusion guard
  27. //          — those referenced variables that no longer exist.
  28. //          S2R ignition sources were already S2/S3 only (see
  29. //          NOTE 3 in V5.9 changelog below), so this is a pure
  30. //          cleanup with no change to S2R's firing behavior.
  31. //          bullReject/bearReject (CANDLE STRUCTURE block) are
  32. //          left in place even though S1 was their only consumer
  33. //          — kept as reference building blocks for a future S1
  34. //          redesign, not deleted by default. Flag if you want
  35. //          them stripped too.
  36. //
  37. // REMOVE — S2R webhook alert removed
  38. //          S2R keeps full detection, strategy entries, and
  39. //          on-chart labels — only the outbound alert() firing
  40. //          for confirmedLongS2R/confirmedShortS2R is gone.
  41. //          Matches the 22/08 precedent already applied on the
  42. //          n8n side (S2R removed from Secondary/Shadow/Webhook
  43. //          Layer 3 assessment). Eddie reads S2R on-chart at his
  44. //          discretion; it no longer reaches Telegram.
  45. //
  46. // CHANGE — Emojis removed from S2/S3/S2R on-chart labels
  47. //          plotshape `text=` values stripped of emoji prefixes
  48. //          (e.g. "🔥 S2" -> "S2", "PRE ⚡ S3" -> "PRE S3").
  49. //          alert() JSON payloads never contained emojis, so
  50. //          Telegram-side formatting is unaffected — Telegram
  51. //          keeps its own icons per Format Telegram V1.
  52. //
  53. // CHANGE — strategy() title renamed to "Black Edge Strategy"
  54. //          Was "Core Setup Strategy" — brand alignment with the
  55. //          BlackDaddy Edge System naming used across Notion/docs.
  56. //          File name on disk unchanged (setup-family naming).
  57. // ============================================================
  58.  
  59. // ============================================================
  60. // CHANGELOG V5.10.2 (vs V5.10.1)
  61. // ------------------------------------------------------------
  62. // FIX — S2 takes priority over S3 when both conditions overlap
  63. //       On bars where price breaks high[1] AND SMA8/SMA21 cross
  64. //       fires simultaneously, V5.10.1 classified the bar as S3
  65. //       (cross ignition) because S3's body threshold (0.4) is
  66. //       lower than S2's (0.5). A medium-bodied breakout candle
  67. //       would satisfy S3 but not S2, mislabelling a momentum
  68. //       ignition as a cross ignition.
  69. //       Observed on: XLMUSDT 2026-05-28 30m — S3 printed on a
  70. //       clean reclaim of 0.1820 with expanding volume. Correct
  71. //       classification is S2 (momentum ignition). Trader waited
  72. //       for a pullback to MAs (S3 playbook) and missed the move.
  73. //       Fix: S3 now excludes longS2/shortS2 — if price breaks
  74. //       high[1]/low[1] with a body > 50% range on the same bar
  75. //       as a cross, S2 fires. S3 only fires when no S2 is present.
  76. //       Semantic rationale: a bar that breaks the prior high on
  77. //       a MA cross is a momentum event, not a cross event.
  78. // ============================================================
  79.  
  80. // ============================================================
  81. // CHANGELOG V5.10.1 (vs V5.10)
  82. // ------------------------------------------------------------
  83. // FIX — S2R mutual exclusion with all higher-priority setups
  84. //       With maxLateATR increased to 2.0 in V5.10, S2R and S1
  85. //       could both fire on the same bar — two labels printed
  86. //       on the chart. This created a mismatch with N8N scanners
  87. //       which use a priority chain (S1 > S1+ > S2 > S3 > S2R)
  88. //       and only send one Telegram alert per bar.
  89. //       Fix: S2R now excludes all four higher-priority setups:
  90. //         and not longS1 and not longS1Plus and not longS2 and not longS3
  91. //       S2/S3 overlap with S2R is structurally rare (breakout
  92. //       candle vs. pause candle are contradictory) but guarded
  93. //       for full alignment with the N8N priority chain.
  94. // ============================================================
  95.  
  96. // ============================================================
  97. // CHANGELOG V5.10 (vs V5.9)
  98. // ------------------------------------------------------------
  99. // CHANGE — maxLateATR default increased from 1.5 to 2.0
  100. //          V5.9 suppressed valid S2 and S2R signals on strong
  101. //          trending coins where price moved beyond 1.5 ATR from
  102. //          EMA50 before the setup confirmed. Observed on:
  103. //          - BNBUSDT 2026-05-29: two S2s fired, relaunch at 21:00
  104. //            suppressed by notLateLong despite clean consolidation
  105. //          - ALGOUSDT 2026-05-29: launch candle at 19:30 suppressed
  106. //            despite bullTrend confirmed and price above EMA50
  107. //          Increasing to 2.0 ATR gives stronger trending coins more
  108. //          room to fire signals during sustained momentum moves.
  109. //          bullTrend definition intentionally unchanged — the lag
  110. //          on SMA8/SMA21 cross is a feature that protects against
  111. //          false breakouts into resistance zones.
  112. //          TEST VERSION — validate on live charts before adopting
  113. //          as permanent default. Revert to 1.5 if over-firing.
  114. // ============================================================
  115.  
  116. // ============================================================
  117. // CHANGELOG V5.9 (vs V5.8)
  118. // ------------------------------------------------------------
  119. // FIX 1 — entryATR reset bug resolved
  120. //          V5.8 had `if strategy.position_size == 0: entryATR := na`
  121. //          running on the same bar as the entry signal. Because
  122. //          Pine Script fills orders between bars (not mid-execution),
  123. //          position_size is still 0 throughout that bar's script run.
  124. //          This caused entryATR to be set then immediately reset to
  125. //          na on the entry bar, so SL/TP exits never fired.
  126. //          Guard now reads:
  127. //            if strategy.position_size == 0 and not longSignal and not shortSignal
  128. //          ensuring the reset only happens when truly flat with no
  129. //          new entry firing on the current bar.
  130. //
  131. // NOTE 1 — pullbackLong / pullbackShort are intentionally identical
  132. //          (see inline comment at that block — by design).
  133. //
  134. // NOTE 2 — pausingLong / pausingShort are intentionally identical
  135. //          (see inline comment at that block — by design).
  136. //
  137. // NOTE 3 — S1 / S1+ are intentionally excluded from S2R ignitions
  138. //          S2R is designed to continue momentum from a decisive
  139. //          breakout candle (S2 = momentum ignition, S3 = MA cross
  140. //          ignition). S1/S1+ are pullback-rejection setups — they
  141. //          signal mean-reversion into the zone, not a momentum burst.
  142. //          Including them as S2R ignition sources would fire S2R
  143. //          on normal price action that doesn't carry ignition momentum.
  144. //          (S1/S1+ were removed entirely in V5.10.2b — this note is
  145. //          preserved as historical record of the original design intent.)
  146. // ============================================================
  147.  
  148. // ============================================================
  149. // CHANGELOG V5.8 (vs V5.7)
  150. // ------------------------------------------------------------
  151. // FIX 1 — S2R one-signal-per-ignition guard added
  152. //          V5.7 allowed S2R to fire on consecutive pause bars
  153. //          after the same ignition event (e.g. 3 S2Rs from one
  154. //          S2). A fired flag now blocks subsequent S2R signals
  155. //          until a new S2 or S3 ignition resets it — matching
  156. //          the same pattern used for S3 double-signal guard.
  157. //
  158. // FIX 2 — pausingLong/Short threshold relaxed from 0.8 to 0.9
  159. //          Strong trending coins (APTUSDT) grind up with candles
  160. //          slightly below average range but not below 80%.
  161. //          0.9 threshold catches these shallow pauses correctly.
  162. // ============================================================
  163.  
  164. // ============================================================
  165. // CHANGELOG V5.7 (vs V5.6)
  166. // ------------------------------------------------------------
  167. // close > high[1] removed from S2R — contradicted pausingLong
  168. // ============================================================
  169.  
  170. // ============================================================
  171. // CHANGELOG V5.6 (vs V5.5)
  172. // ------------------------------------------------------------
  173. // S2R consolidation detection redesigned — momentum pause
  174. // ============================================================
  175.  
  176. // ============================================================
  177. // CHANGELOG V5.5 (vs V5.4)
  178. // ------------------------------------------------------------
  179. // S2R lookback increased to 15 bars default
  180. // ============================================================
  181.  
  182. // ============================================================
  183. // CHANGELOG V5.1 (vs V5)
  184. // ------------------------------------------------------------
  185. // FIX 1 — Pullback zone upper AND lower bound
  186. // FIX 2 — S2 volume filter reverted (ignition = supply exhaustion)
  187. // FIX 3 — S3 double-signal guard
  188. // FIX 4 — Entry requires position_size == 0
  189. // FIX 5 — ATR locked at entry
  190. // ============================================================
  191.  
  192.  
  193. // ============================================================
  194. // INPUTS
  195. // ============================================================
  196. fastLen      = input.int(8,    "SMA 8")
  197. slowLen      = input.int(21,   "SMA 21")
  198. ema9Len      = input.int(9,    "EMA 9")
  199. ema50Len     = input.int(50,   "EMA 50")
  200. ema200Len    = input.int(200,  "EMA 200")
  201. atrLen       = input.int(14,   "ATR Length")
  202. pullbackATR  = input.float(0.4, "Pullback tolerance ATR",      step=0.1)
  203. maxLateATR   = input.float(2.0, "Max distance from EMA50 ATR", step=0.1)
  204. stopATR      = input.float(1.2, "Stop ATR",                    step=0.1)
  205. targetRR     = input.float(2.0, "Target RR",                   step=0.1)
  206. s2rLookback  = input.int(15,   "S2R Lookback bars",            minval=5,  maxval=25)
  207. s2rMinBars   = input.int(4,    "S2R Min bars since ignition",  minval=2,  maxval=8)
  208. s2rPauseBars = input.int(4,    "S2R Consolidation bars",       minval=2,  maxval=8)
  209.  
  210.  
  211. // ============================================================
  212. // MOVING AVERAGES
  213. // ============================================================
  214. sma8   = ta.sma(close, fastLen)
  215. sma21  = ta.sma(close, slowLen)
  216. ema9   = ta.ema(close, ema9Len)
  217. ema50  = ta.ema(close, ema50Len)
  218. ema200 = ta.ema(close, ema200Len)
  219. atr    = ta.atr(atrLen)
  220.  
  221.  
  222. // ============================================================
  223. // TREND BIAS
  224. // ============================================================
  225. bullTrend = sma8 > sma21 and close > ema50
  226. bearTrend = sma8 < sma21 and close < ema50
  227.  
  228.  
  229. // ============================================================
  230. // PULLBACK ZONE (upper AND lower bound)
  231. // ------------------------------------------------------------
  232. // pullbackLong and pullbackShort are intentionally identical.
  233. // Both simply ask: "is the candle overlapping the MA zone?"
  234. // Directional filtering is handled downstream by bullTrend /
  235. // bearTrend and the bullReject / bearReject candle conditions.
  236. // Separate names are kept for readability at the callsite.
  237. // ============================================================
  238. zoneTop = math.max(sma8, sma21)
  239. zoneBot = math.min(sma8, sma21)
  240.  
  241. pullbackLong  = low  <= zoneTop + atr * pullbackATR and high >= zoneBot - atr * pullbackATR
  242. pullbackShort = high >= zoneBot - atr * pullbackATR and low  <= zoneTop + atr * pullbackATR
  243.  
  244.  
  245. // ============================================================
  246. // NOT TOO LATE (distance from EMA50 cap)
  247. // ============================================================
  248. notLateLong  = (close - ema50) <= atr * maxLateATR
  249. notLateShort = (ema50 - close) <= atr * maxLateATR
  250.  
  251.  
  252. // ============================================================
  253. // VOLUME CONTEXT
  254. // ============================================================
  255. volMA           = ta.sma(volume, 20)
  256. volumeSpike     = not na(volMA) and volume > volMA * 1.5
  257. volumeExpansion = not na(volMA) and volume > volMA * 1.2
  258. volumeState     = volumeSpike ? "spike" : "normal"
  259.  
  260.  
  261. // ============================================================
  262. // CANDLE STRUCTURE
  263. // ============================================================
  264. barRange  = math.max(high - low, syminfo.mintick)
  265. body      = math.abs(close - open)
  266. upperWick = high - math.max(open, close)
  267. lowerWick = math.min(open, close) - low
  268.  
  269. bullReject = pullbackLong  and close > open and close >= low  + barRange * 0.6 and lowerWick > body * 0.3
  270. bearReject = pullbackShort and close < open and close <= high - barRange * 0.6 and upperWick > body * 0.3
  271.  
  272.  
  273. // ============================================================
  274. // SETUP 2 — MOMENTUM IGNITION (no volume filter — intentional)
  275. // ------------------------------------------------------------
  276. // Volume filter removed in V5.1 — ignition candles fire on
  277. // low/average volume (supply exhaustion). Volume expands after
  278. // the ignition bar, not on it.
  279. // ============================================================
  280. longS2  = bullTrend and close > high[1] and close > sma8 and notLateLong  and body > barRange * 0.5
  281. shortS2 = bearTrend and close < low[1]  and close < sma8 and notLateShort and body > barRange * 0.5
  282.  
  283.  
  284. // ============================================================
  285. // SETUP 3 — CROSS IGNITION (double-signal guard)
  286. // ============================================================
  287. crossUpNow = ta.crossover(sma8,  sma21)
  288. crossDnNow = ta.crossunder(sma8, sma21)
  289.  
  290. var bool s3LongFired  = false
  291. var bool s3ShortFired = false
  292.  
  293. if not (crossUpNow or crossUpNow[1])
  294.     s3LongFired := false
  295. if not (crossDnNow or crossDnNow[1])
  296.     s3ShortFired := false
  297.  
  298. longS3Raw = (
  299.      (crossUpNow or crossUpNow[1]) and
  300.      close >= ema50 and
  301.      close > sma8 and
  302.      close > open and
  303.      body > barRange * 0.4
  304. )
  305.  
  306. shortS3Raw = (
  307.      (crossDnNow or crossDnNow[1]) and
  308.      close <= ema50 and
  309.      close < sma8 and
  310.      close < open and
  311.      body > barRange * 0.4
  312. )
  313.  
  314. longS3  = longS3Raw  and not s3LongFired  and not longS2
  315. shortS3 = shortS3Raw and not s3ShortFired and not shortS2
  316.  
  317. if longS3
  318.     s3LongFired := true
  319. if shortS3
  320.     s3ShortFired := true
  321.  
  322.  
  323. // ============================================================
  324. // SETUP S2R — CONSOLIDATION BREAK
  325. // ------------------------------------------------------------
  326. // Fires when price momentum pauses after a confirmed S2/S3
  327. // ignition, then resumes with a conviction candle.
  328. //
  329. // Ignition sources: S2 and S3 only (intentional — see NOTE 3
  330. // in V5.9 changelog). S1/S1+ are pullback-rejection setups,
  331. // not momentum ignitions, and are excluded by design. (S1/S1+
  332. // were removed entirely in V5.10.2b — the S2/S3-only ignition
  333. // source is unchanged, this is just a cleanup note.)
  334. //
  335. // Momentum pause = current candle range < 90% of average range
  336. // over the last s2rPauseBars bars. Threshold relaxed from 0.8
  337. // to 0.9 in V5.8 to catch shallow pauses on strong trend coins.
  338. //
  339. // One-signal-per-ignition guard added in V5.8 — s2rLongFired
  340. // flag prevents multiple S2R signals from the same ignition
  341. // event. Resets when a new S2 or S3 fires.
  342. // ============================================================
  343. barsSinceIgnitionLong  = ta.barssince(longS2  or longS3)
  344. barsSinceIgnitionShort = ta.barssince(shortS2 or shortS3)
  345.  
  346. recentLongIgnition  = barsSinceIgnitionLong  >= s2rMinBars and barsSinceIgnitionLong  <= s2rLookback
  347. recentShortIgnition = barsSinceIgnitionShort >= s2rMinBars and barsSinceIgnitionShort <= s2rLookback
  348.  
  349. // Momentum pause — range below 90% of recent average.
  350. // pausingLong and pausingShort are intentionally identical: a
  351. // range contraction is direction-agnostic. Separate names are
  352. // kept so each signal's condition reads symmetrically at the
  353. // longS2R / shortS2R callsite below.
  354. avgRange     = ta.sma(high - low, s2rPauseBars)
  355. pausingLong  = (high - low) < avgRange * 0.9
  356. pausingShort = (high - low) < avgRange * 0.9
  357.  
  358. // One-signal-per-ignition guard
  359. var bool s2rLongFired  = false
  360. var bool s2rShortFired = false
  361.  
  362. // Reset fired flag when a new ignition fires
  363. if longS2 or longS3
  364.     s2rLongFired := false
  365. if shortS2 or shortS3
  366.     s2rShortFired := false
  367.  
  368. longS2R  = bullTrend and recentLongIgnition  and pausingLong  and close > open and body > barRange * 0.4 and notLateLong  and not s2rLongFired  and not longS2  and not longS3
  369. shortS2R = bearTrend and recentShortIgnition and pausingShort and close < open and body > barRange * 0.4 and notLateShort and not s2rShortFired and not shortS2 and not shortS3
  370.  
  371. if longS2R
  372.     s2rLongFired := true
  373. if shortS2R
  374.     s2rShortFired := true
  375.  
  376.  
  377. // ============================================================
  378. // FINAL SIGNALS
  379. // ============================================================
  380. longSignal  = longS2  or longS3  or longS2R
  381. shortSignal = shortS2 or shortS3 or shortS2R
  382.  
  383.  
  384. // ============================================================
  385. // PREVIEW vs CONFIRMED
  386. // ============================================================
  387. isPreviewBar   = barstate.isrealtime and not barstate.isconfirmed
  388. isConfirmedBar = barstate.isconfirmed
  389.  
  390. previewLongS2      = longS2      and isPreviewBar
  391. previewShortS2     = shortS2     and isPreviewBar
  392. previewLongS3      = longS3      and isPreviewBar
  393. previewShortS3     = shortS3     and isPreviewBar
  394. previewLongS2R     = longS2R     and isPreviewBar
  395. previewShortS2R    = shortS2R    and isPreviewBar
  396.  
  397. confirmedLongS2      = longS2      and isConfirmedBar
  398. confirmedShortS2     = shortS2     and isConfirmedBar
  399. confirmedLongS3      = longS3      and isConfirmedBar
  400. confirmedShortS3     = shortS3     and isConfirmedBar
  401. confirmedLongS2R     = longS2R     and isConfirmedBar
  402. confirmedShortS2R    = shortS2R    and isConfirmedBar
  403.  
  404.  
  405. // ============================================================
  406. // LABELS
  407. // ============================================================
  408.  
  409. // Preview labels (semi-transparent — bar not yet closed)
  410. plotshape(previewLongS2,      title="PREVIEW LONG S2",   style=shape.labelup,   location=location.belowbar, text="PRE S2",   size=size.small, color=color.new(color.blue,   55), textcolor=color.white)
  411. plotshape(previewShortS2,     title="PREVIEW SHORT S2",  style=shape.labeldown, location=location.abovebar, text="PRE S2",   size=size.small, color=color.new(color.orange, 55), textcolor=color.white)
  412. plotshape(previewLongS3,      title="PREVIEW LONG S3",   style=shape.labelup,   location=location.belowbar, text="PRE S3",   size=size.small, color=color.new(color.purple, 55), textcolor=color.white)
  413. plotshape(previewShortS3,     title="PREVIEW SHORT S3",  style=shape.labeldown, location=location.abovebar, text="PRE S3",   size=size.small, color=color.new(color.fuchsia,55), textcolor=color.white)
  414. plotshape(previewLongS2R,     title="PREVIEW LONG S2R",  style=shape.labelup,   location=location.belowbar, text="PRE S2R",  size=size.small, color=color.new(color.teal,   55), textcolor=color.white)
  415. plotshape(previewShortS2R,    title="PREVIEW SHORT S2R", style=shape.labeldown, location=location.abovebar, text="PRE S2R",  size=size.small, color=color.new(color.teal,   55), textcolor=color.white)
  416.  
  417. // Confirmed labels (fully opaque — bar closed)
  418. plotshape(confirmedLongS2,      title="LONG S2",   style=shape.labelup,   location=location.belowbar, text="S2",   size=size.small,  color=color.new(color.blue,   0), textcolor=color.white)
  419. plotshape(confirmedShortS2,     title="SHORT S2",  style=shape.labeldown, location=location.abovebar, text="S2",   size=size.small,  color=color.new(color.orange, 0), textcolor=color.white)
  420. plotshape(confirmedLongS3,      title="LONG S3",   style=shape.labelup,   location=location.belowbar, text="S3",   size=size.small,  color=color.new(color.purple, 0), textcolor=color.white)
  421. plotshape(confirmedShortS3,     title="SHORT S3",  style=shape.labeldown, location=location.abovebar, text="S3",   size=size.small,  color=color.new(color.fuchsia,0), textcolor=color.white)
  422. plotshape(confirmedLongS2R,     title="LONG S2R",  style=shape.labelup,   location=location.belowbar, text="S2R",  size=size.normal, color=color.new(color.teal,   0), textcolor=color.white)
  423. plotshape(confirmedShortS2R,    title="SHORT S2R", style=shape.labeldown, location=location.abovebar, text="S2R",  size=size.normal, color=color.new(color.teal,   0), textcolor=color.white)
  424.  
  425.  
  426. // ============================================================
  427. // WEBHOOK CONTEXT
  428. // ============================================================
  429. is30m = timeframe.period == "30"
  430. // Note: alerts only fire on 30m timeframe by design.
  431. // If you add this script to other timeframes, alerts will
  432. // silently not fire — this is intentional.
  433.  
  434. trendAlignmentLong  = close > ema200 ? "bullish" : "bearish"
  435. trendAlignmentShort = close < ema200 ? "bearish" : "bullish"
  436.  
  437.  
  438. // ============================================================
  439. // WEBHOOK ALERTS — CONFIRMED BARS, 30m ONLY
  440. // ------------------------------------------------------------
  441. // S1/S1+ removed entirely (setups deleted in V5.10.2b).
  442. // S2R removed from this section (V5.10.2b) — S2R still fires,
  443. // plots, and enters/exits per FINAL SIGNALS, it just no longer
  444. // sends a webhook alert. Only S2 and S3 reach Telegram.
  445. // ============================================================
  446. if confirmedLongS2 and is30m
  447.     alert('{"setup":"S2","side":"LONG","symbol":"'    + syminfo.ticker + '","timeframe":"30m","price":"' + str.tostring(close) + '","status":"confirmed","trend":"' + trendAlignmentLong  + '","volume":"' + volumeState + '"}', alert.freq_once_per_bar_close)
  448. if confirmedShortS2 and is30m
  449.     alert('{"setup":"S2","side":"SHORT","symbol":"'   + syminfo.ticker + '","timeframe":"30m","price":"' + str.tostring(close) + '","status":"confirmed","trend":"' + trendAlignmentShort + '","volume":"' + volumeState + '"}', alert.freq_once_per_bar_close)
  450. if confirmedLongS3 and is30m
  451.     alert('{"setup":"S3","side":"LONG","symbol":"'    + syminfo.ticker + '","timeframe":"30m","price":"' + str.tostring(close) + '","status":"confirmed","trend":"' + trendAlignmentLong  + '","volume":"' + volumeState + '"}', alert.freq_once_per_bar_close)
  452. if confirmedShortS3 and is30m
  453.     alert('{"setup":"S3","side":"SHORT","symbol":"'   + syminfo.ticker + '","timeframe":"30m","price":"' + str.tostring(close) + '","status":"confirmed","trend":"' + trendAlignmentShort + '","volume":"' + volumeState + '"}', alert.freq_once_per_bar_close)
  454.  
  455.  
  456. // ============================================================
  457. // ENTRIES: position must be flat before new entry
  458. // ============================================================
  459. if longSignal and isConfirmedBar and strategy.position_size == 0
  460.     strategy.entry("Long", strategy.long)
  461.  
  462. if shortSignal and isConfirmedBar and strategy.position_size == 0
  463.     strategy.entry("Short", strategy.short)
  464.  
  465.  
  466. // ============================================================
  467. // EXITS: ATR locked at entry, not recalculated
  468. // ------------------------------------------------------------
  469. // entryATR is set on the signal bar (position_size still 0
  470. // because Pine fills orders between bars, not mid-execution).
  471. // The reset guard `not longSignal and not shortSignal` ensures
  472. // the na-reset does NOT run on the same bar as an entry,
  473. // which was the V5.8 bug that prevented exits from ever firing.
  474. // ============================================================
  475. var float entryATR = na
  476.  
  477. if longSignal and isConfirmedBar and strategy.position_size == 0
  478.     entryATR := atr
  479.  
  480. if shortSignal and isConfirmedBar and strategy.position_size == 0
  481.     entryATR := atr
  482.  
  483. if strategy.position_size == 0 and not longSignal and not shortSignal
  484.     entryATR := na
  485.  
  486. if strategy.position_size > 0 and not na(entryATR)
  487.     longStopPrice = strategy.position_avg_price - entryATR * stopATR
  488.     longTakePrice = strategy.position_avg_price + (strategy.position_avg_price - longStopPrice) * targetRR
  489.     strategy.exit("Long Exit", from_entry="Long", stop=longStopPrice, limit=longTakePrice)
  490.  
  491. if strategy.position_size < 0 and not na(entryATR)
  492.     shortStopPrice = strategy.position_avg_price + entryATR * stopATR
  493.     shortTakePrice = strategy.position_avg_price - (shortStopPrice - strategy.position_avg_price) * targetRR
  494.     strategy.exit("Short Exit", from_entry="Short", stop=shortStopPrice, limit=shortTakePrice)
  495.  
  496.  
  497. // ============================================================
  498. // PLOTS
  499. // ============================================================
  500. plot(sma8,   "SMA 8",   color=color.white,  linewidth=2)
  501. plot(sma21,  "SMA 21",  color=color.yellow, linewidth=2)
  502. plot(ema9,   "EMA 9",   color=color.aqua,   linewidth=1)
  503. plot(ema50,  "EMA 50",  color=color.orange, linewidth=2)
  504. plot(ema200, "EMA 200", color=color.blue,   linewidth=2)
Advertisement
Add Comment
Please, Sign In to add comment