AshICT

Ash ICT CRT — Protocol Engine v20.9.3.2 Synced Parent ID + Primary Execution TF

Jul 11th, 2026
21
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 192.59 KB | None | 0 0
  1. //@version=6
  2. indicator(
  3. title = "Ash ICT CRT — Protocol Engine v20.9.3.2 Synced Parent ID + Primary Execution TF",
  4. shorttitle = "Ash CRT Protocol v20.9.3.2",
  5. overlay = true,
  6. dynamic_requests = true,
  7. max_lines_count = 500,
  8. max_labels_count = 500
  9. )
  10.  
  11. //======================================================================
  12. // 1. CORE CRT SETTINGS
  13. //======================================================================
  14. groupCore = "1. Core CRT Detection"
  15.  
  16. useSelectedHours = input.bool(
  17. true,
  18. "Use Market-Specific CRT Time Protocol",
  19. group = groupCore,
  20. tooltip = "The time model is a quality protocol, not a mandatory trade signal. Daily, Weekly and Monthly candles automatically pass the time protocol."
  21. )
  22.  
  23. marketTimeProfile = input.string(
  24. "Auto",
  25. "Market Time Profile",
  26. options = ["Auto", "Forex", "Indices", "Futures", "Crypto", "Commodities", "Manual"],
  27. group = groupCore,
  28. tooltip = "Auto uses TradingView symbol metadata and ticker keywords. Use a manual profile when a broker classifies the symbol differently."
  29. )
  30.  
  31. timezoneInput = input.string(
  32. "America/New_York",
  33. "CRT Model Timezone",
  34. options = [
  35. "America/New_York",
  36. "Etc/UTC",
  37. "Europe/London",
  38. "Asia/Dubai",
  39. "Asia/Kolkata"
  40. ],
  41. group = groupCore
  42. )
  43.  
  44. timeMatchToleranceHours = input.int(
  45. 0,
  46. "Time Match Tolerance (Hours)",
  47. minval = 0,
  48. maxval = 2,
  49. group = groupCore,
  50. tooltip = "0 requires an exact model-hour open. Increase to 1 for brokers whose 2H/3H candle alignment is shifted by one hour."
  51. )
  52.  
  53. forexHour1 = input.int(1, "Forex Hour 1", minval = 0, maxval = 23, group = groupCore)
  54. forexHour2 = input.int(5, "Forex Hour 2", minval = 0, maxval = 23, group = groupCore)
  55. forexHour3 = input.int(9, "Forex Hour 3", minval = 0, maxval = 23, group = groupCore)
  56.  
  57. indicesHour1 = input.int(2, "Indices Hour 1", minval = 0, maxval = 23, group = groupCore)
  58. indicesHour2 = input.int(6, "Indices Hour 2", minval = 0, maxval = 23, group = groupCore)
  59. indicesHour3 = input.int(10, "Indices Hour 3", minval = 0, maxval = 23, group = groupCore)
  60.  
  61. futuresHour1 = input.int(2, "Futures Hour 1", minval = 0, maxval = 23, group = groupCore)
  62. futuresHour2 = input.int(6, "Futures Hour 2", minval = 0, maxval = 23, group = groupCore)
  63. futuresHour3 = input.int(10, "Futures Hour 3", minval = 0, maxval = 23, group = groupCore)
  64.  
  65. cryptoHour1 = input.int(1, "Crypto Hour 1", minval = 0, maxval = 23, group = groupCore)
  66. cryptoHour2 = input.int(5, "Crypto Hour 2", minval = 0, maxval = 23, group = groupCore)
  67. cryptoHour3 = input.int(9, "Crypto Hour 3", minval = 0, maxval = 23, group = groupCore)
  68.  
  69. commoditiesHour1 = input.int(1, "Commodities Hour 1", minval = 0, maxval = 23, group = groupCore)
  70. commoditiesHour2 = input.int(5, "Commodities Hour 2", minval = 0, maxval = 23, group = groupCore)
  71. commoditiesHour3 = input.int(9, "Commodities Hour 3", minval = 0, maxval = 23, group = groupCore)
  72.  
  73. manualHour1 = input.int(1, "Manual Hour 1", minval = 0, maxval = 23, group = groupCore)
  74. manualHour2 = input.int(5, "Manual Hour 2", minval = 0, maxval = 23, group = groupCore)
  75. manualHour3 = input.int(9, "Manual Hour 3", minval = 0, maxval = 23, group = groupCore)
  76.  
  77. requireCloseInside = input.bool(
  78. true,
  79. "Manipulation Must Close Back Inside Range",
  80. group = groupCore
  81. )
  82.  
  83. rejectDoubleSweep = input.bool(
  84. true,
  85. "Reject Manipulation Sweeping Both Sides",
  86. group = groupCore
  87. )
  88.  
  89. requireDirectionalClose = input.bool(
  90. false,
  91. "Require Directional Manipulation Close",
  92. group = groupCore,
  93. tooltip = "Bullish setup: manipulation candle must close bullish. Bearish setup: manipulation candle must close bearish."
  94. )
  95.  
  96. //======================================================================
  97. // 2. PROTOCOL ENGINE
  98. //======================================================================
  99. groupProtocol = "2. Protocol Engine"
  100.  
  101. minimumProtocols = input.int(
  102. 3,
  103. "Minimum Protocols Required",
  104. minval = 1,
  105. maxval = 9,
  106. group = groupProtocol,
  107. tooltip = "The blue/yellow sequence appears only when the setup passes at least this many enabled quality protocols."
  108. )
  109.  
  110. useTimeProtocol = input.bool(true, "Protocol 1 — Valid CRT Time", group = groupProtocol)
  111. useKeyLevelProtocol = input.bool(true, "Protocol 2 — HTF Key-Level Interaction", group = groupProtocol)
  112. useRejectionProtocol = input.bool(true, "Protocol 3 — Strong Rejection Wick", group = groupProtocol)
  113. useMidpointProtocol = input.bool(true, "Protocol 4 — Midpoint Reclaim", group = groupProtocol)
  114. useRangeSizeProtocol = input.bool(true, "Protocol 5 — Controlled Range Size", group = groupProtocol)
  115. useBodyProtocol = input.bool(true, "Protocol 6 — Healthy Range Body", group = groupProtocol)
  116. usePOIProtocol = input.bool(true, "Protocol 7 — Directional HTF POI Confluence", group = groupProtocol, tooltip = "Requires POI direction to agree with the CRT purge direction. Bullish CRTs seek bullish POIs after sell-side purge; bearish CRTs seek bearish POIs after buy-side purge.")
  117.  
  118. useHierarchyProtocol = input.bool(
  119. true,
  120. "Protocol 8 — Higher-Timeframe CRT Alignment",
  121. group = groupProtocol,
  122. tooltip = "Compares the candidate CRT direction with the latest confirmed structural CRT direction on its parent timeframe."
  123. )
  124.  
  125. neutralHierarchyPass = input.bool(
  126. true,
  127. "Allow CRT When Parent Direction Is Neutral",
  128. group = groupProtocol
  129. )
  130.  
  131. rejectOpposingHierarchy = input.bool(
  132. true,
  133. "Reject Opposing Parent CRT Direction",
  134. group = groupProtocol,
  135. tooltip = "Example: a bearish H1 CRT is rejected while the latest H4 CRT context remains bullish."
  136. )
  137.  
  138. string groupLifecycle = "CRT Lifecycle Engine"
  139.  
  140. lifecycleExpiryBars = input.int(
  141. 12,
  142. "Expire CRT After Bars",
  143. minval = 1,
  144. maxval = 100,
  145. group = groupLifecycle,
  146. tooltip = "An active CRT stops influencing hierarchy when its opposite-side target has not been reached within this many source-timeframe candles."
  147. )
  148.  
  149. targetRequiresClose = input.bool(
  150. false,
  151. "Target Requires Candle Close",
  152. group = groupLifecycle,
  153. tooltip = "Off: touching the opposite side completes the CRT. On: price must close through the opposite side."
  154. )
  155.  
  156. invalidationRequiresClose = input.bool(
  157. true,
  158. "Invalidation Requires Candle Close",
  159. group = groupLifecycle,
  160. tooltip = "Bullish CRT invalidates below the Range low; bearish CRT invalidates above the Range high. Keeping this enabled avoids wick-only invalidations."
  161. )
  162.  
  163. replaceWithNewestCRT = input.bool(
  164. true,
  165. "Newest CRT Replaces Previous CRT",
  166. group = groupLifecycle,
  167. tooltip = "A newer qualified CRT on the same timeframe becomes the active lifecycle context."
  168. )
  169.  
  170. // v19.8 Narrative Reset / Re-Arm controls
  171. enableNarrativeRearmEngine = input.bool(
  172. true,
  173. "Enable Narrative Reset / Re-Arm Engine",
  174. group = groupLifecycle,
  175. tooltip = "After a parent objective is completed, invalidated, or expired, execution remains stood down until a genuinely newer qualified parent CRT creates a fresh narrative."
  176. )
  177.  
  178. rearmDisplayParentBars = input.int(
  179. 2,
  180. "Show RE-ARMED State for Parent Bars",
  181. minval = 1,
  182. maxval = 10,
  183. group = groupLifecycle,
  184. tooltip = "Controls how long the dashboard highlights the newly re-armed parent narrative after the fresh qualified parent CRT."
  185. )
  186.  
  187. // v19.9 Narrative Transition Memory / Freshness controls
  188. enableNarrativeFreshnessEngine = input.bool(
  189. true,
  190. "Enable Narrative Transition Memory / Freshness Engine",
  191. group = groupLifecycle,
  192. tooltip = "Assigns a unique sequential identity to each qualified source-timeframe CRT. After a terminal story, only a later narrative identity can be treated as fresh and re-arm execution."
  193. )
  194.  
  195. freshNarrativeDisplayBars = input.int(
  196. 4,
  197. "Fresh Narrative Highlight (Parent Bars)",
  198. minval = 1,
  199. maxval = 20,
  200. group = groupLifecycle,
  201. tooltip = "Number of parent-timeframe bars during which a newly created narrative is labelled FRESH. The narrative remains active afterward, but the freshness highlight ends."
  202. )
  203.  
  204. // v20.0 Fresh Narrative Validation Engine
  205. enableFreshNarrativeValidation = input.bool(
  206. true,
  207. "Enable Fresh Narrative Validation Engine",
  208. group = groupLifecycle,
  209. tooltip = "A post-reset parent CRT must validate direction, HTF context, delivery, and an undelivered objective before execution can re-arm."
  210. )
  211.  
  212. freshValidationWindowBars = input.int(
  213. 4,
  214. "Fresh Narrative Validation Window (Parent Bars)",
  215. minval = 1,
  216. maxval = 20,
  217. group = groupLifecycle,
  218. tooltip = "Maximum number of parent bars allowed for delivery confirmation. A fresh narrative that does not begin directional delivery inside this window is rejected."
  219. )
  220.  
  221. requireFreshHierarchyAlignment = input.bool(
  222. true,
  223. "Require HTF Context Alignment",
  224. group = groupLifecycle,
  225. tooltip = "Rejects a fresh parent CRT when it opposes the active higher-timeframe structural CRT. Neutral higher-timeframe context is allowed."
  226. )
  227.  
  228. requireFreshDeliveryConfirmation = input.bool(
  229. true,
  230. "Require Delivery Confirmation",
  231. group = groupLifecycle,
  232. tooltip = "Requires the existing displacement/delivery engine to confirm movement away from the manipulated side before execution re-arms."
  233. )
  234.  
  235. // v20.3 Narrative Delivery & Objective Tracker
  236. enableNarrativeObjectiveTracker = input.bool(
  237. true,
  238. "Enable Narrative Delivery & Objective Tracker",
  239. group = groupLifecycle,
  240. tooltip = "Tracks whether the active fresh narrative is validating, delivering, approaching its objective, completed, invalidated, expired, or permanently rejected."
  241. )
  242.  
  243. objectiveNearThresholdATR = input.float(
  244. 0.25,
  245. "Objective Near Threshold (ATR)",
  246. minval = 0.0,
  247. step = 0.05,
  248. group = groupLifecycle,
  249. tooltip = "The objective is labelled NEAR when price is within this ATR distance of the selected draw-on-liquidity target."
  250. )
  251.  
  252. // Directional POI context controls
  253. poiLookback = input.int(
  254. 80,
  255. "POI Detection Lookback",
  256. minval = 10,
  257. maxval = 300,
  258. group = groupProtocol
  259. )
  260.  
  261. poiToleranceATR = input.float(
  262. 0.05,
  263. "POI Touch Tolerance (ATR)",
  264. minval = 0.0,
  265. step = 0.01,
  266. group = groupProtocol
  267. )
  268.  
  269. minimumPOITypes = input.int(
  270. 1,
  271. "Minimum Aligned POI Types Required",
  272. minval = 1,
  273. maxval = 5,
  274. group = groupProtocol
  275. )
  276.  
  277. minimumDirectionalPOIScore = input.int(
  278. 2,
  279. "Minimum Directional POI Score",
  280. minval = 1,
  281. maxval = 10,
  282. group = groupProtocol,
  283. tooltip = "FVG/Order Block = 2 points. IFVG/Breaker/Rejection Block = 3 points."
  284. )
  285.  
  286. rejectOpposingPOIDominance = input.bool(
  287. true,
  288. "Reject Opposing POI Dominance",
  289. group = groupProtocol
  290. )
  291.  
  292. useFVGPOI = input.bool(true, "Include Fair Value Gaps", group = groupProtocol)
  293. useIFVGPOI = input.bool(true, "Include Inverse FVGs", group = groupProtocol)
  294. useOrderBlockPOI = input.bool(true, "Include Order Blocks", group = groupProtocol)
  295. useBreakerPOI = input.bool(true, "Include Breaker Blocks", group = groupProtocol)
  296. useRejectionBlockPOI = input.bool(true, "Include Rejection Blocks", group = groupProtocol)
  297.  
  298. keyLevelToleranceATR = input.float(
  299. 0.10,
  300. "Key-Level Touch Tolerance (ATR)",
  301. minval = 0.0,
  302. step = 0.01,
  303. group = groupProtocol
  304. )
  305.  
  306. minimumRejectionPercent = input.float(
  307. 35.0,
  308. "Minimum Manipulation Rejection Wick %",
  309. minval = 0.0,
  310. maxval = 100.0,
  311. step = 1.0,
  312. group = groupProtocol
  313. )
  314.  
  315. requireMidpointReclaim = input.bool(
  316. true,
  317. "Require Range Midpoint Reclaim",
  318. group = groupProtocol
  319. )
  320.  
  321. atrLength = input.int(
  322. 20,
  323. "ATR Length",
  324. minval = 1,
  325. group = groupProtocol
  326. )
  327.  
  328. minimumRangeATR = input.float(
  329. 0.4,
  330. "Minimum Range Size (ATR)",
  331. minval = 0.0,
  332. step = 0.1,
  333. group = groupProtocol
  334. )
  335.  
  336. maximumRangeATR = input.float(
  337. 2.0,
  338. "Maximum Range Size (ATR)",
  339. minval = 0.1,
  340. step = 0.1,
  341. group = groupProtocol
  342. )
  343.  
  344. minimumRangeBodyPercent = input.float(
  345. 20.0,
  346. "Minimum Range Body %",
  347. minval = 0.0,
  348. maxval = 100.0,
  349. step = 1.0,
  350. group = groupProtocol
  351. )
  352.  
  353. maximumRangeBodyPercent = input.float(
  354. 80.0,
  355. "Maximum Range Body %",
  356. minval = 0.0,
  357. maxval = 100.0,
  358. step = 1.0,
  359. group = groupProtocol
  360. )
  361.  
  362. string groupLiquidity = "Liquidity Purge Context"
  363.  
  364. useLiquidityPurgeContext = input.bool(
  365. true,
  366. "Protocol 10 — Meaningful Liquidity Purge Context",
  367. group = groupLiquidity,
  368. tooltip = "Bonus context only. It does not reject or hide any CRT that qualified under the stable v16.7 engine."
  369. )
  370.  
  371. liquiditySwingLookback = input.int(
  372. 20,
  373. "Swing Liquidity Lookback",
  374. minval = 3,
  375. maxval = 200,
  376. group = groupLiquidity
  377. )
  378.  
  379. liquidityToleranceATR = input.float(
  380. 0.05,
  381. "Liquidity Equality Tolerance (ATR)",
  382. minval = 0.0,
  383. step = 0.01,
  384. group = groupLiquidity
  385. )
  386.  
  387. minimumLiquidityPurgeScore = input.int(
  388. 1,
  389. "Meaningful Purge Score Threshold",
  390. minval = 1,
  391. maxval = 6,
  392. group = groupLiquidity,
  393. tooltip = "Previous day = 1, previous week = 2, previous month = 3, established swing liquidity = 1."
  394. )
  395.  
  396. string groupNested = "CRT Sequence / Nested HTF Context"
  397.  
  398. useNestedCRTContext = input.bool(
  399. true,
  400. "Protocol 11 — Nested HTF CRT Context",
  401. group = groupNested,
  402. tooltip = "Bonus context only. Detects when the current CRT is nested inside, overlaps, or directionally aligns with an active parent-timeframe CRT. It cannot reject or hide stable v16.9 CRTs."
  403. )
  404.  
  405. requireFullParentContainment = input.bool(
  406. false,
  407. "Require Full Containment for Nested State",
  408. group = groupNested,
  409. tooltip = "Off: overlap with the active parent CRT range qualifies. On: the complete local Range candle must sit inside the parent CRT range."
  410. )
  411.  
  412. useParentPremiumDiscount = input.bool(
  413. true,
  414. "Score Parent Premium / Discount Location",
  415. group = groupNested,
  416. tooltip = "Bullish nested CRTs score when formed in the lower half of the parent range. Bearish nested CRTs score in the upper half."
  417. )
  418.  
  419. minimumNestedContextScore = input.int(
  420. 2,
  421. "Meaningful Nested Context Score",
  422. minval = 1,
  423. maxval = 3,
  424. group = groupNested,
  425. tooltip = "Inside/overlap = 1, direction aligned = 1, correct premium/discount location = 1."
  426. )
  427.  
  428. string groupDelivery = "Displacement / Delivery Confirmation"
  429.  
  430. useDeliveryContext = input.bool(
  431. true,
  432. "Protocol 12 — Displacement and Delivery Confirmation",
  433. group = groupDelivery,
  434. tooltip = "Bonus confirmation only. Evaluates post-manipulation delivery without hiding CRTs qualified by the stable v17.1 engine."
  435. )
  436.  
  437. deliveryWindowBars = input.int(
  438. 3,
  439. "Delivery Confirmation Window (Bars)",
  440. minval = 1,
  441. maxval = 6,
  442. group = groupDelivery
  443. )
  444.  
  445. minimumDeliveryBodyATR = input.float(
  446. 0.50,
  447. "Minimum Displacement Body (ATR)",
  448. minval = 0.0,
  449. step = 0.05,
  450. group = groupDelivery
  451. )
  452.  
  453. requireDeliveryFVG = input.bool(
  454. false,
  455. "Require FVG Creation for Delivery Bonus",
  456. group = groupDelivery
  457. )
  458.  
  459. minimumDeliveryScore = input.int(
  460. 2,
  461. "Meaningful Delivery Score",
  462. minval = 1,
  463. maxval = 4,
  464. group = groupDelivery,
  465. tooltip = "Directional close = 1, strong ATR body = 1, range-mid delivery = 1, FVG creation = 1."
  466. )
  467.  
  468. string groupFailure = "Failed CRT / Reversal Context"
  469.  
  470. useFailedCRTContext = input.bool(
  471. true,
  472. "Protocol 13 — Failed CRT / Reversal Context",
  473. group = groupFailure,
  474. tooltip = "Context only. Tracks a qualified CRT that fails through its manipulated-side boundary and treats that failure as potential opposite-direction information. It does not hide stable v17.4 CRTs."
  475. )
  476.  
  477. failureRequiresClose = input.bool(
  478. true,
  479. "Failure Requires Close Through Boundary",
  480. group = groupFailure
  481. )
  482.  
  483. failureWindowBars = input.int(
  484. 6,
  485. "Failure Detection Window (Bars)",
  486. minval = 1,
  487. maxval = 30,
  488. group = groupFailure
  489. )
  490.  
  491. requireFailureDirectionalClose = input.bool(
  492. true,
  493. "Require Failure Candle Direction",
  494. group = groupFailure,
  495. tooltip = "Bullish CRT failure candle must close bearish; bearish CRT failure candle must close bullish."
  496. )
  497.  
  498. minimumFailureBodyATR = input.float(
  499. 0.25,
  500. "Minimum Failure Body (ATR)",
  501. minval = 0.0,
  502. step = 0.05,
  503. group = groupFailure
  504. )
  505.  
  506. string groupTarget = "CRT Target Delivery / Draw on Liquidity"
  507.  
  508. useTargetDeliveryContext = input.bool(
  509. true,
  510. "Protocol 14 — Target Delivery / Draw on Liquidity",
  511. group = groupTarget,
  512. tooltip = "Context only. Selects the nearest valid opposite-side liquidity objective for each qualified CRT. It does not alter stable v17.5 CRT qualification or candle colors."
  513. )
  514.  
  515. includeOppositeCRTRangeBoundary = input.bool(
  516. true,
  517. "Include Opposite CRT Range Boundary",
  518. group = groupTarget
  519. )
  520.  
  521. includePreviousDayTarget = input.bool(
  522. true,
  523. "Include Previous Day Liquidity",
  524. group = groupTarget
  525. )
  526.  
  527. includePreviousWeekTarget = input.bool(
  528. true,
  529. "Include Previous Week Liquidity",
  530. group = groupTarget
  531. )
  532.  
  533. includePreviousMonthTarget = input.bool(
  534. true,
  535. "Include Previous Month Liquidity",
  536. group = groupTarget
  537. )
  538.  
  539. includeSwingLiquidityTarget = input.bool(
  540. true,
  541. "Include Swing Liquidity",
  542. group = groupTarget
  543. )
  544.  
  545. targetSwingLookback = input.int(
  546. 20,
  547. "Target Swing Lookback",
  548. minval = 3,
  549. maxval = 200,
  550. group = groupTarget
  551. )
  552.  
  553. targetReachToleranceATR = input.float(
  554. 0.05,
  555. "Target Reach Tolerance (ATR)",
  556. minval = 0.0,
  557. step = 0.01,
  558. group = groupTarget
  559. )
  560.  
  561. string groupGrade = "CRT Intelligence Grade Engine"
  562.  
  563. useIntelligenceGrade = input.bool(
  564. true,
  565. "CRT Intelligence Grade Engine",
  566. group = groupGrade,
  567. tooltip = "Grades qualified CRTs from C to A+ using the protocol intelligence already built. Grading is informational and does not alter stable v17.6 CRT qualification."
  568. )
  569.  
  570. gradeAPlusThreshold = input.int(
  571. 8,
  572. "A+ Minimum Intelligence Score",
  573. minval = 1,
  574. maxval = 10,
  575. group = groupGrade
  576. )
  577.  
  578. gradeAThreshold = input.int(
  579. 6,
  580. "A Minimum Intelligence Score",
  581. minval = 1,
  582. maxval = 10,
  583. group = groupGrade
  584. )
  585.  
  586. gradeBThreshold = input.int(
  587. 4,
  588. "B Minimum Intelligence Score",
  589. minval = 1,
  590. maxval = 10,
  591. group = groupGrade
  592. )
  593.  
  594. string groupDashboard = "CRT Intelligence Dashboard"
  595.  
  596. showIntelligenceDashboard = input.bool(
  597. true,
  598. "Show CRT Intelligence Dashboard",
  599. group = groupDashboard
  600. )
  601.  
  602. dashboardPosition = input.string(
  603. "Top Right",
  604. "Dashboard Position",
  605. options = ["Top Right", "Top Left", "Bottom Right", "Bottom Left"],
  606. group = groupDashboard
  607. )
  608.  
  609. dashboardTextSize = input.string(
  610. "Small",
  611. "Dashboard Text Size",
  612. options = ["Tiny", "Small", "Normal"],
  613. group = groupDashboard
  614. )
  615.  
  616. string groupKeyLevel = "Dedicated ICT Key Level Engine"
  617.  
  618. useDedicatedKeyLevelEngine = input.bool(
  619. true,
  620. "Enable Dedicated ICT Key Level Engine",
  621. group = groupKeyLevel,
  622. tooltip = "Detects the dominant FVG, IFVG, Order Block, Breaker, or Rejection Block interacting with the latest CRT Range on the selected source timeframe."
  623. )
  624.  
  625. keyLevelLookback = input.int(
  626. 80,
  627. "Key Level Detection Lookback",
  628. minval = 10,
  629. maxval = 300,
  630. group = groupKeyLevel
  631. )
  632.  
  633. keyLevelTypeToleranceATR = input.float(
  634. 0.05,
  635. "Key Level Zone Tolerance (ATR)",
  636. minval = 0.0,
  637. step = 0.01,
  638. group = groupKeyLevel
  639. )
  640.  
  641. string groupSMT = "SMT / Multi-Asset Matrix"
  642.  
  643. useSMTProtocol = input.bool(
  644. true,
  645. "Protocol 9 — Multi-Asset SMT Matrix",
  646. group = groupSMT,
  647. tooltip = "Checks the candidate CRT against up to two correlated or inversely correlated comparison markets."
  648. )
  649.  
  650. smtMode = input.string(
  651. "Auto Matrix",
  652. "SMT Comparison Mode",
  653. options = ["Auto Matrix", "Manual"],
  654. group = groupSMT
  655. )
  656.  
  657. manualSMTSymbol1 = input.symbol(
  658. "CME_MINI:NQ1!",
  659. "Manual Comparison Symbol 1",
  660. group = groupSMT
  661. )
  662.  
  663. manualSMTRelation1 = input.string(
  664. "Direct",
  665. "Manual Symbol 1 Relation",
  666. options = ["Direct", "Inverse"],
  667. group = groupSMT
  668. )
  669.  
  670. manualSMTSymbol2 = input.symbol(
  671. "CBOT_MINI:YM1!",
  672. "Manual Comparison Symbol 2",
  673. group = groupSMT
  674. )
  675.  
  676. manualSMTRelation2 = input.string(
  677. "Direct",
  678. "Manual Symbol 2 Relation",
  679. options = ["Direct", "Inverse"],
  680. group = groupSMT
  681. )
  682.  
  683. useSecondSMTMarket = input.bool(
  684. true,
  685. "Use Second SMT Market",
  686. group = groupSMT
  687. )
  688.  
  689. smtLookback = input.int(
  690. 20,
  691. "SMT Swing Lookback",
  692. minval = 2,
  693. maxval = 200,
  694. group = groupSMT
  695. )
  696.  
  697. smtToleranceATR = input.float(
  698. 0.05,
  699. "SMT Equality Tolerance (ATR)",
  700. minval = 0.0,
  701. step = 0.01,
  702. group = groupSMT
  703. )
  704.  
  705. minimumSMTConfirmations = input.int(
  706. 1,
  707. "Minimum Aligned SMT Confirmations",
  708. minval = 1,
  709. maxval = 2,
  710. group = groupSMT,
  711. tooltip = "One aligned comparison is enough by default. Set to 2 for stricter multi-market confirmation."
  712. )
  713.  
  714. allowNeutralSMT = input.bool(
  715. true,
  716. "Allow Neutral SMT",
  717. group = groupSMT
  718. )
  719.  
  720. rejectOpposingSMT = input.bool(
  721. false,
  722. "Reject Strong Opposing SMT",
  723. group = groupSMT,
  724. tooltip = "Rejects a CRT when opposing SMT confirmations outnumber aligned SMT confirmations."
  725. )
  726.  
  727. //======================================================================
  728. // 3. VISUAL SETTINGS
  729. //======================================================================
  730. groupVisual = "3. Visual Settings"
  731.  
  732. colorCandles = input.bool(true, "Color Qualified CRT Candles on Source Timeframe", group = groupVisual)
  733. rangeColor = input.color(color.rgb(35, 125, 225), "Range Candle Color", group = groupVisual)
  734. manipulationColor = input.color(color.rgb(255, 195, 0), "Manipulation Candle Color", group = groupVisual)
  735.  
  736. // v20.9.2 visual-history controls. These settings change chart visibility only.
  737. // All CRT detection, narrative memory, validation, objectives, and alerts continue
  738. // calculating from the full available history in the background.
  739. crtVisualHistoryMode = input.string(
  740. "Current Week",
  741. "CRT Candle Visual History",
  742. options = ["All History", "Current Week", "Last N Chart Candles"],
  743. group = groupVisual,
  744. tooltip = "All History shows every historical coloured CRT. Current Week shows only CRTs belonging to the latest chart week. Last N Chart Candles limits colours to the most recent number of candles on the chart timeframe. This does not change detection or alerts."
  745. )
  746.  
  747. crtVisualRecentBars = input.int(
  748. 4,
  749. "CRT — Last N Chart Candles",
  750. minval = 2,
  751. maxval = 5000,
  752. group = groupVisual,
  753. tooltip = "Used only when CRT Candle Visual History is set to Last N Chart Candles. Example: 4 on a 1H chart means the latest four 1H candles."
  754. )
  755.  
  756. //======================================================================
  757. // 4. MULTI-HTF HIERARCHY + AUTO AMD WINDOWS
  758. //======================================================================
  759. groupProjection = "4. Multi-HTF Hierarchy + AMD Windows"
  760.  
  761. enableHTFProjection = input.bool(
  762. true,
  763. "Show Selected HTF AMD Windows on Lower Timeframes",
  764. group = groupProjection
  765. )
  766.  
  767. hierarchyContext = input.string(
  768. "Auto",
  769. "HTF Context Mode",
  770. options = ["Auto", "Monthly", "Weekly", "Daily", "H4", "H3", "H2", "H1", "30m"],
  771. group = groupProjection,
  772. tooltip = "Auto uses the chart timeframe on Monthly, Weekly, Daily, H4, H3, H2, H1 and 30m charts. On charts below 30m it uses the Lower-TF Projection Context selected below."
  773. )
  774.  
  775. lowerTFProjectionContext = input.string(
  776. "H4",
  777. "Lower-TF Projection Context",
  778. options = ["Monthly", "Weekly", "Daily", "H4", "H3", "H2", "H1", "30m"],
  779. group = groupProjection,
  780. tooltip = "Used only when HTF Context Mode is Auto and the chart timeframe is below 30 minutes."
  781. )
  782.  
  783. // v20.9.3.2 — Dynamic higher-timeframe narrative ownership.
  784. // On 1H and lower charts, the highest active qualified parent is inherited in
  785. // this order: 4H → 3H → 2H → 1H. The execution authorization engine itself
  786. // remains restricted by Maximum Execution Chart Timeframe.
  787. enableDynamicParentHierarchy = input.bool(
  788. true,
  789. "Enable Dynamic 4H / 3H / 2H / 1H Parent Hierarchy",
  790. group = groupProjection,
  791. tooltip = "On 1H and lower charts, inherit the highest active qualified narrative from 4H, 3H, 2H, then 1H. This fixes cases where a confirmed 3H or 2H parent was invisible on the 1H/15M execution chain."
  792. )
  793.  
  794. f_contextToTF(string context) =>
  795. context == "Monthly" ? "M" :
  796. context == "Weekly" ? "W" :
  797. context == "Daily" ? "D" :
  798. context == "H3" ? "180" :
  799. context == "H2" ? "120" :
  800. context == "H1" ? "60" :
  801. context == "30m" ? "30" : "240"
  802.  
  803. int currentChartSeconds = timeframe.in_seconds(timeframe.period)
  804.  
  805. string autoSelectedHTF =
  806. timeframe.ismonthly ? "M" :
  807. timeframe.isweekly ? "W" :
  808. timeframe.isdaily ? "D" :
  809. not na(currentChartSeconds) and currentChartSeconds >= 14400 ? "240" :
  810. not na(currentChartSeconds) and currentChartSeconds >= 10800 ? "180" :
  811. not na(currentChartSeconds) and currentChartSeconds >= 7200 ? "120" :
  812. not na(currentChartSeconds) and currentChartSeconds >= 3600 ? "60" :
  813. not na(currentChartSeconds) and currentChartSeconds >= 1800 ? "30" :
  814. f_contextToTF(lowerTFProjectionContext)
  815.  
  816. string selectedHTF = hierarchyContext == "Auto" ? autoSelectedHTF : f_contextToTF(hierarchyContext)
  817.  
  818. // Clean-chart mode: no automatic AMD vertical separators or phase labels.
  819. // The selected HTF structure is still tracked internally for LTF unlock logic.
  820.  
  821.  
  822. //======================================================================
  823. // 5. EXECUTION UNLOCK ENGINE
  824. //======================================================================
  825. groupExecution = "5. Execution Unlock Engine"
  826.  
  827. enableExecutionEngine = input.bool(
  828. true,
  829. "Enable LTF Execution Scanner",
  830. group = groupExecution,
  831. tooltip = "After the selected HTF manipulation closes, scan only its Distribution window for aligned lower-timeframe CRT structure."
  832. )
  833.  
  834. maximumExecutionMinutes = input.int(
  835. 15,
  836. "Maximum Execution Chart Timeframe (Minutes)",
  837. minval = 1,
  838. maxval = 60,
  839. group = groupExecution,
  840. tooltip = "Example: 15 allows the scanner on 15m, 5m, 3m, 2m and 1m charts."
  841. )
  842.  
  843. primaryExecutionTimeframe = input.string(
  844. "5m",
  845. "Primary One-Shot Execution Timeframe",
  846. options = ["15m", "5m", "3m", "2m", "1m", "All LTFs (Advanced)"],
  847. group = groupExecution,
  848. tooltip = "Only this chart timeframe may consume the one-shot execution authorization for a parent narrative. Other lower timeframes remain confirmation/information charts. Default: 5m. All LTFs (Advanced) restores independent authorization on every lower-timeframe chart and can create duplicate permissions across separate chart instances."
  849. )
  850.  
  851. firstExecutionOnly = input.bool(
  852. true,
  853. "Show First Entry Only per HTF Setup",
  854. group = groupExecution
  855. )
  856.  
  857. colorUnlockedLTFStructure = input.bool(
  858. true,
  859. "Color Unlocked LTF Range + Manipulation",
  860. group = groupExecution,
  861. tooltip = "Inside the confirmed HTF Distribution window, color only aligned lower-timeframe CRT structure: blue Range candle and yellow Manipulation candle."
  862. )
  863.  
  864. showRawCRTForTesting = input.bool(
  865. false,
  866. "TEST — Show Raw CRT Without Protocol Filters",
  867. group = groupExecution,
  868. tooltip = "Diagnostic only. Shows every valid close-back-inside CRT before protocol filtering."
  869. )
  870.  
  871. localRequireCloseInside = input.bool(
  872. true,
  873. "LTF Manipulation Must Close Inside Local Range",
  874. group = groupExecution
  875. )
  876.  
  877. localRequireMidpoint = input.bool(
  878. true,
  879. "LTF Manipulation Must Reclaim Local Midpoint",
  880. group = groupExecution
  881. )
  882.  
  883. localMinimumRejection = input.float(
  884. 25.0,
  885. "Minimum LTF Rejection Wick %",
  886. minval = 0.0,
  887. maxval = 100.0,
  888. step = 1.0,
  889. group = groupExecution
  890. )
  891.  
  892. ltfRangeColor = input.color(color.rgb(35, 125, 225), "Unlocked LTF Range Color", group = groupExecution)
  893. ltfManipulationColor = input.color(color.rgb(255, 195, 0), "Unlocked LTF Manipulation Color", group = groupExecution)
  894.  
  895. // v20.7 Execution Authorization Engine (primary-TF lock added in v20.9.3.2)
  896. enableExecutionAuthorizationEngine = input.bool(
  897. true,
  898. "Enable One-Shot Execution Authorization",
  899. group = groupExecution,
  900. tooltip = "After a parent narrative is active, authorizes one aligned qualified LTF CRT per parent narrative ID. This is permission guidance only; it does not place orders."
  901. )
  902.  
  903. authorizationRequireLiquidityOrPOI = input.bool(
  904. true,
  905. "Authorization Requires Liquidity Purge or Key-Level Reaction",
  906. group = groupExecution,
  907. tooltip = "The aligned LTF CRT must also confirm a meaningful liquidity purge or a directional FVG/IFVG, order block, breaker, rejection block, or tracked external level."
  908. )
  909.  
  910. authorizationRequireObjectiveRoom = input.bool(
  911. true,
  912. "Authorization Requires Room to Parent Objective",
  913. group = groupExecution,
  914. tooltip = "Blocks authorization when the parent objective is already behind price, unavailable, completed, or too close to justify chasing."
  915. )
  916.  
  917. authorizationMinimumRoomATR = input.float(
  918. 0.50,
  919. "Minimum Room to Parent Objective (LTF ATR)",
  920. minval = 0.0,
  921. maxval = 10.0,
  922. step = 0.05,
  923. group = groupExecution,
  924. tooltip = "Minimum remaining distance from current price to the parent objective, measured with the execution-chart ATR."
  925. )
  926.  
  927. authorizationRequireDistributionWindow = input.bool(
  928. false,
  929. "Authorization Requires Active HTF Distribution Window",
  930. group = groupExecution,
  931. tooltip = "Optional strict mode. When enabled, authorization is allowed only inside the existing projected HTF Distribution window."
  932. )
  933.  
  934. //======================================================================
  935. // 6. FORWARD-TEST ALERT ENGINE
  936. //======================================================================
  937. string groupForwardAlerts = "6. Forward-Test Alert Engine"
  938.  
  939. enableForwardTestAlerts = input.bool(
  940. true,
  941. "Enable Forward-Test Runtime Alerts",
  942. group = groupForwardAlerts,
  943. tooltip = "Uses Pine alert() calls so the execution milestones can be monitored without consuming additional plot slots. Create one TradingView alert using: Any alert() function call."
  944. )
  945.  
  946. alertParentConfirmed = input.bool(true, "Alert — Parent Narrative Confirmed 4/4", group = groupForwardAlerts)
  947. alertExecutionArmed = input.bool(true, "Alert — Execution Armed", group = groupForwardAlerts)
  948. alertEntryConfirmed = input.bool(true, "Alert — Entry Confirmed", group = groupForwardAlerts)
  949. alertDeliveryNoReentry = input.bool(true, "Alert — Delivery / No Re-Entry", group = groupForwardAlerts)
  950. alertParentObjectiveCompleted = input.bool(true, "Alert — Parent Objective Completed", group = groupForwardAlerts)
  951. alertParentRejectedInvalidated = input.bool(true, "Alert — Parent Rejected / Invalidated / Expired", group = groupForwardAlerts)
  952. alertNoChase = input.bool(true, "Alert — No Chase / Objective Too Near", group = groupForwardAlerts)
  953.  
  954. //======================================================================
  955. // 7. ASH ICT FRACTAL
  956. //======================================================================
  957. string groupFractal = "7. Ash ICT Fractal"
  958.  
  959. showAshICTFractal = input.bool(
  960. true,
  961. "Show Ash ICT Fractal",
  962. group = groupFractal,
  963. tooltip = "Displays the original clean Ash ICT Fractal markers on every chart timeframe. Signals are confirmed only after the required right-side candles close."
  964. )
  965.  
  966. ashICTFractalPeriods = input.int(
  967. 2,
  968. "Fractal Period",
  969. minval = 1,
  970. maxval = 10,
  971. group = groupFractal,
  972. tooltip = "Original default is 2 candles on each side of the centre candle."
  973. )
  974.  
  975. ashICTFractalUseHighLow = input.bool(
  976. true,
  977. "Use High/Low",
  978. group = groupFractal,
  979. tooltip = "On: fractals use candle wicks. Off: fractals use candle body highs and lows."
  980. )
  981.  
  982. showAshICTFractalHigh = input.bool(true, "Show Fractal High", group = groupFractal)
  983. showAshICTFractalLow = input.bool(true, "Show Fractal Low", group = groupFractal)
  984. ashICTFractalHighColor = input.color(color.rgb(170, 170, 0), "Fractal High Color", group = groupFractal)
  985. ashICTFractalLowColor = input.color(color.rgb(180, 0, 120), "Fractal Low Color", group = groupFractal)
  986.  
  987. ashICTFractalHistoryMode = input.string(
  988. "Current Week",
  989. "Fractal Visual History",
  990. options = ["All History", "Current Week", "Last N Chart Candles"],
  991. group = groupFractal,
  992. tooltip = "Controls only how many Ash ICT Fractal markers remain visible. The fractal calculations themselves are unchanged."
  993. )
  994.  
  995. ashICTFractalRecentBars = input.int(
  996. 50,
  997. "Fractal — Last N Chart Candles",
  998. minval = 2,
  999. maxval = 5000,
  1000. group = groupFractal,
  1001. tooltip = "Used only when Fractal Visual History is set to Last N Chart Candles. Set this to 3 or 4 for an extremely clean chart, or use a larger number such as 50 for more swing context."
  1002. )
  1003.  
  1004. //======================================================================
  1005. // 8. HELPERS — AUTO MARKET TIME PROTOCOL
  1006. //======================================================================
  1007. // Returns true when a visual belongs to the selected display window.
  1008. // `last_bar_time` and `last_bar_index` anchor the filter to the latest bar
  1009. // loaded on the chart, which also keeps the filter useful on closed markets.
  1010. f_visualHistoryPass(string mode, int recentBars, int targetBarIndex, int targetTime) =>
  1011. bool validTarget = not na(targetTime) and targetBarIndex >= 0
  1012. bool inLatestChartWeek =
  1013. validTarget and
  1014. year(targetTime, timezoneInput) == year(last_bar_time, timezoneInput) and
  1015. weekofyear(targetTime, timezoneInput) == weekofyear(last_bar_time, timezoneInput)
  1016. bool inRecentChartBars =
  1017. validTarget and
  1018. targetBarIndex >= math.max(last_bar_index - recentBars + 1, 0)
  1019. mode == "All History" or
  1020. (mode == "Current Week" and inLatestChartWeek) or
  1021. (mode == "Last N Chart Candles" and inRecentChartBars)
  1022.  
  1023. f_hourDistance(int a, int b) =>
  1024. int directDistance = math.abs(a - b)
  1025. math.min(directDistance, 24 - directDistance)
  1026.  
  1027. f_hourMatches(int candleHour, int modelHour) =>
  1028. f_hourDistance(candleHour, modelHour) <= timeMatchToleranceHours
  1029.  
  1030. f_autoMarketProfile() =>
  1031. string tickerUpper = str.upper(syminfo.ticker)
  1032. string rootUpper = str.upper(syminfo.root)
  1033. bool indexKeyword =
  1034. str.contains(tickerUpper, "US100") or
  1035. str.contains(tickerUpper, "NAS") or
  1036. str.contains(tickerUpper, "SPX") or
  1037. str.contains(tickerUpper, "US500") or
  1038. str.contains(tickerUpper, "DJI") or
  1039. str.contains(tickerUpper, "DAX") or
  1040. str.contains(tickerUpper, "FTSE")
  1041. bool commodityKeyword =
  1042. str.contains(tickerUpper, "XAU") or
  1043. str.contains(tickerUpper, "XAG") or
  1044. str.contains(rootUpper, "CL") or
  1045. str.contains(rootUpper, "MCL") or
  1046. str.contains(rootUpper, "GC") or
  1047. str.contains(rootUpper, "SI") or
  1048. str.contains(tickerUpper, "OIL")
  1049. syminfo.type == "forex" ? "Forex" :
  1050. syminfo.type == "crypto" ? "Crypto" :
  1051. commodityKeyword ? "Commodities" :
  1052. syminfo.type == "futures" ? (indexKeyword or str.contains(rootUpper, "ES") or str.contains(rootUpper, "NQ") or str.contains(rootUpper, "YM") or str.contains(rootUpper, "RTY") ? "Indices" : "Futures") :
  1053. syminfo.type == "index" or indexKeyword ? "Indices" :
  1054. "Manual"
  1055.  
  1056. f_selectedMarketProfile() =>
  1057. marketTimeProfile == "Auto" ? f_autoMarketProfile() : marketTimeProfile
  1058.  
  1059. f_profileHours(string profile) =>
  1060. int h1 =
  1061. profile == "Forex" ? forexHour1 :
  1062. profile == "Indices" ? indicesHour1 :
  1063. profile == "Futures" ? futuresHour1 :
  1064. profile == "Crypto" ? cryptoHour1 :
  1065. profile == "Commodities" ? commoditiesHour1 : manualHour1
  1066. int h2 =
  1067. profile == "Forex" ? forexHour2 :
  1068. profile == "Indices" ? indicesHour2 :
  1069. profile == "Futures" ? futuresHour2 :
  1070. profile == "Crypto" ? cryptoHour2 :
  1071. profile == "Commodities" ? commoditiesHour2 : manualHour2
  1072. int h3 =
  1073. profile == "Forex" ? forexHour3 :
  1074. profile == "Indices" ? indicesHour3 :
  1075. profile == "Futures" ? futuresHour3 :
  1076. profile == "Crypto" ? cryptoHour3 :
  1077. profile == "Commodities" ? commoditiesHour3 : manualHour3
  1078. [h1, h2, h3]
  1079.  
  1080. isAllowedRangeHour(int candleTime) =>
  1081. bool higherCalendarTF = timeframe.isdaily or timeframe.isweekly or timeframe.ismonthly
  1082. string activeProfile = f_selectedMarketProfile()
  1083. [modelHour1, modelHour2, modelHour3] = f_profileHours(activeProfile)
  1084. int candleHour = hour(candleTime, timezoneInput)
  1085. not useSelectedHours or higherCalendarTF or
  1086. f_hourMatches(candleHour, modelHour1) or
  1087. f_hourMatches(candleHour, modelHour2) or
  1088. f_hourMatches(candleHour, modelHour3)
  1089.  
  1090. isNearLevel(float candleHigh, float candleLow, float level, float tolerance) =>
  1091. not na(level) and candleHigh >= level - tolerance and candleLow <= level + tolerance
  1092.  
  1093.  
  1094. rangeOverlapsZone(float candleHigh, float candleLow, float zoneHigh, float zoneLow, float tolerance) =>
  1095. not na(zoneHigh) and not na(zoneLow) and candleHigh >= zoneLow - tolerance and candleLow <= zoneHigh + tolerance
  1096.  
  1097. // Directional POI Confluence Engine v2. No zones are drawn.
  1098. // Scores are weighted by POI quality and kept directional.
  1099. f_detectDirectionalPOIs(float testHigh, float testLow, float tolerance) =>
  1100. bool bullFVGTouch = false
  1101. bool bearFVGTouch = false
  1102. bool bullIFVGTouch = false
  1103. bool bearIFVGTouch = false
  1104. bool bullOBTouch = false
  1105. bool bearOBTouch = false
  1106. bool bullBreakerTouch = false
  1107. bool bearBreakerTouch = false
  1108. bool bullRBTouch = false
  1109. bool bearRBTouch = false
  1110.  
  1111. int maxBack = math.min(poiLookback, bar_index > 10 ? bar_index - 5 : 0)
  1112. if maxBack >= 4
  1113. for k = 2 to maxBack
  1114. bool bullFVG = low[k] > high[k + 2]
  1115. bool bearFVG = high[k] < low[k + 2]
  1116. float bullFVGHigh = low[k]
  1117. float bullFVGLow = high[k + 2]
  1118. float bearFVGHigh = low[k + 2]
  1119. float bearFVGLow = high[k]
  1120. bullFVGTouch := bullFVGTouch or (bullFVG and rangeOverlapsZone(testHigh, testLow, bullFVGHigh, bullFVGLow, tolerance))
  1121. bearFVGTouch := bearFVGTouch or (bearFVG and rangeOverlapsZone(testHigh, testLow, bearFVGHigh, bearFVGLow, tolerance))
  1122.  
  1123. // An invalidated bearish FVG reclaimed upward acts as bullish IFVG.
  1124. // An invalidated bullish FVG reclaimed downward acts as bearish IFVG.
  1125. bool bullishIFVG = bearFVG and close[k - 1] > bearFVGHigh
  1126. bool bearishIFVG = bullFVG and close[k - 1] < bullFVGLow
  1127. bullIFVGTouch := bullIFVGTouch or (bullishIFVG and rangeOverlapsZone(testHigh, testLow, bearFVGHigh, bearFVGLow, tolerance))
  1128. bearIFVGTouch := bearIFVGTouch or (bearishIFVG and rangeOverlapsZone(testHigh, testLow, bullFVGHigh, bullFVGLow, tolerance))
  1129.  
  1130. bool bullishDisplacement = close[k] > high[k + 1] and close[k] > open[k]
  1131. bool bearishDisplacement = close[k] < low[k + 1] and close[k] < open[k]
  1132. bool bullishOB = bullishDisplacement and close[k + 1] < open[k + 1]
  1133. bool bearishOB = bearishDisplacement and close[k + 1] > open[k + 1]
  1134. bullOBTouch := bullOBTouch or (bullishOB and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance))
  1135. bearOBTouch := bearOBTouch or (bearishOB and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance))
  1136.  
  1137. bool bullishBreaker = close[k + 1] < open[k + 1] and close[k] > high[k + 1]
  1138. bool bearishBreaker = close[k + 1] > open[k + 1] and close[k] < low[k + 1]
  1139. bullBreakerTouch := bullBreakerTouch or (bullishBreaker and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance))
  1140. bearBreakerTouch := bearBreakerTouch or (bearishBreaker and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance))
  1141.  
  1142. float candleRangeK = math.max(high[k] - low[k], syminfo.mintick)
  1143. float lowerWickPctK = (math.min(open[k], close[k]) - low[k]) / candleRangeK * 100.0
  1144. float upperWickPctK = (high[k] - math.max(open[k], close[k])) / candleRangeK * 100.0
  1145. bool bullishRB = lowerWickPctK >= 50.0
  1146. bool bearishRB = upperWickPctK >= 50.0
  1147. float bullRBHigh = math.min(open[k], close[k])
  1148. float bullRBLow = low[k]
  1149. float bearRBHigh = high[k]
  1150. float bearRBLow = math.max(open[k], close[k])
  1151. bullRBTouch := bullRBTouch or (bullishRB and rangeOverlapsZone(testHigh, testLow, bullRBHigh, bullRBLow, tolerance))
  1152. bearRBTouch := bearRBTouch or (bearishRB and rangeOverlapsZone(testHigh, testLow, bearRBHigh, bearRBLow, tolerance))
  1153.  
  1154. int bullTypes =
  1155. (useFVGPOI and bullFVGTouch ? 1 : 0) +
  1156. (useIFVGPOI and bullIFVGTouch ? 1 : 0) +
  1157. (useOrderBlockPOI and bullOBTouch ? 1 : 0) +
  1158. (useBreakerPOI and bullBreakerTouch ? 1 : 0) +
  1159. (useRejectionBlockPOI and bullRBTouch ? 1 : 0)
  1160.  
  1161. int bearTypes =
  1162. (useFVGPOI and bearFVGTouch ? 1 : 0) +
  1163. (useIFVGPOI and bearIFVGTouch ? 1 : 0) +
  1164. (useOrderBlockPOI and bearOBTouch ? 1 : 0) +
  1165. (useBreakerPOI and bearBreakerTouch ? 1 : 0) +
  1166. (useRejectionBlockPOI and bearRBTouch ? 1 : 0)
  1167.  
  1168. int bullScore =
  1169. (useFVGPOI and bullFVGTouch ? 2 : 0) +
  1170. (useIFVGPOI and bullIFVGTouch ? 3 : 0) +
  1171. (useOrderBlockPOI and bullOBTouch ? 2 : 0) +
  1172. (useBreakerPOI and bullBreakerTouch ? 3 : 0) +
  1173. (useRejectionBlockPOI and bullRBTouch ? 3 : 0)
  1174.  
  1175. int bearScore =
  1176. (useFVGPOI and bearFVGTouch ? 2 : 0) +
  1177. (useIFVGPOI and bearIFVGTouch ? 3 : 0) +
  1178. (useOrderBlockPOI and bearOBTouch ? 2 : 0) +
  1179. (useBreakerPOI and bearBreakerTouch ? 3 : 0) +
  1180. (useRejectionBlockPOI and bearRBTouch ? 3 : 0)
  1181.  
  1182. [bullTypes, bearTypes, bullScore, bearScore]
  1183.  
  1184. //======================================================================
  1185. // 6A. DEDICATED ICT KEY LEVEL TYPE ENGINE
  1186. // Runs in the selected source-timeframe context.
  1187. // Type codes: 0=None, 1=FVG, 2=IFVG, 3=Order Block,
  1188. // 4=Breaker, 5=Rejection Block.
  1189. //======================================================================
  1190. f_keyLevelTypeForRange(float testHigh, float testLow, float tolerance) =>
  1191. int bullishType = 0
  1192. int bearishType = 0
  1193. int bullishWeight = 0
  1194. int bearishWeight = 0
  1195.  
  1196. int maxBack = math.min(keyLevelLookback, bar_index > 10 ? bar_index - 5 : 0)
  1197.  
  1198. if maxBack >= 4
  1199. for k = 2 to maxBack
  1200. bool bullFVG = low[k] > high[k + 2]
  1201. bool bearFVG = high[k] < low[k + 2]
  1202.  
  1203. float bullFVGHigh = low[k]
  1204. float bullFVGLow = high[k + 2]
  1205. float bearFVGHigh = low[k + 2]
  1206. float bearFVGLow = high[k]
  1207.  
  1208. bool bullFVGTouch = bullFVG and rangeOverlapsZone(testHigh, testLow, bullFVGHigh, bullFVGLow, tolerance)
  1209. bool bearFVGTouch = bearFVG and rangeOverlapsZone(testHigh, testLow, bearFVGHigh, bearFVGLow, tolerance)
  1210.  
  1211. bool bullishIFVG = bearFVG and close[k - 1] > bearFVGHigh
  1212. bool bearishIFVG = bullFVG and close[k - 1] < bullFVGLow
  1213.  
  1214. bool bullIFVGTouch = bullishIFVG and rangeOverlapsZone(testHigh, testLow, bearFVGHigh, bearFVGLow, tolerance)
  1215. bool bearIFVGTouch = bearishIFVG and rangeOverlapsZone(testHigh, testLow, bullFVGHigh, bullFVGLow, tolerance)
  1216.  
  1217. bool bullishDisplacement = close[k] > high[k + 1] and close[k] > open[k]
  1218. bool bearishDisplacement = close[k] < low[k + 1] and close[k] < open[k]
  1219. bool bullishOB = bullishDisplacement and close[k + 1] < open[k + 1]
  1220. bool bearishOB = bearishDisplacement and close[k + 1] > open[k + 1]
  1221.  
  1222. bool bullOBTouch = bullishOB and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance)
  1223. bool bearOBTouch = bearishOB and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance)
  1224.  
  1225. bool bullishBreaker = close[k + 1] < open[k + 1] and close[k] > high[k + 1]
  1226. bool bearishBreaker = close[k + 1] > open[k + 1] and close[k] < low[k + 1]
  1227.  
  1228. bool bullBreakerTouch = bullishBreaker and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance)
  1229. bool bearBreakerTouch = bearishBreaker and rangeOverlapsZone(testHigh, testLow, high[k + 1], low[k + 1], tolerance)
  1230.  
  1231. float candleRangeK = math.max(high[k] - low[k], syminfo.mintick)
  1232. float lowerWickPctK = (math.min(open[k], close[k]) - low[k]) / candleRangeK * 100.0
  1233. float upperWickPctK = (high[k] - math.max(open[k], close[k])) / candleRangeK * 100.0
  1234.  
  1235. bool bullishRB = lowerWickPctK >= 50.0
  1236. bool bearishRB = upperWickPctK >= 50.0
  1237.  
  1238. float bullRBHigh = math.min(open[k], close[k])
  1239. float bullRBLow = low[k]
  1240. float bearRBHigh = high[k]
  1241. float bearRBLow = math.max(open[k], close[k])
  1242.  
  1243. bool bullRBTouch = bullishRB and rangeOverlapsZone(testHigh, testLow, bullRBHigh, bullRBLow, tolerance)
  1244. bool bearRBTouch = bearishRB and rangeOverlapsZone(testHigh, testLow, bearRBHigh, bearRBLow, tolerance)
  1245.  
  1246. if bullFVGTouch and bullishWeight < 2
  1247. bullishType := 1
  1248. bullishWeight := 2
  1249. if bearFVGTouch and bearishWeight < 2
  1250. bearishType := 1
  1251. bearishWeight := 2
  1252.  
  1253. if bullOBTouch and bullishWeight < 2
  1254. bullishType := 3
  1255. bullishWeight := 2
  1256. if bearOBTouch and bearishWeight < 2
  1257. bearishType := 3
  1258. bearishWeight := 2
  1259.  
  1260. if bullIFVGTouch and bullishWeight < 3
  1261. bullishType := 2
  1262. bullishWeight := 3
  1263. if bearIFVGTouch and bearishWeight < 3
  1264. bearishType := 2
  1265. bearishWeight := 3
  1266.  
  1267. if bullBreakerTouch and bullishWeight < 3
  1268. bullishType := 4
  1269. bullishWeight := 3
  1270. if bearBreakerTouch and bearishWeight < 3
  1271. bearishType := 4
  1272. bearishWeight := 3
  1273.  
  1274. if bullRBTouch and bullishWeight < 3
  1275. bullishType := 5
  1276. bullishWeight := 3
  1277. if bearRBTouch and bearishWeight < 3
  1278. bearishType := 5
  1279. bearishWeight := 3
  1280.  
  1281. [bullishType, bearishType, bullishWeight, bearishWeight]
  1282.  
  1283. f_sourceTFKeyLevelState() =>
  1284. float sourceRangeHigh = high[1]
  1285. float sourceRangeLow = low[1]
  1286. float sourceATR = ta.atr(14)
  1287. float sourceTolerance = sourceATR[1] * keyLevelTypeToleranceATR
  1288. [bullType, bearType, bullWeight, bearWeight] = f_keyLevelTypeForRange(sourceRangeHigh, sourceRangeLow, sourceTolerance)
  1289.  
  1290. bool sourceSweptHigh = high > sourceRangeHigh
  1291. bool sourceSweptLow = low < sourceRangeLow
  1292. bool sourceSingleSweep = sourceSweptHigh != sourceSweptLow
  1293. bool sourceClosedInside = close < sourceRangeHigh and close > sourceRangeLow
  1294. bool sourceBase =
  1295. barstate.isconfirmed and
  1296. sourceSingleSweep and
  1297. (not rejectDoubleSweep or not (sourceSweptHigh and sourceSweptLow)) and
  1298. (not requireCloseInside or sourceClosedInside)
  1299.  
  1300. int sourceDirection =
  1301. sourceBase and sourceSweptLow and not sourceSweptHigh ? 1 :
  1302. sourceBase and sourceSweptHigh and not sourceSweptLow ? -1 : 0
  1303.  
  1304. int alignedType =
  1305. sourceDirection == 1 ? bullType :
  1306. sourceDirection == -1 ? bearType : 0
  1307.  
  1308. int opposingType =
  1309. sourceDirection == 1 ? bearType :
  1310. sourceDirection == -1 ? bullType : 0
  1311.  
  1312. int alignedWeight =
  1313. sourceDirection == 1 ? bullWeight :
  1314. sourceDirection == -1 ? bearWeight : 0
  1315.  
  1316. [sourceDirection, alignedType, opposingType, alignedWeight]
  1317.  
  1318. [sourceKeyDirection, sourceKeyLevelType, sourceOpposingKeyLevelType, sourceKeyLevelWeight] =
  1319. request.security(
  1320. syminfo.tickerid,
  1321. selectedHTF,
  1322. f_sourceTFKeyLevelState(),
  1323. gaps = barmerge.gaps_off,
  1324. lookahead = barmerge.lookahead_off
  1325. )
  1326.  
  1327. //======================================================================
  1328. // 7. MULTI-ASSET SMT MATRIX
  1329. // CME, Forex, Crypto, Metals and Energy.
  1330. // v16.7 uses verified exchange prefixes and spot crypto comparison feeds.
  1331. // Relation code: 1 = direct correlation, -1 = inverse correlation.
  1332. //======================================================================
  1333. f_autoSMTSymbol1() =>
  1334. string t = str.upper(syminfo.ticker)
  1335. string r = str.upper(syminfo.root)
  1336.  
  1337. bool es = r == "ES" or str.contains(t, "US500") or str.contains(t, "SPX")
  1338. bool nq = r == "NQ" or str.contains(t, "US100") or str.contains(t, "NAS100")
  1339. bool ym = r == "YM" or str.contains(t, "US30")
  1340. bool rty = r == "RTY"
  1341.  
  1342. bool eurusd = str.contains(t, "EURUSD")
  1343. bool gbpusd = str.contains(t, "GBPUSD")
  1344. bool audusd = str.contains(t, "AUDUSD")
  1345. bool nzdusd = str.contains(t, "NZDUSD")
  1346. bool usdchf = str.contains(t, "USDCHF")
  1347. bool usdcad = str.contains(t, "USDCAD")
  1348. bool usdjpy = str.contains(t, "USDJPY")
  1349. bool eurjpy = str.contains(t, "EURJPY")
  1350. bool gbpjpy = str.contains(t, "GBPJPY")
  1351. bool audjpy = str.contains(t, "AUDJPY")
  1352. bool nzdjpy = str.contains(t, "NZDJPY")
  1353.  
  1354. bool btc = str.contains(t, "BTC")
  1355. bool eth = str.contains(t, "ETH")
  1356. bool sol = str.contains(t, "SOL")
  1357.  
  1358. bool gold = str.contains(t, "XAU") or r == "GC"
  1359. bool silver = str.contains(t, "XAG") or r == "SI"
  1360. bool wti = r == "CL" or str.contains(t, "USOIL") or str.contains(t, "WTI")
  1361. bool brent = r == "BRN" or str.contains(t, "UKOIL") or str.contains(t, "BRENT")
  1362.  
  1363. es ? "CME_MINI:NQ1!" :
  1364. nq ? "CME_MINI:ES1!" :
  1365. ym ? "CME_MINI:ES1!" :
  1366. rty ? "CME_MINI:ES1!" :
  1367. eurusd ? "OANDA:GBPUSD" :
  1368. gbpusd ? "OANDA:EURUSD" :
  1369. audusd ? "OANDA:NZDUSD" :
  1370. nzdusd ? "OANDA:AUDUSD" :
  1371. usdchf ? "TVC:DXY" :
  1372. usdcad ? "TVC:DXY" :
  1373. usdjpy ? "TVC:DXY" :
  1374. eurjpy ? "OANDA:GBPJPY" :
  1375. gbpjpy ? "OANDA:EURJPY" :
  1376. audjpy ? "OANDA:NZDJPY" :
  1377. nzdjpy ? "OANDA:AUDJPY" :
  1378. btc ? "BINANCE:ETHUSDT" :
  1379. eth ? "BINANCE:BTCUSDT" :
  1380. sol ? "BINANCE:BTCUSDT" :
  1381. gold ? "COMEX:SI1!" :
  1382. silver ? "COMEX:GC1!" :
  1383. wti ? "TVC:UKOIL" :
  1384. brent ? "NYMEX:CL1!" :
  1385. manualSMTSymbol1
  1386.  
  1387. f_autoSMTRelation1() =>
  1388. string t = str.upper(syminfo.ticker)
  1389. bool usdchf = str.contains(t, "USDCHF")
  1390. usdchf ? -1 : 1
  1391.  
  1392. f_autoSMTSymbol2() =>
  1393. string t = str.upper(syminfo.ticker)
  1394. string r = str.upper(syminfo.root)
  1395.  
  1396. bool es = r == "ES" or str.contains(t, "US500") or str.contains(t, "SPX")
  1397. bool nq = r == "NQ" or str.contains(t, "US100") or str.contains(t, "NAS100")
  1398. bool ym = r == "YM" or str.contains(t, "US30")
  1399. bool rty = r == "RTY"
  1400.  
  1401. bool eurusd = str.contains(t, "EURUSD")
  1402. bool gbpusd = str.contains(t, "GBPUSD")
  1403. bool audusd = str.contains(t, "AUDUSD")
  1404. bool nzdusd = str.contains(t, "NZDUSD")
  1405. bool usdchf = str.contains(t, "USDCHF")
  1406. bool usdcad = str.contains(t, "USDCAD")
  1407. bool usdjpy = str.contains(t, "USDJPY")
  1408.  
  1409. bool btc = str.contains(t, "BTC")
  1410. bool eth = str.contains(t, "ETH")
  1411. bool sol = str.contains(t, "SOL")
  1412.  
  1413. es ? "CBOT_MINI:YM1!" :
  1414. nq ? "CBOT_MINI:YM1!" :
  1415. ym ? "CME_MINI:NQ1!" :
  1416. rty ? "CME_MINI:NQ1!" :
  1417. eurusd ? "TVC:DXY" :
  1418. gbpusd ? "TVC:DXY" :
  1419. audusd ? "TVC:DXY" :
  1420. nzdusd ? "TVC:DXY" :
  1421. usdchf ? "OANDA:EURUSD" :
  1422. usdcad ? "OANDA:AUDUSD" :
  1423. usdjpy ? "OANDA:EURJPY" :
  1424. btc ? "BINANCE:SOLUSDT" :
  1425. eth ? "BINANCE:SOLUSDT" :
  1426. sol ? "BINANCE:ETHUSDT" :
  1427. manualSMTSymbol2
  1428.  
  1429. f_autoSMTRelation2() =>
  1430. string t = str.upper(syminfo.ticker)
  1431. bool eurusd = str.contains(t, "EURUSD")
  1432. bool gbpusd = str.contains(t, "GBPUSD")
  1433. bool audusd = str.contains(t, "AUDUSD")
  1434. bool nzdusd = str.contains(t, "NZDUSD")
  1435. bool usdchf = str.contains(t, "USDCHF")
  1436. bool usdjpy = str.contains(t, "USDJPY")
  1437.  
  1438. eurusd or gbpusd or audusd or nzdusd or usdchf or usdjpy ? -1 : 1
  1439.  
  1440. string smtSymbol1 = smtMode == "Auto Matrix" ? f_autoSMTSymbol1() : manualSMTSymbol1
  1441. string smtSymbol2 = smtMode == "Auto Matrix" ? f_autoSMTSymbol2() : manualSMTSymbol2
  1442. int smtRelation1 = smtMode == "Auto Matrix" ? f_autoSMTRelation1() : (manualSMTRelation1 == "Direct" ? 1 : -1)
  1443. int smtRelation2 = smtMode == "Auto Matrix" ? f_autoSMTRelation2() : (manualSMTRelation2 == "Direct" ? 1 : -1)
  1444.  
  1445. // v20.9.3.1 — Bundle each SMT market into one request tuple.
  1446. // This preserves the exact SMT values while reducing six unique requests to two.
  1447. [smtHigh1, smtLow1, smtATR1] = request.security(
  1448. smtSymbol1,
  1449. selectedHTF,
  1450. [high, low, ta.atr(14)],
  1451. gaps = barmerge.gaps_off,
  1452. lookahead = barmerge.lookahead_off,
  1453. ignore_invalid_symbol = true
  1454. )
  1455.  
  1456. [smtHigh2, smtLow2, smtATR2] = request.security(
  1457. smtSymbol2,
  1458. selectedHTF,
  1459. [high, low, ta.atr(14)],
  1460. gaps = barmerge.gaps_off,
  1461. lookahead = barmerge.lookahead_off,
  1462. ignore_invalid_symbol = true
  1463. )
  1464.  
  1465. float ownPriorHigh = ta.highest(high[1], smtLookback)
  1466. float ownPriorLow = ta.lowest(low[1], smtLookback)
  1467. float ownTolerance = ta.atr(14) * smtToleranceATR
  1468.  
  1469. bool ownHH = high > ownPriorHigh + ownTolerance
  1470. bool ownLL = low < ownPriorLow - ownTolerance
  1471.  
  1472. f_smtState(float comparisonHigh, float comparisonLow, float comparisonATR, int relation) =>
  1473. bool comparisonDataReady =
  1474. not na(comparisonHigh) and
  1475. not na(comparisonLow) and
  1476. not na(comparisonATR)
  1477.  
  1478. float comparisonPriorHigh = ta.highest(comparisonHigh[1], smtLookback)
  1479. float comparisonPriorLow = ta.lowest(comparisonLow[1], smtLookback)
  1480. float comparisonTolerance = comparisonATR * smtToleranceATR
  1481.  
  1482. bool comparisonHistoryReady =
  1483. comparisonDataReady and
  1484. not na(comparisonPriorHigh) and
  1485. not na(comparisonPriorLow)
  1486.  
  1487. bool comparisonHH =
  1488. comparisonHistoryReady and
  1489. comparisonHigh > comparisonPriorHigh + comparisonTolerance
  1490.  
  1491. bool comparisonLL =
  1492. comparisonHistoryReady and
  1493. comparisonLow < comparisonPriorLow - comparisonTolerance
  1494.  
  1495. bool bullishDirect = comparisonHistoryReady and ((ownLL and not comparisonLL) or (comparisonLL and not ownLL))
  1496. bool bearishDirect = comparisonHistoryReady and ((ownHH and not comparisonHH) or (comparisonHH and not ownHH))
  1497.  
  1498. bool bullishInverse = comparisonHistoryReady and ((ownLL and not comparisonHH) or (comparisonHH and not ownLL))
  1499. bool bearishInverse = comparisonHistoryReady and ((ownHH and not comparisonLL) or (comparisonLL and not ownHH))
  1500.  
  1501. int state =
  1502. not comparisonHistoryReady ? 0 :
  1503. relation == 1 ?
  1504. (bullishDirect ? 1 : bearishDirect ? -1 : 0) :
  1505. (bullishInverse ? 1 : bearishInverse ? -1 : 0)
  1506. state
  1507.  
  1508. int smtState1 = f_smtState(smtHigh1, smtLow1, smtATR1, smtRelation1)
  1509. int smtState2 = useSecondSMTMarket ? f_smtState(smtHigh2, smtLow2, smtATR2, smtRelation2) : 0
  1510.  
  1511. int bullishSMTCount = (smtState1 == 1 ? 1 : 0) + (smtState2 == 1 ? 1 : 0)
  1512. int bearishSMTCount = (smtState1 == -1 ? 1 : 0) + (smtState2 == -1 ? 1 : 0)
  1513.  
  1514. bool bullishSMT = bullishSMTCount >= minimumSMTConfirmations
  1515. bool bearishSMT = bearishSMTCount >= minimumSMTConfirmations
  1516.  
  1517. //======================================================================
  1518. // 8. CRT HIERARCHY ALIGNMENT
  1519. //======================================================================
  1520. f_parentTimeframe(string childTF) =>
  1521. childTF == "W" ? "M" :
  1522. childTF == "D" ? "W" :
  1523. childTF == "240" or childTF == "180" or childTF == "120" ? "D" :
  1524. childTF == "60" ? "240" :
  1525. childTF == "30" ? "60" :
  1526. ""
  1527.  
  1528. f_activeStructuralCRTDirection() =>
  1529. float parentRangeHigh = high[1]
  1530. float parentRangeLow = low[1]
  1531. bool parentSweptHigh = high > parentRangeHigh
  1532. bool parentSweptLow = low < parentRangeLow
  1533. bool parentSingleSweep = parentSweptHigh != parentSweptLow
  1534. bool parentClosedInside = close < parentRangeHigh and close > parentRangeLow
  1535.  
  1536. bool parentBase =
  1537. barstate.isconfirmed and
  1538. parentSingleSweep and
  1539. (not rejectDoubleSweep or not (parentSweptHigh and parentSweptLow)) and
  1540. (not requireCloseInside or parentClosedInside)
  1541.  
  1542. int parentEventDirection =
  1543. parentBase and parentSweptLow and not parentSweptHigh ? 1 :
  1544. parentBase and parentSweptHigh and not parentSweptLow ? -1 : 0
  1545.  
  1546. bool parentEvent = parentEventDirection != 0
  1547. int latestParentDirection = nz(ta.valuewhen(parentEvent, parentEventDirection, 0), 0)
  1548. float latestParentRangeHigh = ta.valuewhen(parentEvent, parentRangeHigh, 0)
  1549. float latestParentRangeLow = ta.valuewhen(parentEvent, parentRangeLow, 0)
  1550. int parentBarsSinceEvent = ta.barssince(parentEvent)
  1551.  
  1552. bool hasParentCRT =
  1553. latestParentDirection != 0 and
  1554. not na(latestParentRangeHigh) and
  1555. not na(latestParentRangeLow) and
  1556. not na(parentBarsSinceEvent)
  1557.  
  1558. bool parentTargetReached =
  1559. hasParentCRT and parentBarsSinceEvent > 0 and (
  1560. latestParentDirection == 1 ?
  1561. (targetRequiresClose ? close >= latestParentRangeHigh : high >= latestParentRangeHigh) :
  1562. (targetRequiresClose ? close <= latestParentRangeLow : low <= latestParentRangeLow)
  1563. )
  1564.  
  1565. bool parentInvalidated =
  1566. hasParentCRT and parentBarsSinceEvent > 0 and (
  1567. latestParentDirection == 1 ?
  1568. (invalidationRequiresClose ? close < latestParentRangeLow : low < latestParentRangeLow) :
  1569. (invalidationRequiresClose ? close > latestParentRangeHigh : high > latestParentRangeHigh)
  1570. )
  1571.  
  1572. bool parentExpired = hasParentCRT and parentBarsSinceEvent > lifecycleExpiryBars
  1573. bool parentActive = hasParentCRT and not parentTargetReached and not parentInvalidated and not parentExpired
  1574.  
  1575. parentActive ? latestParentDirection : 0
  1576.  
  1577. f_activeStructuralCRTContext() =>
  1578. float pRangeHigh = high[1]
  1579. float pRangeLow = low[1]
  1580. bool pSweptHigh = high > pRangeHigh
  1581. bool pSweptLow = low < pRangeLow
  1582. bool pSingleSweep = pSweptHigh != pSweptLow
  1583. bool pClosedInside = close < pRangeHigh and close > pRangeLow
  1584.  
  1585. bool pBase =
  1586. barstate.isconfirmed and
  1587. pSingleSweep and
  1588. (not rejectDoubleSweep or not (pSweptHigh and pSweptLow)) and
  1589. (not requireCloseInside or pClosedInside)
  1590.  
  1591. int pEventDirection =
  1592. pBase and pSweptLow and not pSweptHigh ? 1 :
  1593. pBase and pSweptHigh and not pSweptLow ? -1 : 0
  1594.  
  1595. bool pEvent = pEventDirection != 0
  1596. int pLatestDirection = nz(ta.valuewhen(pEvent, pEventDirection, 0), 0)
  1597. float pLatestHigh = ta.valuewhen(pEvent, pRangeHigh, 0)
  1598. float pLatestLow = ta.valuewhen(pEvent, pRangeLow, 0)
  1599. int pBarsSince = ta.barssince(pEvent)
  1600.  
  1601. bool pHasCRT =
  1602. pLatestDirection != 0 and
  1603. not na(pLatestHigh) and
  1604. not na(pLatestLow) and
  1605. not na(pBarsSince)
  1606.  
  1607. bool pTargetReached =
  1608. pHasCRT and pBarsSince > 0 and (
  1609. pLatestDirection == 1 ?
  1610. (targetRequiresClose ? close >= pLatestHigh : high >= pLatestHigh) :
  1611. (targetRequiresClose ? close <= pLatestLow : low <= pLatestLow)
  1612. )
  1613.  
  1614. bool pInvalidated =
  1615. pHasCRT and pBarsSince > 0 and (
  1616. pLatestDirection == 1 ?
  1617. (invalidationRequiresClose ? close < pLatestLow : low < pLatestLow) :
  1618. (invalidationRequiresClose ? close > pLatestHigh : high > pLatestHigh)
  1619. )
  1620.  
  1621. bool pExpired = pHasCRT and pBarsSince > lifecycleExpiryBars
  1622. bool pActive = pHasCRT and not pTargetReached and not pInvalidated and not pExpired
  1623.  
  1624. [pActive ? pLatestDirection : 0, pActive ? pLatestHigh : na, pActive ? pLatestLow : na]
  1625.  
  1626. string parentHierarchyTF = f_parentTimeframe(selectedHTF)
  1627.  
  1628. string parentContextRequestTF = parentHierarchyTF == "" ? selectedHTF : parentHierarchyTF
  1629.  
  1630. // v20.9.3.1 — One parent-context request supplies direction, high and low.
  1631. [parentContextDirectionRaw, parentContextHighRaw, parentContextLowRaw] =
  1632. request.security(
  1633. syminfo.tickerid,
  1634. parentContextRequestTF,
  1635. f_activeStructuralCRTContext(),
  1636. gaps = barmerge.gaps_off,
  1637. lookahead = barmerge.lookahead_off
  1638. )
  1639.  
  1640. int parentCRTDirection = parentHierarchyTF == "" ? 0 : parentContextDirectionRaw
  1641. int parentContextDirection = parentHierarchyTF == "" ? 0 : parentContextDirectionRaw
  1642. float parentContextHigh = parentHierarchyTF == "" ? na : parentContextHighRaw
  1643. float parentContextLow = parentHierarchyTF == "" ? na : parentContextLowRaw
  1644.  
  1645. //======================================================================
  1646. // 9. HIGHER-TIMEFRAME KEY LEVELS
  1647. // Previous completed day/week/month levels; non-repainting.
  1648. //======================================================================
  1649. // v20.9.3.1 — Bundle each completed period's high/low into one request.
  1650. [previousDayHigh, previousDayLow] = request.security(syminfo.tickerid, "D", [high[1], low[1]], lookahead = barmerge.lookahead_on)
  1651. [previousWeekHigh, previousWeekLow] = request.security(syminfo.tickerid, "W", [high[1], low[1]], lookahead = barmerge.lookahead_on)
  1652. [previousMonthHigh, previousMonthLow] = request.security(syminfo.tickerid, "M", [high[1], low[1]], lookahead = barmerge.lookahead_on)
  1653.  
  1654. //======================================================================
  1655. // 8. RANGE + MANIPULATION STRUCTURE
  1656. // Candle [1] = potential Range candle
  1657. // Candle [0] = potential Manipulation candle
  1658. //======================================================================
  1659. float rangeHigh = high[1]
  1660. float rangeLow = low[1]
  1661. float rangeOpen = open[1]
  1662. float rangeClose = close[1]
  1663. float rangeSize = math.max(rangeHigh - rangeLow, syminfo.mintick)
  1664. float rangeMidpoint = (rangeHigh + rangeLow) * 0.5
  1665. float rangeBodyPercent = math.abs(rangeClose - rangeOpen) / rangeSize * 100.0
  1666.  
  1667. bool sweptHigh = high > rangeHigh
  1668. bool sweptLow = low < rangeLow
  1669. bool sweptBoth = sweptHigh and sweptLow
  1670. bool singleSweep = sweptHigh != sweptLow
  1671. bool closedInside = close < rangeHigh and close > rangeLow
  1672.  
  1673. bool bullishDirectionOK = not requireDirectionalClose or close > open
  1674. bool bearishDirectionOK = not requireDirectionalClose or close < open
  1675.  
  1676. bool baseRules =
  1677. barstate.isconfirmed and
  1678. singleSweep and
  1679. (not rejectDoubleSweep or not sweptBoth) and
  1680. (not requireCloseInside or closedInside)
  1681.  
  1682. bool bullishCandidate = baseRules and sweptLow and not sweptHigh and bullishDirectionOK
  1683. bool bearishCandidate = baseRules and sweptHigh and not sweptLow and bearishDirectionOK
  1684.  
  1685. //======================================================================
  1686. // 8A. PROTOCOL 11 — CRT SEQUENCE / NESTED ACTIVE PARENT RANGE
  1687. // Informational bonus only. Stable v16.9 qualification remains unchanged.
  1688. //======================================================================
  1689. bool parentContextActive =
  1690. useNestedCRTContext and
  1691. parentContextDirection != 0 and
  1692. not na(parentContextHigh) and
  1693. not na(parentContextLow)
  1694.  
  1695. bool localRangeContainedInParent =
  1696. parentContextActive and
  1697. rangeHigh <= parentContextHigh and
  1698. rangeLow >= parentContextLow
  1699.  
  1700. bool localRangeOverlapsParent =
  1701. parentContextActive and
  1702. rangeHigh >= parentContextLow and
  1703. rangeLow <= parentContextHigh
  1704.  
  1705. bool nestedInsideParent =
  1706. requireFullParentContainment ?
  1707. localRangeContainedInParent :
  1708. localRangeOverlapsParent
  1709.  
  1710. bool nestedDirectionAligned =
  1711. parentContextActive and (
  1712. (bullishCandidate and parentContextDirection == 1) or
  1713. (bearishCandidate and parentContextDirection == -1)
  1714. )
  1715.  
  1716. float parentContextMidpoint =
  1717. parentContextActive ? (parentContextHigh + parentContextLow) * 0.5 : na
  1718.  
  1719. bool nestedLocationAligned =
  1720. parentContextActive and
  1721. useParentPremiumDiscount and (
  1722. (bullishCandidate and rangeMidpoint <= parentContextMidpoint) or
  1723. (bearishCandidate and rangeMidpoint >= parentContextMidpoint)
  1724. )
  1725.  
  1726. int nestedContextScore =
  1727. (nestedInsideParent ? 1 : 0) +
  1728. (nestedDirectionAligned ? 1 : 0) +
  1729. (nestedLocationAligned ? 1 : 0)
  1730.  
  1731. bool meaningfulNestedContext =
  1732. useNestedCRTContext and
  1733. nestedContextScore >= minimumNestedContextScore
  1734.  
  1735. //======================================================================
  1736. // 9. SILENT PROTOCOL TESTS
  1737. //======================================================================
  1738. float atr = ta.atr(14)
  1739.  
  1740. //======================================================================
  1741. // 9A. PROTOCOL 10 — MEANINGFUL LIQUIDITY PURGE BONUS CONTEXT
  1742. // This module is informational only and cannot reject a v16.7 CRT.
  1743. //======================================================================
  1744. float liquidityTolerance = atr[1] * liquidityToleranceATR
  1745. float priorSwingHigh = ta.highest(high[2], liquiditySwingLookback)
  1746. float priorSwingLow = ta.lowest(low[2], liquiditySwingLookback)
  1747.  
  1748. bool purgedPDH = bearishCandidate and not na(previousDayHigh[1]) and high > previousDayHigh[1] + liquidityTolerance
  1749. bool purgedPDL = bullishCandidate and not na(previousDayLow[1]) and low < previousDayLow[1] - liquidityTolerance
  1750. bool purgedPWH = bearishCandidate and not na(previousWeekHigh[1]) and high > previousWeekHigh[1] + liquidityTolerance
  1751. bool purgedPWL = bullishCandidate and not na(previousWeekLow[1]) and low < previousWeekLow[1] - liquidityTolerance
  1752. bool purgedPMH = bearishCandidate and not na(previousMonthHigh[1]) and high > previousMonthHigh[1] + liquidityTolerance
  1753. bool purgedPML = bullishCandidate and not na(previousMonthLow[1]) and low < previousMonthLow[1] - liquidityTolerance
  1754. bool purgedSwingHigh = bearishCandidate and not na(priorSwingHigh) and high > priorSwingHigh + liquidityTolerance
  1755. bool purgedSwingLow = bullishCandidate and not na(priorSwingLow) and low < priorSwingLow - liquidityTolerance
  1756.  
  1757. int liquidityPurgeScore =
  1758. (purgedPDH or purgedPDL ? 1 : 0) +
  1759. (purgedPWH or purgedPWL ? 2 : 0) +
  1760. (purgedPMH or purgedPML ? 3 : 0) +
  1761. (purgedSwingHigh or purgedSwingLow ? 1 : 0)
  1762.  
  1763. bool meaningfulLiquidityPurge =
  1764. useLiquidityPurgeContext and
  1765. liquidityPurgeScore >= minimumLiquidityPurgeScore
  1766.  
  1767. float keyTolerance = atr[1] * keyLevelToleranceATR
  1768.  
  1769. bool timeProtocol = isAllowedRangeHour(time[1])
  1770.  
  1771. bool keyLevelProtocol =
  1772. isNearLevel(rangeHigh, rangeLow, previousDayHigh[1], keyTolerance) or
  1773. isNearLevel(rangeHigh, rangeLow, previousDayLow[1], keyTolerance) or
  1774. isNearLevel(rangeHigh, rangeLow, previousWeekHigh[1], keyTolerance) or
  1775. isNearLevel(rangeHigh, rangeLow, previousWeekLow[1], keyTolerance) or
  1776. isNearLevel(rangeHigh, rangeLow, previousMonthHigh[1], keyTolerance) or
  1777. isNearLevel(rangeHigh, rangeLow, previousMonthLow[1], keyTolerance)
  1778.  
  1779. float manipulationRange = math.max(high - low, syminfo.mintick)
  1780. float lowerRejectionPercent = (math.min(open, close) - low) / manipulationRange * 100.0
  1781. float upperRejectionPercent = (high - math.max(open, close)) / manipulationRange * 100.0
  1782.  
  1783. bool rejectionProtocol =
  1784. (bullishCandidate and lowerRejectionPercent >= minimumRejectionPercent) or
  1785. (bearishCandidate and upperRejectionPercent >= minimumRejectionPercent)
  1786.  
  1787. bool midpointProtocol =
  1788. (bullishCandidate and close > rangeMidpoint) or
  1789. (bearishCandidate and close < rangeMidpoint)
  1790.  
  1791. float rangeATRRatio = atr[1] > 0.0 ? rangeSize / atr[1] : 0.0
  1792. bool rangeSizeProtocol = rangeATRRatio >= minimumRangeATR and rangeATRRatio <= maximumRangeATR
  1793.  
  1794. bool bodyProtocol =
  1795. rangeBodyPercent >= minimumRangeBodyPercent and
  1796. rangeBodyPercent <= maximumRangeBodyPercent
  1797.  
  1798. float poiTolerance = atr[1] * poiToleranceATR
  1799. [bullPOITypes, bearPOITypes, bullPOIScore, bearPOIScore] = f_detectDirectionalPOIs(rangeHigh, rangeLow, poiTolerance)
  1800. bool bullishPOIAligned = bullPOITypes >= minimumPOITypes and bullPOIScore >= minimumDirectionalPOIScore and (not rejectOpposingPOIDominance or bullPOIScore >= bearPOIScore)
  1801. bool bearishPOIAligned = bearPOITypes >= minimumPOITypes and bearPOIScore >= minimumDirectionalPOIScore and (not rejectOpposingPOIDominance or bearPOIScore >= bullPOIScore)
  1802. bool poiProtocol = (bullishCandidate and bullishPOIAligned) or (bearishCandidate and bearishPOIAligned)
  1803. int poiTypeScore = bullishCandidate ? bullPOITypes : bearishCandidate ? bearPOITypes : 0
  1804. int directionalPOIScore = bullishCandidate ? bullPOIScore : bearishCandidate ? bearPOIScore : 0
  1805.  
  1806. bool hierarchyAligned =
  1807. (bullishCandidate and parentCRTDirection == 1) or
  1808. (bearishCandidate and parentCRTDirection == -1)
  1809.  
  1810. bool hierarchyNeutral = parentCRTDirection == 0
  1811.  
  1812. bool hierarchyOpposing =
  1813. (bullishCandidate and parentCRTDirection == -1) or
  1814. (bearishCandidate and parentCRTDirection == 1)
  1815.  
  1816. bool hierarchyProtocol = hierarchyAligned or (hierarchyNeutral and neutralHierarchyPass)
  1817.  
  1818. bool hierarchyHardPass =
  1819. not useHierarchyProtocol or
  1820. not rejectOpposingHierarchy or
  1821. not hierarchyOpposing
  1822.  
  1823. int alignedSMTCount =
  1824. bullishCandidate ? bullishSMTCount :
  1825. bearishCandidate ? bearishSMTCount : 0
  1826.  
  1827. int opposingSMTCount =
  1828. bullishCandidate ? bearishSMTCount :
  1829. bearishCandidate ? bullishSMTCount : 0
  1830.  
  1831. bool smtAligned = alignedSMTCount >= minimumSMTConfirmations
  1832. bool smtOpposing = opposingSMTCount > alignedSMTCount and opposingSMTCount > 0
  1833. bool smtNeutral = alignedSMTCount == 0 and opposingSMTCount == 0
  1834.  
  1835. bool smtProtocol =
  1836. smtAligned or
  1837. (smtNeutral and allowNeutralSMT)
  1838.  
  1839. bool smtHardPass =
  1840. not useSMTProtocol or
  1841. not rejectOpposingSMT or
  1842. not smtOpposing
  1843.  
  1844. int enabledProtocols =
  1845. (useTimeProtocol ? 1 : 0) +
  1846. (useKeyLevelProtocol ? 1 : 0) +
  1847. (useRejectionProtocol ? 1 : 0) +
  1848. (useMidpointProtocol ? 1 : 0) +
  1849. (useRangeSizeProtocol ? 1 : 0) +
  1850. (useBodyProtocol ? 1 : 0) +
  1851. (usePOIProtocol ? 1 : 0) +
  1852. (useHierarchyProtocol ? 1 : 0) +
  1853. (useSMTProtocol ? 1 : 0)
  1854.  
  1855. int protocolScore =
  1856. (useTimeProtocol and timeProtocol ? 1 : 0) +
  1857. (useKeyLevelProtocol and keyLevelProtocol ? 1 : 0) +
  1858. (useRejectionProtocol and rejectionProtocol ? 1 : 0) +
  1859. (useMidpointProtocol and midpointProtocol ? 1 : 0) +
  1860. (useRangeSizeProtocol and rangeSizeProtocol ? 1 : 0) +
  1861. (useBodyProtocol and bodyProtocol ? 1 : 0) +
  1862. (usePOIProtocol and poiProtocol ? 1 : 0) +
  1863. (useHierarchyProtocol and hierarchyProtocol ? 1 : 0) +
  1864. (useSMTProtocol and smtProtocol ? 1 : 0)
  1865.  
  1866. // Protocol 10 is a bonus only and is deliberately excluded from
  1867. // enabledProtocols, protocolScore, effectiveMinimum and protocolQualified.
  1868. int protocolScoreWithLiquidityBonus =
  1869. protocolScore + (meaningfulLiquidityPurge ? 1 : 0)
  1870.  
  1871. int protocolScoreWithContextBonuses =
  1872. protocolScore +
  1873. (meaningfulLiquidityPurge ? 1 : 0) +
  1874. (meaningfulNestedContext ? 1 : 0)
  1875.  
  1876. int effectiveMinimum = math.min(minimumProtocols, math.max(enabledProtocols, 1))
  1877. bool protocolQualified = protocolScore >= effectiveMinimum and hierarchyHardPass and smtHardPass
  1878.  
  1879. bool bullishManipulation = bullishCandidate and protocolQualified
  1880. bool bearishManipulation = bearishCandidate and protocolQualified
  1881. bool qualifiedCRT = bullishManipulation or bearishManipulation
  1882. bool rawQualifiedCRT = bullishCandidate or bearishCandidate
  1883. bool visibleCRT = showRawCRTForTesting ? rawQualifiedCRT : qualifiedCRT
  1884.  
  1885. int currentQualifiedCRTDirection =
  1886. bullishManipulation ? 1 :
  1887. bearishManipulation ? -1 : 0
  1888.  
  1889. bool dedicatedKeyLevelAligned =
  1890. useDedicatedKeyLevelEngine and
  1891. qualifiedCRT and
  1892. sourceKeyLevelType != 0 and
  1893. sourceKeyDirection == currentQualifiedCRTDirection
  1894.  
  1895. int currentKeyLevelType =
  1896. dedicatedKeyLevelAligned ? sourceKeyLevelType : 0
  1897.  
  1898. int latestKeyLevelType =
  1899. nz(ta.valuewhen(qualifiedCRT, currentKeyLevelType, 0), 0)
  1900.  
  1901. int latestKeyLevelDirection =
  1902. nz(ta.valuewhen(qualifiedCRT, currentQualifiedCRTDirection, 0), 0)
  1903.  
  1904. int latestKeyLevelWeight =
  1905. nz(ta.valuewhen(qualifiedCRT, dedicatedKeyLevelAligned ? sourceKeyLevelWeight : 0, 0), 0)
  1906.  
  1907.  
  1908.  
  1909. //======================================================================
  1910. // 11A. PROTOCOL 12 — POST-MANIPULATION DISPLACEMENT / DELIVERY
  1911. // Delayed bonus context only. A CRT is first confirmed normally; the next
  1912. // configured bars are then evaluated for directional delivery.
  1913. //======================================================================
  1914. int barsSinceQualifiedForDelivery = ta.barssince(qualifiedCRT)
  1915. bool deliveryWindowActive =
  1916. useDeliveryContext and
  1917. not na(barsSinceQualifiedForDelivery) and
  1918. barsSinceQualifiedForDelivery >= 1 and
  1919. barsSinceQualifiedForDelivery <= deliveryWindowBars
  1920.  
  1921. int deliveryCRTDirection = nz(ta.valuewhen(qualifiedCRT, bullishManipulation ? 1 : -1, 0), 0)
  1922. float deliveryRangeHigh = ta.valuewhen(qualifiedCRT, rangeHigh, 0)
  1923. float deliveryRangeLow = ta.valuewhen(qualifiedCRT, rangeLow, 0)
  1924. float deliveryRangeMid = not na(deliveryRangeHigh) and not na(deliveryRangeLow) ? (deliveryRangeHigh + deliveryRangeLow) * 0.5 : na
  1925. float deliveryATR = ta.atr(14)
  1926. float deliveryBody = math.abs(close - open)
  1927.  
  1928. bool directionalDelivery =
  1929. deliveryWindowActive and (
  1930. (deliveryCRTDirection == 1 and close > open) or
  1931. (deliveryCRTDirection == -1 and close < open)
  1932. )
  1933.  
  1934. bool strongDeliveryBody =
  1935. deliveryWindowActive and
  1936. deliveryATR > 0 and
  1937. deliveryBody >= deliveryATR * minimumDeliveryBodyATR
  1938.  
  1939. bool deliveredThroughRangeMid =
  1940. deliveryWindowActive and
  1941. not na(deliveryRangeMid) and (
  1942. (deliveryCRTDirection == 1 and close > deliveryRangeMid) or
  1943. (deliveryCRTDirection == -1 and close < deliveryRangeMid)
  1944. )
  1945.  
  1946. bool bullishDeliveryFVG =
  1947. deliveryWindowActive and
  1948. deliveryCRTDirection == 1 and
  1949. bar_index >= 2 and
  1950. low > high[2]
  1951.  
  1952. bool bearishDeliveryFVG =
  1953. deliveryWindowActive and
  1954. deliveryCRTDirection == -1 and
  1955. bar_index >= 2 and
  1956. high < low[2]
  1957.  
  1958. bool deliveryFVGCreated = bullishDeliveryFVG or bearishDeliveryFVG
  1959.  
  1960. int currentDeliveryScore =
  1961. (directionalDelivery ? 1 : 0) +
  1962. (strongDeliveryBody ? 1 : 0) +
  1963. (deliveredThroughRangeMid ? 1 : 0) +
  1964. (deliveryFVGCreated ? 1 : 0)
  1965.  
  1966. var int deliveryContextScore = 0
  1967.  
  1968. if qualifiedCRT
  1969. deliveryContextScore := 0
  1970. else if deliveryWindowActive
  1971. deliveryContextScore := math.max(deliveryContextScore, currentDeliveryScore)
  1972. else
  1973. deliveryContextScore := 0
  1974.  
  1975. bool priorDeliveryFVG =
  1976. bar_index > 0 and deliveryFVGCreated[1]
  1977.  
  1978. bool meaningfulDeliveryContext =
  1979. useDeliveryContext and
  1980. deliveryWindowActive and
  1981. deliveryContextScore >= minimumDeliveryScore and
  1982. (not requireDeliveryFVG or deliveryFVGCreated or priorDeliveryFVG)
  1983.  
  1984. //======================================================================
  1985. // 12. ACTIVE CRT LIFECYCLE
  1986. // Status codes: 0=None, 1=Active Bullish, -1=Active Bearish,
  1987. // 2=Target Reached, -2=Invalidated, 3=Expired.
  1988. //======================================================================
  1989. int newCRTDirection = bullishManipulation ? 1 : bearishManipulation ? -1 : 0
  1990. bool newQualifiedCRT = newCRTDirection != 0
  1991.  
  1992. int latestCRTDirection = nz(ta.valuewhen(newQualifiedCRT, newCRTDirection, 0), 0)
  1993. float latestCRTRangeHigh = ta.valuewhen(newQualifiedCRT, rangeHigh, 0)
  1994. float latestCRTRangeLow = ta.valuewhen(newQualifiedCRT, rangeLow, 0)
  1995. int barsSinceQualifiedCRT = ta.barssince(newQualifiedCRT)
  1996.  
  1997. bool hasTrackedCRT =
  1998. latestCRTDirection != 0 and
  1999. not na(latestCRTRangeHigh) and
  2000. not na(latestCRTRangeLow) and
  2001. not na(barsSinceQualifiedCRT)
  2002.  
  2003. bool crtTargetReached =
  2004. hasTrackedCRT and barsSinceQualifiedCRT > 0 and (
  2005. latestCRTDirection == 1 ?
  2006. (targetRequiresClose ? close >= latestCRTRangeHigh : high >= latestCRTRangeHigh) :
  2007. (targetRequiresClose ? close <= latestCRTRangeLow : low <= latestCRTRangeLow)
  2008. )
  2009.  
  2010. bool crtInvalidated =
  2011. hasTrackedCRT and barsSinceQualifiedCRT > 0 and (
  2012. latestCRTDirection == 1 ?
  2013. (invalidationRequiresClose ? close < latestCRTRangeLow : low < latestCRTRangeLow) :
  2014. (invalidationRequiresClose ? close > latestCRTRangeHigh : high > latestCRTRangeHigh)
  2015. )
  2016.  
  2017. bool crtExpired = hasTrackedCRT and barsSinceQualifiedCRT > lifecycleExpiryBars
  2018.  
  2019. bool crtLifecycleActive =
  2020. hasTrackedCRT and
  2021. not crtTargetReached and
  2022. not crtInvalidated and
  2023. not crtExpired
  2024.  
  2025. int activeCRTDirection = crtLifecycleActive ? latestCRTDirection : 0
  2026.  
  2027. int crtLifecycleStatus =
  2028. crtLifecycleActive ? latestCRTDirection :
  2029. crtTargetReached ? 2 :
  2030. crtInvalidated ? -2 :
  2031. crtExpired ? 3 : 0
  2032.  
  2033.  
  2034. //======================================================================
  2035. // 12A. PROTOCOL 13 — FAILED CRT / REVERSAL CONTEXT
  2036. // A qualified CRT failure is opposite-direction information only.
  2037. // This module is context/alert logic and does not alter CRT qualification.
  2038. //======================================================================
  2039. bool failureWindowActive =
  2040. useFailedCRTContext and
  2041. hasTrackedCRT and
  2042. barsSinceQualifiedCRT > 0 and
  2043. barsSinceQualifiedCRT <= failureWindowBars
  2044.  
  2045. float failedCRTBoundary =
  2046. latestCRTDirection == 1 ? latestCRTRangeLow :
  2047. latestCRTDirection == -1 ? latestCRTRangeHigh : na
  2048.  
  2049. bool failedThroughBoundary =
  2050. failureWindowActive and (
  2051. latestCRTDirection == 1 ?
  2052. (failureRequiresClose ? close < failedCRTBoundary : low < failedCRTBoundary) :
  2053. latestCRTDirection == -1 ?
  2054. (failureRequiresClose ? close > failedCRTBoundary : high > failedCRTBoundary) :
  2055. false
  2056. )
  2057.  
  2058. bool failureDirectionOK =
  2059. not requireFailureDirectionalClose or (
  2060. (latestCRTDirection == 1 and close < open) or
  2061. (latestCRTDirection == -1 and close > open)
  2062. )
  2063.  
  2064. float failureATR = ta.atr(14)
  2065. float failureBody = math.abs(close - open)
  2066. bool failureBodyOK =
  2067. failureATR > 0 and
  2068. failureBody >= failureATR * minimumFailureBodyATR
  2069.  
  2070. bool failedCRTEvent =
  2071. failedThroughBoundary and
  2072. failureDirectionOK and
  2073. failureBodyOK and
  2074. not failedThroughBoundary[1]
  2075.  
  2076. int failedCRTReversalDirection =
  2077. failedCRTEvent ?
  2078. (latestCRTDirection == 1 ? -1 : latestCRTDirection == -1 ? 1 : 0) :
  2079. 0
  2080.  
  2081. int latestFailedCRTReversalDirection =
  2082. nz(ta.valuewhen(failedCRTEvent, failedCRTReversalDirection, 0), 0)
  2083.  
  2084. int barsSinceFailedCRT = ta.barssince(failedCRTEvent)
  2085.  
  2086. bool failedCRTReversalContextActive =
  2087. useFailedCRTContext and
  2088. latestFailedCRTReversalDirection != 0 and
  2089. not na(barsSinceFailedCRT) and
  2090. barsSinceFailedCRT <= failureWindowBars
  2091.  
  2092.  
  2093. //======================================================================
  2094. // 12B. PROTOCOL 14 — CRT TARGET DELIVERY / DRAW ON LIQUIDITY
  2095. // Selects the nearest valid opposite-side objective for the latest
  2096. // qualified CRT. Context only; does not affect CRT qualification.
  2097. // Target type codes:
  2098. // 0=None, 1=Opposite CRT boundary, 2=Previous Day,
  2099. // 3=Previous Week, 4=Previous Month, 5=Swing Liquidity.
  2100. //======================================================================
  2101. float targetATR = ta.atr(14)
  2102. float targetTolerance = targetATR * targetReachToleranceATR
  2103. float targetSwingHigh = ta.highest(high[1], targetSwingLookback)
  2104. float targetSwingLow = ta.lowest(low[1], targetSwingLookback)
  2105.  
  2106. f_pickNearestBullishTarget(
  2107. float referencePrice,
  2108. float crtHigh,
  2109. float pdh,
  2110. float pwh,
  2111. float pmh,
  2112. float swingHigh
  2113. ) =>
  2114. float selectedTarget = na
  2115. int selectedType = 0
  2116. float bestDistance = na
  2117.  
  2118. if includeOppositeCRTRangeBoundary and not na(crtHigh) and crtHigh > referencePrice
  2119. selectedTarget := crtHigh
  2120. selectedType := 1
  2121. bestDistance := crtHigh - referencePrice
  2122.  
  2123. if includePreviousDayTarget and not na(pdh) and pdh > referencePrice
  2124. float distance = pdh - referencePrice
  2125. if na(bestDistance) or distance < bestDistance
  2126. selectedTarget := pdh
  2127. selectedType := 2
  2128. bestDistance := distance
  2129.  
  2130. if includePreviousWeekTarget and not na(pwh) and pwh > referencePrice
  2131. float distance = pwh - referencePrice
  2132. if na(bestDistance) or distance < bestDistance
  2133. selectedTarget := pwh
  2134. selectedType := 3
  2135. bestDistance := distance
  2136.  
  2137. if includePreviousMonthTarget and not na(pmh) and pmh > referencePrice
  2138. float distance = pmh - referencePrice
  2139. if na(bestDistance) or distance < bestDistance
  2140. selectedTarget := pmh
  2141. selectedType := 4
  2142. bestDistance := distance
  2143.  
  2144. if includeSwingLiquidityTarget and not na(swingHigh) and swingHigh > referencePrice
  2145. float distance = swingHigh - referencePrice
  2146. if na(bestDistance) or distance < bestDistance
  2147. selectedTarget := swingHigh
  2148. selectedType := 5
  2149.  
  2150. [selectedTarget, selectedType]
  2151.  
  2152. f_pickNearestBearishTarget(
  2153. float referencePrice,
  2154. float crtLow,
  2155. float pdl,
  2156. float pwl,
  2157. float pml,
  2158. float swingLow
  2159. ) =>
  2160. float selectedTarget = na
  2161. int selectedType = 0
  2162. float bestDistance = na
  2163.  
  2164. if includeOppositeCRTRangeBoundary and not na(crtLow) and crtLow < referencePrice
  2165. selectedTarget := crtLow
  2166. selectedType := 1
  2167. bestDistance := referencePrice - crtLow
  2168.  
  2169. if includePreviousDayTarget and not na(pdl) and pdl < referencePrice
  2170. float distance = referencePrice - pdl
  2171. if na(bestDistance) or distance < bestDistance
  2172. selectedTarget := pdl
  2173. selectedType := 2
  2174. bestDistance := distance
  2175.  
  2176. if includePreviousWeekTarget and not na(pwl) and pwl < referencePrice
  2177. float distance = referencePrice - pwl
  2178. if na(bestDistance) or distance < bestDistance
  2179. selectedTarget := pwl
  2180. selectedType := 3
  2181. bestDistance := distance
  2182.  
  2183. if includePreviousMonthTarget and not na(pml) and pml < referencePrice
  2184. float distance = referencePrice - pml
  2185. if na(bestDistance) or distance < bestDistance
  2186. selectedTarget := pml
  2187. selectedType := 4
  2188. bestDistance := distance
  2189.  
  2190. if includeSwingLiquidityTarget and not na(swingLow) and swingLow < referencePrice
  2191. float distance = referencePrice - swingLow
  2192. if na(bestDistance) or distance < bestDistance
  2193. selectedTarget := swingLow
  2194. selectedType := 5
  2195.  
  2196. [selectedTarget, selectedType]
  2197.  
  2198. float latestQualifiedClose = ta.valuewhen(newQualifiedCRT, close, 0)
  2199.  
  2200. [bullishDrawTarget, bullishDrawType] =
  2201. f_pickNearestBullishTarget(
  2202. latestQualifiedClose,
  2203. latestCRTRangeHigh,
  2204. previousDayHigh,
  2205. previousWeekHigh,
  2206. previousMonthHigh,
  2207. targetSwingHigh
  2208. )
  2209.  
  2210. [bearishDrawTarget, bearishDrawType] =
  2211. f_pickNearestBearishTarget(
  2212. latestQualifiedClose,
  2213. latestCRTRangeLow,
  2214. previousDayLow,
  2215. previousWeekLow,
  2216. previousMonthLow,
  2217. targetSwingLow
  2218. )
  2219.  
  2220. float activeDrawTarget =
  2221. not useTargetDeliveryContext ? na :
  2222. latestCRTDirection == 1 ? bullishDrawTarget :
  2223. latestCRTDirection == -1 ? bearishDrawTarget :
  2224. na
  2225.  
  2226. int activeDrawTargetType =
  2227. not useTargetDeliveryContext ? 0 :
  2228. latestCRTDirection == 1 ? bullishDrawType :
  2229. latestCRTDirection == -1 ? bearishDrawType :
  2230. 0
  2231.  
  2232. bool activeDrawTargetAvailable =
  2233. useTargetDeliveryContext and
  2234. hasTrackedCRT and
  2235. not na(activeDrawTarget) and
  2236. activeDrawTargetType != 0
  2237.  
  2238. bool activeDrawTargetReached =
  2239. activeDrawTargetAvailable and
  2240. barsSinceQualifiedCRT > 0 and (
  2241. latestCRTDirection == 1 ?
  2242. high >= activeDrawTarget - targetTolerance :
  2243. latestCRTDirection == -1 ?
  2244. low <= activeDrawTarget + targetTolerance :
  2245. false
  2246. )
  2247.  
  2248. bool newDrawTargetReached =
  2249. activeDrawTargetReached and
  2250. not activeDrawTargetReached[1]
  2251.  
  2252.  
  2253. //======================================================================
  2254. // 12C. CRT INTELLIGENCE SCORE / GRADE ENGINE
  2255. // Snapshot grade at CRT confirmation. No future-bar information is used
  2256. // in the initial grade, so historical grades do not improve retroactively.
  2257. // Score components:
  2258. // Base qualification=1, protocol depth=0..3, POI=1, SMT=1,
  2259. // liquidity purge=1, nested HTF context=1, target available=1, HTF align=1.
  2260. //======================================================================
  2261. int protocolDepthScore =
  2262. protocolScore >= 7 ? 1 :
  2263. protocolScore >= 5 ? 1 :
  2264. protocolScore >= 3 ? 1 : 0
  2265.  
  2266. // Major context confirmations carry the grade.
  2267. // A neutral or missing context never receives the same weight as alignment.
  2268. int majorContextCount =
  2269. (dedicatedKeyLevelAligned ? 1 : 0) +
  2270. (smtAligned ? 1 : 0) +
  2271. (meaningfulLiquidityPurge ? 1 : 0) +
  2272. (hierarchyAligned ? 1 : 0) +
  2273. (meaningfulNestedContext ? 1 : 0)
  2274.  
  2275. int rawCRTIntelligenceScore =
  2276. qualifiedCRT ?
  2277. protocolDepthScore +
  2278. (dedicatedKeyLevelAligned ? 2 : 0) +
  2279. (smtAligned ? 2 : 0) +
  2280. (meaningfulLiquidityPurge ? 2 : 0) +
  2281. (hierarchyAligned ? 2 : 0) +
  2282. (meaningfulNestedContext ? 1 : 0) :
  2283. 0
  2284.  
  2285. int boundedCRTIntelligenceScore = math.min(rawCRTIntelligenceScore, 10)
  2286.  
  2287. // Hard context gates prevent a technically valid but context-poor CRT
  2288. // from being labelled A or A+.
  2289. bool aPlusGradeGate =
  2290. majorContextCount >= 4 and
  2291. dedicatedKeyLevelAligned and
  2292. (hierarchyAligned or meaningfulNestedContext)
  2293.  
  2294. bool aGradeGate =
  2295. majorContextCount >= 3
  2296.  
  2297. bool bGradeGate =
  2298. majorContextCount >= 1
  2299.  
  2300. int currentCRTGradeCode =
  2301. not useIntelligenceGrade or not qualifiedCRT ? 0 :
  2302. boundedCRTIntelligenceScore >= gradeAPlusThreshold and aPlusGradeGate ? 4 :
  2303. boundedCRTIntelligenceScore >= gradeAThreshold and aGradeGate ? 3 :
  2304. boundedCRTIntelligenceScore >= gradeBThreshold and bGradeGate ? 2 : 1
  2305.  
  2306. int latestCRTIntelligenceScore =
  2307. nz(ta.valuewhen(qualifiedCRT, boundedCRTIntelligenceScore, 0), 0)
  2308.  
  2309. int latestCRTGradeCode =
  2310. nz(ta.valuewhen(qualifiedCRT, currentCRTGradeCode, 0), 0)
  2311.  
  2312. bool gradeAPlusCRT = qualifiedCRT and currentCRTGradeCode == 4
  2313. bool gradeACRT = qualifiedCRT and currentCRTGradeCode == 3
  2314. bool gradeBCRT = qualifiedCRT and currentCRTGradeCode == 2
  2315. bool gradeCCRT = qualifiedCRT and currentCRTGradeCode == 1
  2316.  
  2317. //======================================================================
  2318. // 10. CLEAN SOURCE-TF COLORS + AUTO AMD WINDOWS ON LOWER TIMEFRAMES
  2319. //======================================================================
  2320. int chartSeconds = currentChartSeconds
  2321. int projectionSeconds = timeframe.in_seconds(selectedHTF)
  2322. bool isSourceTimeframe = not na(chartSeconds) and not na(projectionSeconds) and chartSeconds == projectionSeconds
  2323. bool isLowerThanProjection = not na(chartSeconds) and not na(projectionSeconds) and chartSeconds < projectionSeconds
  2324.  
  2325. // Only the selected source timeframe may color CRT candles. Lower timeframes
  2326. // remain untouched so traders cannot confuse HTF projection with LTF CRTs.
  2327. // The history gate changes visibility only; `visibleCRT` and the full protocol
  2328. // engine continue calculating on every available bar.
  2329. bool crtVisualHistoryPass = f_visualHistoryPass(
  2330. crtVisualHistoryMode,
  2331. crtVisualRecentBars,
  2332. bar_index,
  2333. time
  2334. )
  2335.  
  2336. barcolor(
  2337. colorCandles and isSourceTimeframe and visibleCRT and crtVisualHistoryPass ? rangeColor : na,
  2338. offset = -1,
  2339. title = "Qualified CRT Range Candle"
  2340. )
  2341.  
  2342. barcolor(
  2343. colorCandles and isSourceTimeframe and visibleCRT and crtVisualHistoryPass ? manipulationColor : na,
  2344. title = "Qualified CRT Manipulation Candle"
  2345. )
  2346.  
  2347. //----------------------------------------------------------------------
  2348. // Ash ICT Fractal — exact original confirmed swing logic.
  2349. // The centre candle is evaluated only after `periods` candles have closed
  2350. // on its right, then the tiny marker is plotted back on that centre candle.
  2351. //----------------------------------------------------------------------
  2352. float ashICTFractalSourceHigh = ashICTFractalUseHighLow ? high : math.max(open, close)
  2353. float ashICTFractalSourceLow = ashICTFractalUseHighLow ? low : math.min(open, close)
  2354.  
  2355. bool ashICTFractalHigh = true
  2356. bool ashICTFractalLow = true
  2357.  
  2358. for ashFractalIndex = 1 to ashICTFractalPeriods
  2359. ashICTFractalHigh :=
  2360. ashICTFractalHigh and
  2361. ashICTFractalSourceHigh[ashICTFractalPeriods] > ashICTFractalSourceHigh[ashICTFractalPeriods + ashFractalIndex] and
  2362. ashICTFractalSourceHigh[ashICTFractalPeriods] >= ashICTFractalSourceHigh[ashICTFractalPeriods - ashFractalIndex]
  2363.  
  2364. ashICTFractalLow :=
  2365. ashICTFractalLow and
  2366. ashICTFractalSourceLow[ashICTFractalPeriods] < ashICTFractalSourceLow[ashICTFractalPeriods + ashFractalIndex] and
  2367. ashICTFractalSourceLow[ashICTFractalPeriods] <= ashICTFractalSourceLow[ashICTFractalPeriods - ashFractalIndex]
  2368.  
  2369. // Label objects preserve the original tiny triangle appearance without
  2370. // consuming plot slots. This keeps the full engine below TradingView's
  2371. // 64-plot runtime limit.
  2372. int ashICTFractalCentreBar = bar_index - ashICTFractalPeriods
  2373. int ashICTFractalCentreTime = time[ashICTFractalPeriods]
  2374. bool ashICTFractalHistoryPass = f_visualHistoryPass(
  2375. ashICTFractalHistoryMode,
  2376. ashICTFractalRecentBars,
  2377. ashICTFractalCentreBar,
  2378. ashICTFractalCentreTime
  2379. )
  2380.  
  2381. if showAshICTFractal and showAshICTFractalHigh and ashICTFractalHigh and ashICTFractalHistoryPass
  2382. label.new(
  2383. x = ashICTFractalCentreBar,
  2384. y = ashICTFractalSourceHigh[ashICTFractalPeriods],
  2385. text = "",
  2386. xloc = xloc.bar_index,
  2387. yloc = yloc.abovebar,
  2388. color = ashICTFractalHighColor,
  2389. style = label.style_triangleup,
  2390. textcolor = ashICTFractalHighColor,
  2391. size = size.tiny
  2392. )
  2393.  
  2394. if showAshICTFractal and showAshICTFractalLow and ashICTFractalLow and ashICTFractalHistoryPass
  2395. label.new(
  2396. x = ashICTFractalCentreBar,
  2397. y = ashICTFractalSourceLow[ashICTFractalPeriods],
  2398. text = "",
  2399. xloc = xloc.bar_index,
  2400. yloc = yloc.belowbar,
  2401. color = ashICTFractalLowColor,
  2402. style = label.style_triangledown,
  2403. textcolor = ashICTFractalLowColor,
  2404. size = size.tiny
  2405. )
  2406.  
  2407. //----------------------------------------------------------------------
  2408. // HTF qualification mirrored inside the selected source timeframe.
  2409. //----------------------------------------------------------------------
  2410. f_htfQualifiedCRT() =>
  2411. float pRangeHigh = high[1]
  2412. float pRangeLow = low[1]
  2413. float pRangeOpen = open[1]
  2414. float pRangeClose = close[1]
  2415. float pRangeSize = math.max(pRangeHigh - pRangeLow, syminfo.mintick)
  2416. float pRangeMid = (pRangeHigh + pRangeLow) * 0.5
  2417. float pRangeBodyPct = math.abs(pRangeClose - pRangeOpen) / pRangeSize * 100.0
  2418. float pAtr = ta.atr(14)
  2419.  
  2420. bool pSweptHigh = high > pRangeHigh
  2421. bool pSweptLow = low < pRangeLow
  2422. bool pSingleSweep = pSweptHigh != pSweptLow
  2423. bool pClosedInside = close < pRangeHigh and close > pRangeLow
  2424. bool pBullDirection = not requireDirectionalClose or close > open
  2425. bool pBearDirection = not requireDirectionalClose or close < open
  2426.  
  2427. bool pBase =
  2428. barstate.isconfirmed and
  2429. pSingleSweep and
  2430. (not rejectDoubleSweep or not (pSweptHigh and pSweptLow)) and
  2431. (not requireCloseInside or pClosedInside)
  2432.  
  2433. bool pBull = pBase and pSweptLow and not pSweptHigh and pBullDirection
  2434. bool pBear = pBase and pSweptHigh and not pSweptLow and pBearDirection
  2435.  
  2436. float pManipRange = math.max(high - low, syminfo.mintick)
  2437. float pLowerReject = (math.min(open, close) - low) / pManipRange * 100.0
  2438. float pUpperReject = (high - math.max(open, close)) / pManipRange * 100.0
  2439.  
  2440. bool pTime = isAllowedRangeHour(time[1])
  2441. bool pReject = (pBull and pLowerReject >= minimumRejectionPercent) or (pBear and pUpperReject >= minimumRejectionPercent)
  2442. bool pMid = (pBull and close > pRangeMid) or (pBear and close < pRangeMid)
  2443. float pAtrRatio = pAtr[1] > 0.0 ? pRangeSize / pAtr[1] : 0.0
  2444. bool pSize = pAtrRatio >= minimumRangeATR and pAtrRatio <= maximumRangeATR
  2445. bool pBody = pRangeBodyPct >= minimumRangeBodyPercent and pRangeBodyPct <= maximumRangeBodyPercent
  2446. float pPoiTolerance = pAtr[1] * poiToleranceATR
  2447. [pBullPOITypes, pBearPOITypes, pBullPOIScore, pBearPOIScore] = f_detectDirectionalPOIs(pRangeHigh, pRangeLow, pPoiTolerance)
  2448. bool pBullPOIAligned = pBullPOITypes >= minimumPOITypes and pBullPOIScore >= minimumDirectionalPOIScore and (not rejectOpposingPOIDominance or pBullPOIScore >= pBearPOIScore)
  2449. bool pBearPOIAligned = pBearPOITypes >= minimumPOITypes and pBearPOIScore >= minimumDirectionalPOIScore and (not rejectOpposingPOIDominance or pBearPOIScore >= pBullPOIScore)
  2450. bool pPOI = (pBull and pBullPOIAligned) or (pBear and pBearPOIAligned)
  2451.  
  2452. // Key-level requests are deliberately excluded here to avoid nested MTF requests.
  2453. int pEnabled =
  2454. (useTimeProtocol ? 1 : 0) +
  2455. (useRejectionProtocol ? 1 : 0) +
  2456. (useMidpointProtocol ? 1 : 0) +
  2457. (useRangeSizeProtocol ? 1 : 0) +
  2458. (useBodyProtocol ? 1 : 0) +
  2459. (usePOIProtocol ? 1 : 0)
  2460.  
  2461. int pScore =
  2462. (useTimeProtocol and pTime ? 1 : 0) +
  2463. (useRejectionProtocol and pReject ? 1 : 0) +
  2464. (useMidpointProtocol and pMid ? 1 : 0) +
  2465. (useRangeSizeProtocol and pSize ? 1 : 0) +
  2466. (useBodyProtocol and pBody ? 1 : 0) +
  2467. (usePOIProtocol and pPOI ? 1 : 0)
  2468.  
  2469. int pMinimum = math.min(minimumProtocols, math.max(pEnabled, 1))
  2470. (pBull or pBear) and pScore >= pMinimum
  2471.  
  2472. f_htfDirection() =>
  2473. float pRangeHigh = high[1]
  2474. float pRangeLow = low[1]
  2475. bool pSweptHigh = high > pRangeHigh
  2476. bool pSweptLow = low < pRangeLow
  2477. bool pSingleSweep = pSweptHigh != pSweptLow
  2478. bool pClosedInside = close < pRangeHigh and close > pRangeLow
  2479. bool pBase = barstate.isconfirmed and pSingleSweep and (not requireCloseInside or pClosedInside)
  2480. pBase and pSweptLow and not pSweptHigh ? 1 : pBase and pSweptHigh and not pSweptLow ? -1 : 0
  2481.  
  2482. // v20.9.3.1 — Bundle the complete HTF projection channel into one request.
  2483. [projectedQualified, projectedDirection, projectedRangeStart, projectedManipulationStart, projectedDistributionStart, projectedDistributionEnd] = request.security(
  2484. syminfo.tickerid,
  2485. selectedHTF,
  2486. [f_htfQualifiedCRT(), f_htfDirection(), time[1], time, time_close, time_close + (time_close - time)],
  2487. gaps = barmerge.gaps_off,
  2488. lookahead = barmerge.lookahead_off
  2489. )
  2490.  
  2491. bool newProjectedSetup =
  2492. enableHTFProjection and
  2493. isLowerThanProjection and
  2494. projectedQualified and
  2495. (na(projectedManipulationStart[1]) or projectedManipulationStart != projectedManipulationStart[1])
  2496.  
  2497. // No projection objects are drawn.
  2498. // `newProjectedSetup` is retained only to update the internal HTF direction
  2499. // and Distribution-window timing used by the optional LTF structure engine.
  2500.  
  2501. //======================================================================
  2502. // 11. DIRECTIONAL LTF STRUCTURE UNLOCK
  2503. // After the qualified HTF Manipulation closes, the scanner activates only
  2504. // inside the HTF Distribution window. It does not issue buy/sell signals.
  2505. // It simply colors the aligned LTF CRT Range candle blue and its confirmed
  2506. // Manipulation candle yellow, leaving execution and Fib placement to trader.
  2507. //======================================================================
  2508. var int activeHTFDirection = 0
  2509. var int activeDistributionStart = na
  2510. var int activeDistributionEnd = na
  2511. var int ltfStructuresThisSetup = 0
  2512.  
  2513. if newProjectedSetup
  2514. activeHTFDirection := projectedDirection
  2515. activeDistributionStart := projectedDistributionStart
  2516. activeDistributionEnd := projectedDistributionEnd
  2517. ltfStructuresThisSetup := 0
  2518.  
  2519. float chartMinutes = not na(chartSeconds) ? chartSeconds / 60.0 : na
  2520.  
  2521. // v20.5 — Explicit native-timeframe boundary guard.
  2522. // TradingView reports 15m as both 900 seconds and a native minute interval.
  2523. // Accept either representation so the exact 15m boundary cannot fall
  2524. // between the HTF-analysis and LTF-execution dashboard branches.
  2525. bool executionChartByNativeTF =
  2526. timeframe.isminutes and
  2527. timeframe.multiplier <= maximumExecutionMinutes
  2528.  
  2529. bool executionChartBySeconds =
  2530. not na(chartMinutes) and
  2531. chartMinutes <= maximumExecutionMinutes
  2532.  
  2533. bool executionTimeframeAllowed =
  2534. isLowerThanProjection and
  2535. (executionChartByNativeTF or executionChartBySeconds)
  2536.  
  2537.  
  2538. bool primaryExecutionTimeframeMatch =
  2539. primaryExecutionTimeframe == "All LTFs (Advanced)" ? executionTimeframeAllowed :
  2540. primaryExecutionTimeframe == "15m" ? (timeframe.isminutes and timeframe.multiplier == 15) :
  2541. primaryExecutionTimeframe == "5m" ? (timeframe.isminutes and timeframe.multiplier == 5) :
  2542. primaryExecutionTimeframe == "3m" ? (timeframe.isminutes and timeframe.multiplier == 3) :
  2543. primaryExecutionTimeframe == "2m" ? (timeframe.isminutes and timeframe.multiplier == 2) :
  2544. primaryExecutionTimeframe == "1m" ? (timeframe.isminutes and timeframe.multiplier == 1) :
  2545. false
  2546.  
  2547. string primaryExecutionTimeframeText =
  2548. primaryExecutionTimeframe == "All LTFs (Advanced)" ? "ALL LTFs" : str.upper(primaryExecutionTimeframe)
  2549.  
  2550. bool insideDistributionWindow =
  2551. not na(activeDistributionStart) and
  2552. not na(activeDistributionEnd) and
  2553. time >= activeDistributionStart and
  2554. time < activeDistributionEnd
  2555.  
  2556. float localRangeHigh = high[1]
  2557. float localRangeLow = low[1]
  2558. float localRangeMid = (localRangeHigh + localRangeLow) * 0.5
  2559. float localManipulationRange = math.max(high - low, syminfo.mintick)
  2560.  
  2561. bool localSweptLow = low < localRangeLow and high <= localRangeHigh
  2562. bool localSweptHigh = high > localRangeHigh and low >= localRangeLow
  2563. bool localClosedInside = close > localRangeLow and close < localRangeHigh
  2564. float localLowerReject = (math.min(open, close) - low) / localManipulationRange * 100.0
  2565. float localUpperReject = (high - math.max(open, close)) / localManipulationRange * 100.0
  2566.  
  2567. bool localBullishCRT =
  2568. barstate.isconfirmed and
  2569. localSweptLow and
  2570. (not localRequireCloseInside or localClosedInside) and
  2571. (not localRequireMidpoint or close > localRangeMid) and
  2572. localLowerReject >= localMinimumRejection
  2573.  
  2574. bool localBearishCRT =
  2575. barstate.isconfirmed and
  2576. localSweptHigh and
  2577. (not localRequireCloseInside or localClosedInside) and
  2578. (not localRequireMidpoint or close < localRangeMid) and
  2579. localUpperReject >= localMinimumRejection
  2580.  
  2581. bool structureEngineUnlocked =
  2582. enableExecutionEngine and
  2583. executionTimeframeAllowed and
  2584. insideDistributionWindow and
  2585. activeHTFDirection != 0
  2586.  
  2587. bool structureQuotaAvailable = not firstExecutionOnly or ltfStructuresThisSetup == 0
  2588. bool bullishLTFStructure = structureEngineUnlocked and structureQuotaAvailable and activeHTFDirection == 1 and localBullishCRT
  2589. bool bearishLTFStructure = structureEngineUnlocked and structureQuotaAvailable and activeHTFDirection == -1 and localBearishCRT
  2590. bool qualifiedLTFStructure = bullishLTFStructure or bearishLTFStructure
  2591.  
  2592. if qualifiedLTFStructure
  2593. ltfStructuresThisSetup += 1
  2594.  
  2595. // The Range candle is confirmed only when its following Manipulation candle
  2596. // closes, so it is colored retrospectively with offset -1.
  2597. barcolor(
  2598. colorUnlockedLTFStructure and qualifiedLTFStructure and crtVisualHistoryPass ? ltfRangeColor : na,
  2599. offset = -1,
  2600. title = "Unlocked LTF CRT Range Candle"
  2601. )
  2602.  
  2603. barcolor(
  2604. colorUnlockedLTFStructure and qualifiedLTFStructure and crtVisualHistoryPass ? ltfManipulationColor : na,
  2605. title = "Unlocked LTF CRT Manipulation Candle"
  2606. )
  2607.  
  2608. // Scores remain available in TradingView's Data Window only.
  2609. plot(protocolScore, "CRT Protocol Score", display = display.data_window)
  2610. plot(effectiveMinimum, "CRT Minimum Required", display = display.data_window)
  2611. plot(directionalPOIScore, "Directional POI Score", display = display.data_window)
  2612. plot(timeProtocol ? 1 : 0, "Market Time Protocol Passed", display = display.data_window)
  2613.  
  2614. string activeMarketProfile = f_selectedMarketProfile()
  2615. int activeMarketProfileCode =
  2616. activeMarketProfile == "Forex" ? 1 :
  2617. activeMarketProfile == "Indices" ? 2 :
  2618. activeMarketProfile == "Futures" ? 3 :
  2619. activeMarketProfile == "Crypto" ? 4 :
  2620. activeMarketProfile == "Commodities" ? 5 : 6
  2621. plot(parentCRTDirection, "Parent HTF CRT Direction", display = display.data_window)
  2622. plot(hierarchyAligned ? 1 : hierarchyOpposing ? -1 : 0, "Hierarchy Alignment State", display = display.data_window)
  2623. plot(activeCRTDirection, "Active CRT Direction", display = display.data_window)
  2624. plot(crtLifecycleStatus, "CRT Lifecycle Status", display = display.data_window)
  2625. plot(barsSinceQualifiedCRT, "Bars Since Qualified CRT", display = display.data_window)
  2626. plot(bullishSMTCount, "Bullish SMT Confirmation Count", display = display.data_window)
  2627. plot(bearishSMTCount, "Bearish SMT Confirmation Count", display = display.data_window)
  2628. plot(smtAligned ? 1 : smtOpposing ? -1 : 0, "SMT Matrix Alignment State", display = display.data_window)
  2629. plot(liquidityPurgeScore, "Liquidity Purge Score", display = display.data_window)
  2630. plot(meaningfulLiquidityPurge ? 1 : 0, "Meaningful Liquidity Purge", display = display.data_window)
  2631. plot(parentContextDirection, "Active Parent CRT Context Direction", display = display.data_window)
  2632. plot(nestedContextScore, "Nested HTF CRT Context Score", display = display.data_window)
  2633. plot(meaningfulNestedContext ? 1 : 0, "Meaningful Nested HTF Context", display = display.data_window)
  2634. plot(deliveryContextScore, "Displacement Delivery Score", display = display.data_window)
  2635. plot(meaningfulDeliveryContext ? 1 : 0, "Meaningful Displacement Delivery", display = display.data_window)
  2636. plot(deliveryCRTDirection, "Delivery CRT Direction", display = display.data_window)
  2637. plot(failedCRTEvent ? 1 : 0, "Failed CRT Event", display = display.data_window)
  2638. plot(failedCRTReversalContextActive ? 1 : 0, "Failed CRT Reversal Context Active", display = display.data_window)
  2639. plot(barsSinceFailedCRT, "Bars Since Failed CRT", display = display.data_window)
  2640. plot(activeDrawTarget, "Active CRT Draw Target", display = display.data_window)
  2641. plot(activeDrawTargetType, "Active CRT Draw Target Type", display = display.data_window)
  2642. plot(activeDrawTargetAvailable ? 1 : 0, "CRT Draw Target Available", display = display.data_window)
  2643. plot(activeDrawTargetReached ? 1 : 0, "CRT Draw Target Reached", display = display.data_window)
  2644. plot(boundedCRTIntelligenceScore, "CRT Intelligence Score", display = display.data_window)
  2645. plot(currentCRTGradeCode, "CRT Grade Code (4=A+, 3=A, 2=B, 1=C)", display = display.data_window)
  2646. plot(majorContextCount, "Major Grade Context Count", display = display.data_window)
  2647.  
  2648.  
  2649. //======================================================================
  2650. // 14A. CRT INTELLIGENCE DASHBOARD — PREVIEW
  2651. // Latest qualified CRT context only. No chart lines or labels are drawn.
  2652. // Dedicated source-timeframe engine reports exact FVG, IFVG,
  2653. // Order Block, Breaker, or Rejection Block context for the latest CRT.
  2654. //======================================================================
  2655. f_dashboardPosition(string p) =>
  2656. p == "Top Left" ? position.top_left :
  2657. p == "Bottom Right" ? position.bottom_right :
  2658. p == "Bottom Left" ? position.bottom_left :
  2659. position.top_right
  2660.  
  2661. f_dashboardTextSize(string s) =>
  2662. s == "Tiny" ? size.tiny :
  2663. s == "Normal" ? size.normal :
  2664. size.small
  2665.  
  2666. f_gradeText(int gradeCode) =>
  2667. gradeCode == 4 ? "A+" :
  2668. gradeCode == 3 ? "A" :
  2669. gradeCode == 2 ? "B" :
  2670. gradeCode == 1 ? "C" : "—"
  2671.  
  2672. f_keyLevelTypeText(int keyType, int direction) =>
  2673. string directionText =
  2674. direction == 1 ? "BULLISH " :
  2675. direction == -1 ? "BEARISH " : ""
  2676. string typeText =
  2677. keyType == 1 ? "FVG" :
  2678. keyType == 2 ? "IFVG" :
  2679. keyType == 3 ? "ORDER BLOCK" :
  2680. keyType == 4 ? "BREAKER" :
  2681. keyType == 5 ? "REJECTION BLOCK" :
  2682. "NONE"
  2683. keyType == 0 ? "NONE" : directionText + typeText
  2684.  
  2685. f_targetTypeText(int targetType, int direction) =>
  2686. targetType == 1 ? (direction == 1 ? "CRT HIGH" : direction == -1 ? "CRT LOW" : "CRT") :
  2687. targetType == 2 ? (direction == 1 ? "PDH" : direction == -1 ? "PDL" : "PD") :
  2688. targetType == 3 ? (direction == 1 ? "PWH" : direction == -1 ? "PWL" : "PW") :
  2689. targetType == 4 ? (direction == 1 ? "PMH" : direction == -1 ? "PML" : "PM") :
  2690. targetType == 5 ? (direction == 1 ? "SWING HIGH" : direction == -1 ? "SWING LOW" : "SWING") :
  2691. "NONE"
  2692.  
  2693. // v19.0 includes State Colour Intelligence and Multi-Timeframe Execution Guidance.
  2694. // ACTIVE keeps directional colour, DELIVERED is always success-green,
  2695. // FAILED / INVALID are red, and inactive lifecycle states are neutral grey.
  2696. f_stateColor(string state) =>
  2697. state == "BULLISH" or state == "BULLISH ACTIVE" or state == "ALIGNED" or state == "CONFIRMED" or state == "ACTIVE" or state == "REACHED" or state == "STRONG" or state == "BULL REVERSAL" or state == "BULLISH DELIVERED" or state == "BEARISH DELIVERED" or state == "DELIVERED" ? color.new(color.green, 72) :
  2698. state == "BEARISH" or state == "BEARISH ACTIVE" or state == "BULLISH FAILED" or state == "BEARISH FAILED" or state == "BULLISH INVALID" or state == "BEARISH INVALID" or state == "CONFLICT" or state == "FAILED" or state == "INVALID" or state == "BEAR REVERSAL" ? color.new(color.red, 72) :
  2699. state == "NEUTRAL" or state == "MODERATE" ? color.new(color.orange, 72) :
  2700. state == "LTF CRT ALIGNED" ? color.new(color.green, 72) :
  2701. state == "LTF CRT OPPOSED" ? color.new(color.red, 72) :
  2702. state == "EXPIRED" or state == "WAITING" ? color.new(color.gray, 72) :
  2703. color.new(color.gray, 82)
  2704.  
  2705. //======================================================================
  2706. // 14A. TRADE READINESS & ACTION ENGINE — v18.7
  2707. // Converts the existing CRT intelligence into a clear action state.
  2708. // A failed CRT creates reversal context only; it never creates an
  2709. // automatic entry. Reversal entries still require an opposite-direction
  2710. // lower-timeframe CRT confirmation.
  2711. //======================================================================
  2712. // v19.2 Unified lifecycle arbitration.
  2713. // The first terminal event wins for the current CRT. If target delivery
  2714. // occurs before (or on the same bar as) failure, the setup remains DELIVERED.
  2715. // A later failure/invalidation cannot rewrite a completed objective.
  2716. bool crtBoundaryTargetEvent = crtTargetReached and not crtTargetReached[1]
  2717. bool unifiedTargetEvent = crtBoundaryTargetEvent or newDrawTargetReached
  2718. int barsSinceUnifiedTarget = ta.barssince(unifiedTargetEvent)
  2719.  
  2720. bool unifiedTargetBelongsToCurrentCRT =
  2721. hasTrackedCRT and
  2722. not na(barsSinceUnifiedTarget) and
  2723. barsSinceUnifiedTarget <= barsSinceQualifiedCRT
  2724.  
  2725. bool unifiedFailureBelongsToCurrentCRT =
  2726. hasTrackedCRT and
  2727. not na(barsSinceFailedCRT) and
  2728. barsSinceFailedCRT <= barsSinceQualifiedCRT
  2729.  
  2730. // Larger bars-since means the event happened earlier. Equality gives
  2731. // target delivery priority when both events occur on the same candle.
  2732. bool targetWonLifecycle =
  2733. unifiedTargetBelongsToCurrentCRT and
  2734. (not unifiedFailureBelongsToCurrentCRT or barsSinceUnifiedTarget >= barsSinceFailedCRT)
  2735.  
  2736. bool failureWonLifecycle =
  2737. unifiedFailureBelongsToCurrentCRT and
  2738. not targetWonLifecycle
  2739.  
  2740. bool tradeTargetReached = targetWonLifecycle
  2741. bool tradeReversalActive = failedCRTReversalContextActive and failureWonLifecycle
  2742.  
  2743. bool tradeInvalid =
  2744. hasTrackedCRT and
  2745. crtInvalidated and
  2746. not tradeTargetReached and
  2747. not failureWonLifecycle
  2748.  
  2749. bool tradeExpired =
  2750. hasTrackedCRT and
  2751. crtExpired and
  2752. not tradeReversalActive and
  2753. not tradeTargetReached and
  2754. not tradeInvalid
  2755.  
  2756. bool tradeProtocolAligned =
  2757. not hierarchyOpposing and
  2758. not smtOpposing and
  2759. latestCRTIntelligenceScore >= gradeBThreshold
  2760.  
  2761. bool tradeReady =
  2762. not tradeReversalActive and
  2763. crtLifecycleActive and
  2764. meaningfulDeliveryContext and
  2765. tradeProtocolAligned
  2766.  
  2767. bool tradeWatch =
  2768. not tradeReversalActive and
  2769. crtLifecycleActive and
  2770. not tradeReady
  2771.  
  2772. string dashboardTradeStatus =
  2773. tradeReversalActive ? "REVERSAL ACTIVE" :
  2774. tradeTargetReached ? "TARGET REACHED" :
  2775. tradeInvalid ? "INVALID" :
  2776. tradeExpired ? "EXPIRED" :
  2777. tradeReady ? "READY" :
  2778. tradeWatch ? "WATCH" :
  2779. "WAIT"
  2780.  
  2781. int executionDirection =
  2782. tradeReversalActive ? latestFailedCRTReversalDirection :
  2783. crtLifecycleActive ? activeCRTDirection : 0
  2784.  
  2785. string dashboardExecutionBias =
  2786. executionDirection == 1 ? "SEEK LONG" :
  2787. executionDirection == -1 ? "SEEK SHORT" :
  2788. "NEUTRAL"
  2789.  
  2790. string dashboardEntryCondition =
  2791. tradeReversalActive ?
  2792. (executionDirection == 1 ? "WAIT BULLISH LTF CRT" : "WAIT BEARISH LTF CRT") :
  2793. tradeReady ?
  2794. (executionDirection == 1 ? "BULLISH CONFIRMATION" : "BEARISH CONFIRMATION") :
  2795. tradeWatch ?
  2796. (meaningfulDeliveryContext ? "WAIT PROTOCOL ALIGNMENT" : "WAIT FOR DELIVERY") :
  2797. tradeTargetReached ? "NO CHASE • TARGET DONE" :
  2798. tradeInvalid ? "NO TRADE" :
  2799. tradeExpired ? "WAIT NEW CRT" :
  2800. "WAIT QUALIFIED CRT"
  2801.  
  2802. string dashboardRiskState =
  2803. tradeReversalActive ? "ORIGINAL CRT FAILED" :
  2804. tradeTargetReached ? "OBJECTIVE DELIVERED" :
  2805. tradeInvalid ? "INVALIDATED" :
  2806. tradeExpired ? "SETUP EXPIRED" :
  2807. tradeReady ? "CONFIRMED • MANAGE RISK" :
  2808. tradeWatch ? "UNCONFIRMED" :
  2809. "NO ACTIVE RISK"
  2810.  
  2811. string dashboardSetupAge =
  2812. hasTrackedCRT and not na(barsSinceQualifiedCRT) ?
  2813. str.tostring(barsSinceQualifiedCRT) + " / " + str.tostring(lifecycleExpiryBars) + " BARS" :
  2814. "—"
  2815.  
  2816. f_tradeStatusColor(string state, int direction) =>
  2817. state == "READY" or state == "RE-ARMED" or state == "EXECUTION ARMED" or state == "ENTRY CONFIRMED" or state == "DELIVERING" ? (direction == -1 ? color.new(color.red, 60) : color.new(color.green, 60)) :
  2818. state == "REVERSAL ACTIVE" ? (direction == -1 ? color.new(color.red, 60) : direction == 1 ? color.new(color.green, 60) : color.new(color.orange, 65)) :
  2819. state == "INVALID" ? color.new(color.red, 58) :
  2820. state == "TARGET REACHED" ? color.new(color.green, 72) :
  2821. state == "WATCH" ? color.new(color.orange, 65) :
  2822. state == "EXPIRED" ? color.new(color.gray, 72) :
  2823. color.new(color.gray, 82)
  2824.  
  2825.  
  2826. // Compact visual code derived from the stable epoch-minute identity.
  2827. // Internal comparisons always use the full monotonic identity.
  2828. f_narrativeIDText(int identity) =>
  2829. identity > 0 ? str.tostring(identity % 1000000) : "0"
  2830.  
  2831. //======================================================================
  2832. // 14B. UNIFIED STORY ENGINE — v19.2
  2833. // On execution charts (15m and below by default), the active H1 story
  2834. // controls directional guidance. The LTF may confirm that direction or
  2835. // remain neutral, but an opposing local CRT cannot flip the HTF bias.
  2836. //======================================================================
  2837. f_executionParentTF() =>
  2838. timeframe.isminutes and timeframe.multiplier <= 15 ? "60" :
  2839. timeframe.isminutes and timeframe.multiplier <= 60 ? "240" :
  2840. not na(chartMinutes) and chartMinutes <= 15.0 ? "60" :
  2841. not na(chartMinutes) and chartMinutes <= 60.0 ? "240" :
  2842. selectedHTF
  2843.  
  2844. string baseInheritanceParentTF = f_executionParentTF()
  2845.  
  2846. // v20.9.3.2 Stable Narrative Identity.
  2847. // The source CRT candle's opening timestamp is the identity. Unlike ta.cum(),
  2848. // this value is independent of how much chart history each LTF instance loaded,
  2849. // so 3H → 1H → 30M → 15M → 5M → 1M all inherit the exact same parent ID.
  2850. int latestQualifiedNarrativeTime = nz(ta.valuewhen(qualifiedCRT, time, 0), 0)
  2851. int latestQualifiedNarrativeID = latestQualifiedNarrativeTime > 0 ? int(math.floor(latestQualifiedNarrativeTime / 60000)) : 0
  2852. int latestNarrativeDirection = nz(ta.valuewhen(qualifiedCRT, currentQualifiedCRTDirection, 0), 0)
  2853. bool latestNarrativeHierarchyPass = ta.valuewhen(qualifiedCRT, hierarchyProtocol and hierarchyHardPass, 0)
  2854.  
  2855. bool terminalNarrativeState = tradeTargetReached or tradeInvalid or tradeExpired
  2856. bool terminalNarrativeEvent = terminalNarrativeState and not terminalNarrativeState[1]
  2857. int latestTerminalNarrativeTime = nz(ta.valuewhen(terminalNarrativeEvent, time, 0), 0)
  2858. int latestTerminalNarrativeID = nz(ta.valuewhen(terminalNarrativeEvent, latestQualifiedNarrativeID, 0), 0)
  2859.  
  2860. bool hasFreshNarrativeIdentity =
  2861. enableNarrativeFreshnessEngine and
  2862. latestTerminalNarrativeTime > 0 and
  2863. latestQualifiedNarrativeID > latestTerminalNarrativeID and
  2864. latestQualifiedNarrativeTime > latestTerminalNarrativeTime
  2865.  
  2866. int freshNarrativeAge =
  2867. hasFreshNarrativeIdentity and not na(barsSinceQualifiedCRT) ?
  2868. barsSinceQualifiedCRT : 100000
  2869.  
  2870. bool freshDirectionConfirmed =
  2871. hasFreshNarrativeIdentity and
  2872. latestNarrativeDirection != 0
  2873.  
  2874. bool freshHTFContextConfirmed =
  2875. hasFreshNarrativeIdentity and
  2876. (not requireFreshHierarchyAlignment or latestNarrativeHierarchyPass)
  2877.  
  2878. bool freshDeliveryConfirmed =
  2879. hasFreshNarrativeIdentity and
  2880. (not requireFreshDeliveryConfirmation or meaningfulDeliveryContext)
  2881.  
  2882. bool freshObjectiveOpen =
  2883. hasFreshNarrativeIdentity and
  2884. crtLifecycleActive and
  2885. not tradeTargetReached and
  2886. not tradeInvalid and
  2887. not tradeExpired
  2888.  
  2889. bool freshValidationTimedOut =
  2890. hasFreshNarrativeIdentity and
  2891. freshNarrativeAge > freshValidationWindowBars and
  2892. not freshDeliveryConfirmed
  2893.  
  2894. // v20.1 Narrative Validation Failure Memory.
  2895. // Once a fresh narrative ID fails validation, that exact ID is permanently
  2896. // rejected. Later changes in delivery or context cannot revive it. Only a
  2897. // strictly newer qualified narrative ID may enter validation.
  2898. var int latestRejectedNarrativeID = 0
  2899.  
  2900. bool freshValidationFailureNow =
  2901. enableFreshNarrativeValidation and
  2902. hasFreshNarrativeIdentity and
  2903. latestQualifiedNarrativeID > latestRejectedNarrativeID and (
  2904. not freshDirectionConfirmed or
  2905. not freshHTFContextConfirmed or
  2906. not freshObjectiveOpen or
  2907. freshValidationTimedOut
  2908. )
  2909.  
  2910. if freshValidationFailureNow
  2911. latestRejectedNarrativeID := latestQualifiedNarrativeID
  2912.  
  2913. bool freshNarrativePermanentlyRejected =
  2914. hasFreshNarrativeIdentity and
  2915. latestQualifiedNarrativeID <= latestRejectedNarrativeID
  2916.  
  2917. bool freshValidationRejected =
  2918. enableFreshNarrativeValidation and
  2919. freshNarrativePermanentlyRejected
  2920.  
  2921. bool freshValidationConfirmed =
  2922. hasFreshNarrativeIdentity and
  2923. not freshNarrativePermanentlyRejected and
  2924. (
  2925. not enableFreshNarrativeValidation or
  2926. (
  2927. freshDirectionConfirmed and
  2928. freshHTFContextConfirmed and
  2929. freshDeliveryConfirmed and
  2930. freshObjectiveOpen and
  2931. not freshValidationTimedOut
  2932. )
  2933. )
  2934.  
  2935. // State codes: 0 = none, 1 = validating, 2 = confirmed, 3 = permanently rejected.
  2936. int freshValidationState =
  2937. not hasFreshNarrativeIdentity ? 0 :
  2938. freshValidationRejected ? 3 :
  2939. freshValidationConfirmed ? 2 : 1
  2940.  
  2941. int freshValidationScore =
  2942. (freshDirectionConfirmed ? 1 : 0) +
  2943. (freshHTFContextConfirmed ? 1 : 0) +
  2944. (freshDeliveryConfirmed ? 1 : 0) +
  2945. (freshObjectiveOpen ? 1 : 0)
  2946.  
  2947. //======================================================================
  2948. // 20.3 NARRATIVE DELIVERY & OBJECTIVE TRACKER
  2949. // State codes:
  2950. // 0=Waiting, 1=Candidate validating, 2=Confirmed,
  2951. // 3=Delivery active, 4=Objective near, 5=Objective completed,
  2952. // 6=Invalidated, 7=Expired, 8=Permanently rejected.
  2953. //======================================================================
  2954. float narrativeTrackerATR = ta.atr(14)
  2955.  
  2956. float narrativeObjectiveDistance =
  2957. activeDrawTargetAvailable ? math.abs(activeDrawTarget - close) : na
  2958.  
  2959. bool narrativeObjectiveNear =
  2960. enableNarrativeObjectiveTracker and
  2961. activeDrawTargetAvailable and
  2962. not activeDrawTargetReached and
  2963. narrativeTrackerATR > 0 and
  2964. narrativeObjectiveDistance <= narrativeTrackerATR * objectiveNearThresholdATR
  2965.  
  2966. bool narrativeDeliveryStarted =
  2967. enableNarrativeObjectiveTracker and
  2968. freshValidationConfirmed and
  2969. crtLifecycleActive and
  2970. meaningfulDeliveryContext
  2971.  
  2972. int narrativeTrackerState =
  2973. not enableNarrativeObjectiveTracker ? 0 :
  2974. freshValidationRejected ? 8 :
  2975. tradeTargetReached ? 5 :
  2976. tradeInvalid ? 6 :
  2977. tradeExpired ? 7 :
  2978. hasFreshNarrativeIdentity and freshValidationState == 1 ? 1 :
  2979. freshValidationConfirmed and narrativeObjectiveNear ? 4 :
  2980. narrativeDeliveryStarted ? 3 :
  2981. freshValidationConfirmed ? 2 :
  2982. 0
  2983.  
  2984. string narrativeTrackerStateText =
  2985. narrativeTrackerState == 1 ? "CANDIDATE VALIDATING" :
  2986. narrativeTrackerState == 2 ? "CONFIRMED • WAIT DELIVERY" :
  2987. narrativeTrackerState == 3 ? "DELIVERY ACTIVE" :
  2988. narrativeTrackerState == 4 ? "OBJECTIVE NEAR" :
  2989. narrativeTrackerState == 5 ? "OBJECTIVE COMPLETED" :
  2990. narrativeTrackerState == 6 ? "NARRATIVE INVALIDATED" :
  2991. narrativeTrackerState == 7 ? "NARRATIVE EXPIRED" :
  2992. narrativeTrackerState == 8 ? "PERMANENTLY REJECTED" :
  2993. "WAIT NEW NARRATIVE"
  2994.  
  2995. string narrativeObjectiveTypeText =
  2996. activeDrawTargetType == 1 ? (latestCRTDirection == 1 ? "CRT HIGH" : latestCRTDirection == -1 ? "CRT LOW" : "CRT") :
  2997. activeDrawTargetType == 2 ? (latestCRTDirection == 1 ? "PDH" : latestCRTDirection == -1 ? "PDL" : "PD") :
  2998. activeDrawTargetType == 3 ? (latestCRTDirection == 1 ? "PWH" : latestCRTDirection == -1 ? "PWL" : "PW") :
  2999. activeDrawTargetType == 4 ? (latestCRTDirection == 1 ? "PMH" : latestCRTDirection == -1 ? "PML" : "PM") :
  3000. activeDrawTargetType == 5 ? (latestCRTDirection == 1 ? "SWING HIGH" : latestCRTDirection == -1 ? "SWING LOW" : "SWING") :
  3001. "NONE"
  3002.  
  3003. string narrativeObjectiveText =
  3004. not enableNarrativeObjectiveTracker ? "DISABLED" :
  3005. narrativeTrackerState == 8 ? "WAIT NEWER NARRATIVE ID" :
  3006. narrativeTrackerState == 5 ? "DELIVERED • NO CHASE" :
  3007. narrativeTrackerState == 6 or narrativeTrackerState == 7 ? "CLOSED • WAIT NEW CRT" :
  3008. not activeDrawTargetAvailable ? "NO OPEN OBJECTIVE" :
  3009. narrativeObjectiveTypeText + " • " + str.tostring(activeDrawTarget, format.mintick)
  3010.  
  3011. color narrativeTrackerColor =
  3012. narrativeTrackerState == 3 or narrativeTrackerState == 4 or narrativeTrackerState == 5 ? color.new(color.green, 58) :
  3013. narrativeTrackerState == 1 or narrativeTrackerState == 2 ? color.new(color.orange, 62) :
  3014. narrativeTrackerState == 6 or narrativeTrackerState == 8 ? color.new(color.red, 58) :
  3015. color.new(color.gray, 78)
  3016.  
  3017. plot(narrativeTrackerState, "Narrative Delivery Tracker State", display = display.data_window)
  3018.  
  3019. bool localNarrativeFresh =
  3020. hasFreshNarrativeIdentity and
  3021. crtLifecycleActive and
  3022. freshNarrativeAge <= freshNarrativeDisplayBars
  3023.  
  3024. bool localNarrativeRearmed =
  3025. enableNarrativeRearmEngine and
  3026. crtLifecycleActive and
  3027. freshValidationConfirmed and
  3028. freshNarrativeAge <= rearmDisplayParentBars
  3029.  
  3030. //======================================================================
  3031. // v20.9.3.2 DYNAMIC 4H / 3H / 2H / 1H PARENT HIERARCHY
  3032. // A lightweight rank is requested from each possible parent. Only the chosen
  3033. // parent then uses the full narrative channel below, preserving request and
  3034. // tuple budgets. The probe is deliberately structural and request-free:
  3035. // Rank 0 = no open structural CRT, Rank 1 = an open parent CRT exists.
  3036. // The exact candidate/confirmed state is read only from the selected parent.
  3037. //======================================================================
  3038. f_dynamicParentRank() =>
  3039. // IMPORTANT: Keep this probe completely self-contained.
  3040. // Referencing the full narrative globals here causes every probe timeframe to
  3041. // reproduce the script's nested request tree and breach TradingView's 40-call limit.
  3042. int probeDirection = f_activeStructuralCRTDirection()
  3043. probeDirection != 0 ? 1 : 0
  3044.  
  3045. int dynamicParentRank240 = request.security(syminfo.tickerid, "240", f_dynamicParentRank(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
  3046. int dynamicParentRank180 = request.security(syminfo.tickerid, "180", f_dynamicParentRank(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
  3047. int dynamicParentRank120 = request.security(syminfo.tickerid, "120", f_dynamicParentRank(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
  3048. int dynamicParentRank60 = request.security(syminfo.tickerid, "60", f_dynamicParentRank(), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_off)
  3049.  
  3050. bool dynamicHierarchyChartEligible =
  3051. enableDynamicParentHierarchy and
  3052. not na(currentChartSeconds) and
  3053. currentChartSeconds <= 3600
  3054.  
  3055. bool dynamicParent240Available = dynamicHierarchyChartEligible and currentChartSeconds < 14400 and dynamicParentRank240 > 0
  3056. bool dynamicParent180Available = dynamicHierarchyChartEligible and currentChartSeconds < 10800 and dynamicParentRank180 > 0
  3057. bool dynamicParent120Available = dynamicHierarchyChartEligible and currentChartSeconds < 7200 and dynamicParentRank120 > 0
  3058. bool dynamicParent60Available = dynamicHierarchyChartEligible and currentChartSeconds < 3600 and dynamicParentRank60 > 0
  3059.  
  3060. string dynamicInheritanceParentTF =
  3061. dynamicParent240Available ? "240" :
  3062. dynamicParent180Available ? "180" :
  3063. dynamicParent120Available ? "120" :
  3064. dynamicParent60Available ? "60" : ""
  3065.  
  3066. bool dynamicParentSelected = dynamicInheritanceParentTF != ""
  3067. string inheritanceParentTF = dynamicParentSelected ? dynamicInheritanceParentTF : baseInheritanceParentTF
  3068.  
  3069. [inheritedReversalActiveRaw, inheritedReversalDirectionRaw, inheritedLifecycleActiveRaw, inheritedActiveDirectionRaw, inheritedTargetReachedRaw, inheritedInvalidRaw, inheritedExpiredRaw, inheritedSetupAgeRaw, inheritedQualifiedNarrativeTimeRaw, inheritedTerminalNarrativeTimeRaw, inheritedNarrativeRearmedRaw, inheritedQualifiedNarrativeIDRaw, inheritedTerminalNarrativeIDRaw, inheritedNarrativeFreshRaw, inheritedFreshNarrativeAgeRaw, inheritedFreshValidationStateRaw, inheritedFreshValidationScoreRaw, inheritedFreshDirectionRaw, inheritedRejectedNarrativeIDRaw, inheritedNarrativeTrackerStateRaw, inheritedNarrativeObjectiveRaw, inheritedNarrativeObjectiveTypeRaw] =
  3070. request.security(
  3071. syminfo.tickerid,
  3072. inheritanceParentTF,
  3073. [tradeReversalActive, executionDirection, crtLifecycleActive and not tradeTargetReached and not tradeInvalid, activeCRTDirection, tradeTargetReached, tradeInvalid, tradeExpired, nz(barsSinceQualifiedCRT, 0), latestQualifiedNarrativeTime, latestTerminalNarrativeTime, localNarrativeRearmed, latestQualifiedNarrativeID, latestTerminalNarrativeID, localNarrativeFresh, freshNarrativeAge, freshValidationState, freshValidationScore, latestNarrativeDirection, latestRejectedNarrativeID, narrativeTrackerState, activeDrawTarget, activeDrawTargetType],
  3074. gaps = barmerge.gaps_off,
  3075. lookahead = barmerge.lookahead_off
  3076. )
  3077.  
  3078. // Every execution chart reads a dedicated parent channel. The parent channel
  3079. // is displayed even when it is terminal/neutral, while the local channel is
  3080. // kept separate for entry timing and local expiry.
  3081. // Narrative inheritance can extend up to the 1H chart when a dynamic 4H/3H/2H
  3082. // parent is active. Actual entry authorization remains limited to the configured
  3083. // execution timeframes (15M and below by default).
  3084. bool executionChildMode =
  3085. (executionTimeframeAllowed or dynamicParentSelected) and
  3086. inheritanceParentTF != timeframe.period
  3087.  
  3088. bool authorizationChildMode =
  3089. executionTimeframeAllowed and
  3090. primaryExecutionTimeframeMatch and
  3091. inheritanceParentTF != timeframe.period
  3092.  
  3093. bool confirmationOnlyChildMode =
  3094. executionChildMode and
  3095. executionTimeframeAllowed and
  3096. not primaryExecutionTimeframeMatch
  3097.  
  3098. bool inheritedFreshNarrative =
  3099. enableNarrativeRearmEngine and
  3100. enableNarrativeFreshnessEngine and
  3101. inheritedLifecycleActiveRaw and
  3102. inheritedQualifiedNarrativeIDRaw > inheritedTerminalNarrativeIDRaw and
  3103. inheritedQualifiedNarrativeTimeRaw > inheritedTerminalNarrativeTimeRaw
  3104.  
  3105. bool inheritedFreshValidationConfirmed = inheritedFreshValidationStateRaw == 2
  3106. bool inheritedFreshValidationRejected = inheritedFreshValidationStateRaw == 3
  3107. bool inheritedFreshValidationPending = inheritedFreshValidationStateRaw == 1
  3108.  
  3109. //======================================================================
  3110. // v20.4 NARRATIVE GENERATION HANDOFF ENGINE
  3111. // A terminal narrative remains available in memory for audit, but it is
  3112. // archived and loses ownership of all live guidance until a newer ID
  3113. // qualifies and validates.
  3114. //======================================================================
  3115. bool localNarrativeArchived =
  3116. enableNarrativeRearmEngine and
  3117. terminalNarrativeState and
  3118. not hasFreshNarrativeIdentity
  3119.  
  3120. bool inheritedNarrativeArchived =
  3121. enableNarrativeRearmEngine and
  3122. (inheritedTargetReachedRaw or inheritedInvalidRaw or inheritedExpiredRaw) and
  3123. not inheritedFreshNarrative
  3124.  
  3125. bool narrativeGenerationWaiting =
  3126. executionChildMode ? inheritedNarrativeArchived : localNarrativeArchived
  3127.  
  3128. // v20.5 — One display lock controls every student-facing dashboard row.
  3129. // Local diagnostics may continue running in the background, but no local
  3130. // event is presented as actionable while the owning narrative is archived.
  3131. bool parentStandDownDisplay = executionChildMode and inheritedNarrativeArchived
  3132. bool localStandDownDisplay = not executionChildMode and localNarrativeArchived
  3133. bool dashboardStandDownDisplay = parentStandDownDisplay or localStandDownDisplay
  3134.  
  3135. int archivedNarrativeID =
  3136. executionChildMode ? inheritedTerminalNarrativeIDRaw : latestTerminalNarrativeID
  3137.  
  3138. string archivedNarrativeReason =
  3139. executionChildMode ?
  3140. (inheritedTargetReachedRaw ? "OBJECTIVE COMPLETE" :
  3141. inheritedInvalidRaw ? "INVALIDATED" :
  3142. inheritedExpiredRaw ? "EXPIRED" :
  3143. "TERMINAL") :
  3144. (tradeTargetReached ? "OBJECTIVE COMPLETE" :
  3145. tradeInvalid ? "INVALIDATED" :
  3146. tradeExpired ? "EXPIRED" :
  3147. "TERMINAL")
  3148.  
  3149. string inheritedNarrativeTrackerText =
  3150. inheritedNarrativeTrackerStateRaw == 1 ? "CANDIDATE VALIDATING" :
  3151. inheritedNarrativeTrackerStateRaw == 2 ? "CONFIRMED • WAIT DELIVERY" :
  3152. inheritedNarrativeTrackerStateRaw == 3 ? "DELIVERY ACTIVE" :
  3153. inheritedNarrativeTrackerStateRaw == 4 ? "OBJECTIVE NEAR" :
  3154. inheritedNarrativeTrackerStateRaw == 5 ? "OBJECTIVE COMPLETED" :
  3155. inheritedNarrativeTrackerStateRaw == 6 ? "NARRATIVE INVALIDATED" :
  3156. inheritedNarrativeTrackerStateRaw == 7 ? "NARRATIVE EXPIRED" :
  3157. inheritedNarrativeTrackerStateRaw == 8 ? "PERMANENTLY REJECTED" :
  3158. "WAIT NEW NARRATIVE"
  3159.  
  3160. string inheritedObjectiveTypeText =
  3161. inheritedNarrativeObjectiveTypeRaw == 1 ? (inheritedActiveDirectionRaw == 1 ? "CRT HIGH" : inheritedActiveDirectionRaw == -1 ? "CRT LOW" : "CRT") :
  3162. inheritedNarrativeObjectiveTypeRaw == 2 ? (inheritedActiveDirectionRaw == 1 ? "PDH" : inheritedActiveDirectionRaw == -1 ? "PDL" : "PD") :
  3163. inheritedNarrativeObjectiveTypeRaw == 3 ? (inheritedActiveDirectionRaw == 1 ? "PWH" : inheritedActiveDirectionRaw == -1 ? "PWL" : "PW") :
  3164. inheritedNarrativeObjectiveTypeRaw == 4 ? (inheritedActiveDirectionRaw == 1 ? "PMH" : inheritedActiveDirectionRaw == -1 ? "PML" : "PM") :
  3165. inheritedNarrativeObjectiveTypeRaw == 5 ? (inheritedActiveDirectionRaw == 1 ? "SWING HIGH" : inheritedActiveDirectionRaw == -1 ? "SWING LOW" : "SWING") :
  3166. "NONE"
  3167.  
  3168. string inheritedNarrativeObjectiveText =
  3169. inheritedNarrativeTrackerStateRaw == 8 ? "WAIT NEWER PARENT ID" :
  3170. inheritedNarrativeTrackerStateRaw == 5 ? "DELIVERED • NO CHASE" :
  3171. inheritedNarrativeTrackerStateRaw == 6 or inheritedNarrativeTrackerStateRaw == 7 ? "CLOSED • WAIT NEW PARENT CRT" :
  3172. not na(inheritedNarrativeObjectiveRaw) and inheritedNarrativeObjectiveTypeRaw != 0 ?
  3173. inheritedObjectiveTypeText + " • " + str.tostring(inheritedNarrativeObjectiveRaw, format.mintick) :
  3174. "NO OPEN OBJECTIVE"
  3175.  
  3176. bool inheritedNarrativeStandDown =
  3177. enableNarrativeRearmEngine and (
  3178. (
  3179. (inheritedTargetReachedRaw or inheritedInvalidRaw or inheritedExpiredRaw) and
  3180. not inheritedFreshNarrative
  3181. ) or
  3182. (
  3183. inheritedFreshNarrative and
  3184. not inheritedFreshValidationConfirmed
  3185. )
  3186. )
  3187.  
  3188. // v19.8 keeps the v19.7 Parent Completion Stand-Down Lock and adds
  3189. // explicit reset/re-arm identity checking.
  3190. // IMPORTANT: The inherited story is derived directly from the parent timeframe
  3191. // on every bar. It is never stored in a chart-timeframe `var`, so a 1m/5m local
  3192. // expiry cannot erase it and a stale child chart cannot keep an old parent bias.
  3193. // Parent delivery/invalidation clears the inherited bias consistently on every LTF.
  3194. int inheritedParentStoryType =
  3195. inheritedNarrativeStandDown ? 0 :
  3196. inheritedReversalActiveRaw and inheritedReversalDirectionRaw != 0 ? 2 :
  3197. inheritedLifecycleActiveRaw and inheritedActiveDirectionRaw != 0 ? 1 : 0
  3198.  
  3199. int inheritedHTFDirection =
  3200. inheritedParentStoryType == 2 ? inheritedReversalDirectionRaw :
  3201. inheritedParentStoryType == 1 ? inheritedActiveDirectionRaw : 0
  3202.  
  3203. bool htfBiasInheritanceLock =
  3204. executionChildMode and
  3205. inheritedHTFDirection != 0
  3206.  
  3207. bool inheritedAlignedLocalCRT =
  3208. htfBiasInheritanceLock and (
  3209. (inheritedHTFDirection == 1 and localBullishCRT) or
  3210. (inheritedHTFDirection == -1 and localBearishCRT)
  3211. )
  3212.  
  3213. bool inheritedOpposingLocalCRT =
  3214. htfBiasInheritanceLock and (
  3215. (inheritedHTFDirection == 1 and localBearishCRT) or
  3216. (inheritedHTFDirection == -1 and localBullishCRT)
  3217. )
  3218.  
  3219. // Classify the complete local story (active CRT or failed-CRT reversal),
  3220. // not only the current two-candle candidate.
  3221. int localStoryDirection =
  3222. tradeReversalActive ? latestFailedCRTReversalDirection :
  3223. crtLifecycleActive ? activeCRTDirection : 0
  3224.  
  3225. bool localStoryAligned =
  3226. htfBiasInheritanceLock and
  3227. localStoryDirection != 0 and
  3228. localStoryDirection == inheritedHTFDirection
  3229.  
  3230. bool localStoryOpposed =
  3231. htfBiasInheritanceLock and
  3232. localStoryDirection != 0 and
  3233. localStoryDirection != inheritedHTFDirection
  3234.  
  3235. //======================================================================
  3236. // 20.7 ONE-SHOT EXECUTION AUTHORIZATION ENGINE — PRIMARY-TF LOCK v20.9.3.2
  3237. // State codes:
  3238. // 0=Locked/Waiting, 1=Parent active / setup building, 2=Execution armed,
  3239. // 3=Entry confirmed, 4=Delivery in progress, 5=Target reached,
  3240. // 6=Invalidated, 7=Expired.
  3241. //
  3242. // The engine never places an order. It grants one execution permission per
  3243. // inherited parent narrative ID only after:
  3244. // • the parent narrative owns a confirmed directional bias,
  3245. // • an undelivered objective remains with sufficient room,
  3246. // • an aligned qualified LTF CRT confirms, and
  3247. // • the LTF CRT reacts from liquidity or a directional key level/POI.
  3248. //======================================================================
  3249. int executionAuthorizationCurrentParentID = inheritedQualifiedNarrativeIDRaw
  3250.  
  3251. bool executionAuthorizationParentValidationPass =
  3252. not inheritedFreshNarrative or inheritedFreshValidationConfirmed
  3253.  
  3254. bool executionAuthorizationParentActive =
  3255. enableExecutionAuthorizationEngine and
  3256. authorizationChildMode and
  3257. htfBiasInheritanceLock and
  3258. executionAuthorizationCurrentParentID > 0 and
  3259. executionAuthorizationParentValidationPass and
  3260. not inheritedTargetReachedRaw and
  3261. not inheritedInvalidRaw and
  3262. not inheritedExpiredRaw and
  3263. not inheritedNarrativeArchived
  3264.  
  3265. float executionAuthorizationATR = ta.atr(14)
  3266. float executionAuthorizationObjectiveDistance =
  3267. inheritedHTFDirection == 1 and not na(inheritedNarrativeObjectiveRaw) ? inheritedNarrativeObjectiveRaw - close :
  3268. inheritedHTFDirection == -1 and not na(inheritedNarrativeObjectiveRaw) ? close - inheritedNarrativeObjectiveRaw :
  3269. na
  3270.  
  3271. bool executionAuthorizationObjectiveOpen =
  3272. executionAuthorizationParentActive and
  3273. not na(executionAuthorizationObjectiveDistance) and
  3274. executionAuthorizationObjectiveDistance > 0
  3275.  
  3276. bool executionAuthorizationRoomPass =
  3277. not authorizationRequireObjectiveRoom or
  3278. (
  3279. executionAuthorizationObjectiveOpen and
  3280. executionAuthorizationATR > 0 and
  3281. executionAuthorizationObjectiveDistance >= executionAuthorizationATR * authorizationMinimumRoomATR and
  3282. inheritedNarrativeTrackerStateRaw != 4
  3283. )
  3284.  
  3285. bool executionAuthorizationWindowPass =
  3286. not authorizationRequireDistributionWindow or insideDistributionWindow
  3287.  
  3288. bool executionAuthorizationAlignedQualifiedCRT =
  3289. barstate.isconfirmed and
  3290. qualifiedCRT and
  3291. currentQualifiedCRTDirection != 0 and
  3292. currentQualifiedCRTDirection == inheritedHTFDirection
  3293.  
  3294. bool executionAuthorizationLiquidityPass =
  3295. executionAuthorizationAlignedQualifiedCRT and meaningfulLiquidityPurge
  3296.  
  3297. bool executionAuthorizationPOIPass =
  3298. executionAuthorizationAlignedQualifiedCRT and
  3299. dedicatedKeyLevelAligned and
  3300. currentKeyLevelType != 0
  3301.  
  3302. bool executionAuthorizationContextPass =
  3303. not authorizationRequireLiquidityOrPOI or
  3304. executionAuthorizationLiquidityPass or
  3305. executionAuthorizationPOIPass
  3306.  
  3307. bool executionAuthorizationSetupArmed =
  3308. executionAuthorizationParentActive and
  3309. executionAuthorizationRoomPass and
  3310. executionAuthorizationWindowPass
  3311.  
  3312. bool executionAuthorizationTrigger =
  3313. executionAuthorizationSetupArmed and
  3314. executionAuthorizationAlignedQualifiedCRT and
  3315. executionAuthorizationContextPass
  3316.  
  3317. var int executionAuthorizationState = 0
  3318. var int executionAuthorizationParentID = 0
  3319. var string executionAuthorizationParentTF = ""
  3320. var int executionAuthorizationDirection = 0
  3321. var int executionAuthorizationConsumedParentID = 0
  3322. var string executionAuthorizationConsumedParentTF = ""
  3323. var int executionAuthorizationEntryBar = na
  3324. var float executionAuthorizationEntryPrice = na
  3325.  
  3326. bool executionAuthorizationIdentityChanged =
  3327. authorizationChildMode and
  3328. executionAuthorizationCurrentParentID > 0 and
  3329. (
  3330. executionAuthorizationCurrentParentID != executionAuthorizationParentID or
  3331. inheritanceParentTF != executionAuthorizationParentTF
  3332. )
  3333.  
  3334. if executionAuthorizationIdentityChanged
  3335. executionAuthorizationParentID := executionAuthorizationCurrentParentID
  3336. executionAuthorizationParentTF := inheritanceParentTF
  3337. executionAuthorizationDirection := inheritedFreshDirectionRaw != 0 ? inheritedFreshDirectionRaw : inheritedHTFDirection
  3338. executionAuthorizationState := 0
  3339. executionAuthorizationEntryBar := na
  3340. executionAuthorizationEntryPrice := na
  3341.  
  3342. if not enableExecutionAuthorizationEngine or not authorizationChildMode
  3343. executionAuthorizationState := 0
  3344. else if inheritedTargetReachedRaw and executionAuthorizationParentID > 0
  3345. executionAuthorizationState := 5
  3346. else if inheritedInvalidRaw and executionAuthorizationParentID > 0
  3347. executionAuthorizationState := 6
  3348. else if inheritedExpiredRaw and executionAuthorizationParentID > 0
  3349. executionAuthorizationState := 7
  3350. else if inheritedFreshValidationPending or inheritedFreshValidationRejected or inheritedNarrativeArchived
  3351. executionAuthorizationState := 0
  3352. else if executionAuthorizationParentActive
  3353. bool executionAuthorizationAlreadyConsumed =
  3354. executionAuthorizationConsumedParentID == executionAuthorizationCurrentParentID and
  3355. executionAuthorizationConsumedParentTF == inheritanceParentTF
  3356.  
  3357. if executionAuthorizationAlreadyConsumed
  3358. executionAuthorizationState := not na(executionAuthorizationEntryBar) and bar_index == executionAuthorizationEntryBar ? 3 : 4
  3359. else if executionAuthorizationTrigger
  3360. executionAuthorizationState := 3
  3361. executionAuthorizationConsumedParentID := executionAuthorizationCurrentParentID
  3362. executionAuthorizationConsumedParentTF := inheritanceParentTF
  3363. executionAuthorizationDirection := inheritedHTFDirection
  3364. executionAuthorizationEntryBar := bar_index
  3365. executionAuthorizationEntryPrice := close
  3366. else if executionAuthorizationSetupArmed
  3367. executionAuthorizationState := 2
  3368. else
  3369. executionAuthorizationState := 1
  3370. else
  3371. executionAuthorizationState := 0
  3372.  
  3373. bool executionAuthorizationConsumed =
  3374. executionAuthorizationCurrentParentID > 0 and
  3375. executionAuthorizationConsumedParentID == executionAuthorizationCurrentParentID and
  3376. executionAuthorizationConsumedParentTF == inheritanceParentTF
  3377.  
  3378. bool executionAuthorizationNoChase =
  3379. executionAuthorizationParentActive and
  3380. authorizationRequireObjectiveRoom and
  3381. not executionAuthorizationRoomPass
  3382.  
  3383. string executionAuthorizationStateText =
  3384. not enableExecutionAuthorizationEngine ? "AUTHORIZATION DISABLED" :
  3385. confirmationOnlyChildMode ? "CONFIRMATION ONLY • PRIMARY " + primaryExecutionTimeframeText :
  3386. not authorizationChildMode ? "PARENT-TF GUIDANCE ONLY" :
  3387. inheritedFreshValidationPending ? "LOCKED • VALIDATING PARENT" :
  3388. inheritedFreshValidationRejected ? "LOCKED • PARENT REJECTED" :
  3389. inheritedNarrativeArchived ? "LOCKED • OLD PARENT ARCHIVED" :
  3390. inheritedTargetReachedRaw or executionAuthorizationState == 5 ? "TARGET REACHED • STAND DOWN" :
  3391. inheritedInvalidRaw or executionAuthorizationState == 6 ? "INVALIDATED • WAIT NEW PARENT" :
  3392. inheritedExpiredRaw or executionAuthorizationState == 7 ? "EXPIRED • WAIT NEW PARENT" :
  3393. not htfBiasInheritanceLock ? "LOCKED • WAIT PARENT STORY" :
  3394. executionAuthorizationNoChase ? "LOCKED • NO CHASE • OBJECTIVE NEAR" :
  3395. authorizationRequireDistributionWindow and not executionAuthorizationWindowPass ? "LOCKED • WAIT DISTRIBUTION WINDOW" :
  3396. executionAuthorizationState == 4 ? "DELIVERY #" + f_narrativeIDText(executionAuthorizationParentID) + " IN PROGRESS • NO RE-ENTRY" :
  3397. executionAuthorizationState == 3 ? "ENTRY CONFIRMED #" + f_narrativeIDText(executionAuthorizationParentID) + " • ONE-SHOT AUTHORIZED" :
  3398. executionAuthorizationState == 2 ? "EXECUTION ARMED #" + f_narrativeIDText(executionAuthorizationParentID) + " • WAIT ALIGNED CRT" :
  3399. executionAuthorizationState == 1 ? "PARENT #" + f_narrativeIDText(executionAuthorizationParentID) + " ACTIVE • BUILDING SETUP" :
  3400. "LOCKED"
  3401.  
  3402. color executionAuthorizationStateColor =
  3403. inheritedFreshValidationPending ? color.new(color.orange, 62) :
  3404. inheritedFreshValidationRejected ? color.new(color.red, 58) :
  3405. inheritedNarrativeArchived ? color.new(color.orange, 65) :
  3406. executionAuthorizationState == 3 or executionAuthorizationState == 4 ? color.new(color.green, 55) :
  3407. executionAuthorizationState == 2 ? color.new(color.orange, 55) :
  3408. executionAuthorizationState == 5 ? color.new(color.green, 72) :
  3409. executionAuthorizationState == 6 ? color.new(color.red, 55) :
  3410. executionAuthorizationState == 7 ? color.new(color.gray, 68) :
  3411. executionAuthorizationNoChase ? color.new(color.orange, 62) :
  3412. color.new(color.gray, 78)
  3413.  
  3414. int displayExecutionDirection = htfBiasInheritanceLock ? inheritedHTFDirection : executionDirection
  3415.  
  3416. string displayTradeStatus =
  3417. parentStandDownDisplay ? "STAND DOWN" :
  3418. localStandDownDisplay ? "STAND DOWN" :
  3419. confirmationOnlyChildMode and enableExecutionAuthorizationEngine ? "CONFIRMATION" :
  3420. authorizationChildMode and enableExecutionAuthorizationEngine ?
  3421. (inheritedTargetReachedRaw or executionAuthorizationState == 5 ? "TARGET REACHED" :
  3422. inheritedInvalidRaw or executionAuthorizationState == 6 ? "INVALID" :
  3423. inheritedExpiredRaw or executionAuthorizationState == 7 ? "EXPIRED" :
  3424. executionAuthorizationState == 4 ? "DELIVERING" :
  3425. executionAuthorizationState == 3 ? "ENTRY CONFIRMED" :
  3426. executionAuthorizationState == 2 ? "EXECUTION ARMED" :
  3427. executionAuthorizationState == 1 ? "WATCH" :
  3428. "WAIT") :
  3429. executionChildMode ?
  3430. (inheritedTargetReachedRaw ? "TARGET REACHED" :
  3431. inheritedInvalidRaw ? "INVALID" :
  3432. inheritedExpiredRaw ? "EXPIRED" :
  3433. htfBiasInheritanceLock ?
  3434. (inheritedNarrativeRearmedRaw ? "RE-ARMED" : inheritedAlignedLocalCRT or localStoryAligned ? "READY" : "WATCH") :
  3435. "WAIT") :
  3436. (tradeTargetReached ? "TARGET REACHED" :
  3437. tradeInvalid ? "INVALID" :
  3438. tradeExpired ? "EXPIRED" :
  3439. localNarrativeRearmed ? "RE-ARMED" :
  3440. dashboardTradeStatus)
  3441.  
  3442. string displayExecutionBias =
  3443. dashboardStandDownDisplay ? "STAND DOWN" :
  3444. executionChildMode and inheritedTargetReachedRaw ? "STAND DOWN" :
  3445. executionChildMode and (inheritedInvalidRaw or inheritedExpiredRaw) ? "NEUTRAL" :
  3446. not executionChildMode and tradeTargetReached ? "STAND DOWN" :
  3447. not executionChildMode and (tradeInvalid or tradeExpired) ? "NEUTRAL" :
  3448. displayExecutionDirection == 1 ? "SEEK LONG" :
  3449. displayExecutionDirection == -1 ? "SEEK SHORT" :
  3450. "NEUTRAL"
  3451.  
  3452. string displayEntryCondition =
  3453. parentStandDownDisplay ? "NO CHASE • WAIT PARENT RE-ARM" :
  3454. localStandDownDisplay ? "NO CHASE • WAIT NEW CRT" :
  3455. confirmationOnlyChildMode and enableExecutionAuthorizationEngine ? "INFO ONLY • AUTHORIZE ON " + primaryExecutionTimeframeText :
  3456. authorizationChildMode and enableExecutionAuthorizationEngine ?
  3457. (inheritedTargetReachedRaw ? "NO CHASE • PARENT TARGET DONE" :
  3458. inheritedInvalidRaw or inheritedExpiredRaw ? "WAIT NEW PARENT CRT" :
  3459. inheritedFreshValidationPending ? "WAIT PARENT VALIDATION" :
  3460. inheritedFreshValidationRejected ? "WAIT NEWER PARENT ID" :
  3461. executionAuthorizationState == 4 ? "NO RE-ENTRY • MANAGE DELIVERY" :
  3462. executionAuthorizationState == 3 ? "ENTRY CONFIRMED • APPLY RISK PLAN" :
  3463. executionAuthorizationNoChase ? "NO CHASE • INSUFFICIENT OBJECTIVE ROOM" :
  3464. authorizationRequireDistributionWindow and not executionAuthorizationWindowPass ? "WAIT HTF DISTRIBUTION WINDOW" :
  3465. executionAuthorizationState == 2 ?
  3466. (authorizationRequireLiquidityOrPOI ? "WAIT ALIGNED QUALIFIED CRT AT LIQUIDITY / POI" : "WAIT ALIGNED QUALIFIED LTF CRT") :
  3467. executionAuthorizationState == 1 ? "WAIT SETUP CONDITIONS" :
  3468. "WAIT PARENT STORY") :
  3469. executionChildMode ?
  3470. (inheritedTargetReachedRaw ? "NO CHASE • PARENT TARGET DONE" :
  3471. inheritedInvalidRaw ? "WAIT NEW PARENT CRT" :
  3472. inheritedExpiredRaw ? "WAIT NEW PARENT CRT" :
  3473. htfBiasInheritanceLock ?
  3474. (inheritedOpposingLocalCRT or localStoryOpposed ? "IGNORE OPPOSING LTF STORY" :
  3475. inheritedAlignedLocalCRT or localStoryAligned ? "ALIGNED LTF STORY CONFIRMED" :
  3476. displayExecutionDirection == 1 ? "WAIT BULLISH LTF CRT" : "WAIT BEARISH LTF CRT") :
  3477. "WAIT PARENT STORY") :
  3478. tradeTargetReached ? "NO CHASE • TARGET DONE" :
  3479. tradeInvalid ? "NO TRADE • WAIT NEW CRT" :
  3480. tradeExpired ? "WAIT NEW QUALIFIED CRT" :
  3481. dashboardEntryCondition
  3482.  
  3483. string displayRiskState =
  3484. parentStandDownDisplay ? "PARENT NARRATIVE ARCHIVED" :
  3485. localStandDownDisplay ? "NARRATIVE ARCHIVED" :
  3486. confirmationOnlyChildMode and enableExecutionAuthorizationEngine ? "INFO ONLY • NO AUTHORIZATION" :
  3487. authorizationChildMode and enableExecutionAuthorizationEngine ?
  3488. (inheritedTargetReachedRaw ? "PARENT OBJECTIVE DELIVERED" :
  3489. inheritedInvalidRaw ? "PARENT INVALIDATED" :
  3490. inheritedExpiredRaw ? "PARENT EXPIRED" :
  3491. executionAuthorizationState == 4 ? "ACTIVE EXECUTION • ONE-SHOT CONSUMED" :
  3492. executionAuthorizationState == 3 ? "AUTHORIZED • APPLY RISK PLAN" :
  3493. executionAuthorizationState == 2 ? "NO POSITION • AUTHORIZATION ARMED" :
  3494. executionAuthorizationNoChase ? "NO RISK • NO CHASE" :
  3495. htfBiasInheritanceLock ? "NO ACTIVE RISK • PARENT ACTIVE" : "NO PARENT RISK") :
  3496. executionChildMode ?
  3497. (inheritedTargetReachedRaw ? "PARENT OBJECTIVE DELIVERED" :
  3498. inheritedInvalidRaw ? "PARENT INVALIDATED" :
  3499. inheritedExpiredRaw ? "PARENT EXPIRED" :
  3500. htfBiasInheritanceLock ? "PARENT STORY ACTIVE" : "NO PARENT RISK") :
  3501. dashboardRiskState
  3502.  
  3503. string displaySetupAge =
  3504. parentStandDownDisplay ? "ARCHIVED PARENT #" + f_narrativeIDText(inheritedTerminalNarrativeIDRaw) :
  3505. localStandDownDisplay ? "ARCHIVED NARRATIVE #" + f_narrativeIDText(latestTerminalNarrativeID) :
  3506. executionChildMode ? str.tostring(inheritedSetupAgeRaw) + " / " + str.tostring(lifecycleExpiryBars) + " PARENT BARS" : dashboardSetupAge
  3507.  
  3508. // v20.6 Parent Story Synchronization (retained in v20.9.3.2).
  3509. // Candidate state is displayed before the inherited directional lock is allowed
  3510. // to activate. This keeps child dashboards synchronized with the live parent ID
  3511. // and validation score without weakening the validation safety lock.
  3512. string inheritedFreshDirectionText =
  3513. inheritedFreshDirectionRaw == 1 ? "BULLISH" :
  3514. inheritedFreshDirectionRaw == -1 ? "BEARISH" :
  3515. "DIRECTIONAL"
  3516.  
  3517. string inheritedParentStory =
  3518. inheritedFreshNarrative and inheritedFreshValidationPending ?
  3519. inheritanceParentTF + " " + inheritedFreshDirectionText +
  3520. " CANDIDATE #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) +
  3521. " • VALIDATING " + str.tostring(inheritedFreshValidationScoreRaw) + "/4" :
  3522. inheritedFreshNarrative and inheritedFreshValidationRejected ?
  3523. inheritanceParentTF + " " + inheritedFreshDirectionText +
  3524. " CANDIDATE #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) +
  3525. " • REJECTED" :
  3526. inheritedFreshNarrative and inheritedFreshValidationConfirmed and inheritedParentStoryType != 0 ?
  3527. inheritanceParentTF + " " + inheritedFreshDirectionText +
  3528. " NARRATIVE ACTIVE #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) +
  3529. (inheritedNarrativeRearmedRaw ? " • RE-ARMED" : "") :
  3530. inheritedParentStoryType == 2 ?
  3531. inheritanceParentTF + (inheritedHTFDirection == 1 ? " BULL REVERSAL" : " BEAR REVERSAL") :
  3532. inheritedParentStoryType == 1 ?
  3533. inheritanceParentTF + (inheritedHTFDirection == 1 ? " BULLISH NARRATIVE ACTIVE" : " BEARISH NARRATIVE ACTIVE") :
  3534. inheritedTargetReachedRaw ? inheritanceParentTF + " OBJECTIVE DELIVERED • STAND DOWN" :
  3535. inheritedInvalidRaw ? inheritanceParentTF + " INVALIDATED • RESET" :
  3536. inheritedExpiredRaw ? inheritanceParentTF + " EXPIRED • RESET" :
  3537. inheritanceParentTF + " WAITING FOR NEW NARRATIVE"
  3538.  
  3539. // v18.8 lifecycle clarity: the CRT row describes both direction and lifecycle.
  3540. // This prevents a delivered historical bearish CRT from looking like a live short bias.
  3541. string localLifecycleText =
  3542. localNarrativeArchived ? "ARCHIVED" :
  3543. tradeReversalActive ?
  3544. (latestCRTDirection == 1 ? "BULLISH FAILED" : latestCRTDirection == -1 ? "BEARISH FAILED" : "FAILED") :
  3545. tradeTargetReached ? "DELIVERED" :
  3546. tradeInvalid ? "INVALID" :
  3547. tradeExpired ? "EXPIRED" :
  3548. crtLifecycleActive ?
  3549. (activeCRTDirection == 1 ? "BULLISH ACTIVE" : activeCRTDirection == -1 ? "BEARISH ACTIVE" : "ACTIVE") :
  3550. "WAITING"
  3551.  
  3552. string dashboardCRTState =
  3553. executionChildMode and inheritedNarrativeArchived ? "PARENT STORY ARCHIVED" :
  3554. not executionChildMode and localNarrativeArchived ? "NARRATIVE ARCHIVED" :
  3555. htfBiasInheritanceLock and (inheritedOpposingLocalCRT or localStoryOpposed) ? "LTF STORY OPPOSED" :
  3556. htfBiasInheritanceLock and (inheritedAlignedLocalCRT or localStoryAligned) ? "LTF STORY ALIGNED" :
  3557. htfBiasInheritanceLock ? "LTF WAITING" :
  3558. localLifecycleText
  3559.  
  3560. string dashboardHTF =
  3561. hierarchyAligned ? "ALIGNED" :
  3562. hierarchyOpposing ? "CONFLICT" :
  3563. "NEUTRAL"
  3564.  
  3565. string dashboardPOI =
  3566. f_keyLevelTypeText(latestKeyLevelType, latestKeyLevelDirection)
  3567.  
  3568. string dashboardKeyLevelTF =
  3569. latestKeyLevelType != 0 ? selectedHTF : "—"
  3570.  
  3571. string dashboardPurge =
  3572. meaningfulLiquidityPurge ?
  3573. (latestCRTDirection == 1 ? "SSL PURGED" : latestCRTDirection == -1 ? "BSL PURGED" : "CONFIRMED") :
  3574. "NONE"
  3575.  
  3576. string dashboardSMT =
  3577. smtAligned ?
  3578. (latestCRTDirection == 1 ? "BULLISH" : latestCRTDirection == -1 ? "BEARISH" : "CONFIRMED") :
  3579. smtOpposing ? "CONFLICT" :
  3580. "NEUTRAL"
  3581.  
  3582. string dashboardNested =
  3583. meaningfulNestedContext ? "ALIGNED" :
  3584. parentContextActive ? "NEUTRAL" :
  3585. "NONE"
  3586.  
  3587. string dashboardDelivery =
  3588. executionChildMode and inheritedTargetReachedRaw ? "DELIVERED" :
  3589. executionChildMode and inheritedInvalidRaw ? "INVALID" :
  3590. executionChildMode and inheritedExpiredRaw ? "EXPIRED" :
  3591. not executionChildMode and tradeTargetReached ? "DELIVERED" :
  3592. not executionChildMode and tradeInvalid ? "INVALID" :
  3593. not executionChildMode and tradeExpired ? "EXPIRED" :
  3594. htfBiasInheritanceLock ?
  3595. (localStoryAligned ? "ALIGNED" : localStoryOpposed ? "OPPOSED" : "WAITING") :
  3596. meaningfulDeliveryContext ? "CONFIRMED" :
  3597. tradeReversalActive ? "FAILED" :
  3598. "WAITING"
  3599.  
  3600. string dashboardTarget =
  3601. narrativeGenerationWaiting ? "ARCHIVED" :
  3602. f_targetTypeText(activeDrawTargetType, latestCRTDirection)
  3603.  
  3604. string dashboardTargetStatus =
  3605. narrativeGenerationWaiting ? "CLOSED" :
  3606. tradeTargetReached ? "REACHED" :
  3607. activeDrawTargetAvailable and not tradeReversalActive and not tradeInvalid ? "ACTIVE" :
  3608. "NONE"
  3609.  
  3610. //======================================================================
  3611. // 20.8 DASHBOARD CLARITY LAYER
  3612. // Display-only separation of the owning parent objective from local CRT
  3613. // diagnostics. The authorization state machine and room threshold are not
  3614. // modified here.
  3615. //======================================================================
  3616. bool dashboardRoomFilterFailed =
  3617. executionChildMode and
  3618. enableExecutionAuthorizationEngine and
  3619. executionAuthorizationNoChase
  3620.  
  3621. string dashboardObjectiveLabel =
  3622. executionChildMode ? "PARENT OBJECTIVE" : "DRAW ON LIQUIDITY"
  3623.  
  3624. string dashboardObjectiveDisplay =
  3625. executionChildMode ?
  3626. (inheritedNarrativeObjectiveText + (dashboardRoomFilterFailed ? " • TOO NEAR" : "")) :
  3627. dashboardTarget
  3628.  
  3629. string dashboardLocalTargetLabel =
  3630. executionChildMode ? "LOCAL TARGET" : "TARGET STATUS"
  3631.  
  3632. string dashboardLocalTargetDisplay =
  3633. executionChildMode ?
  3634. (tradeTargetReached ? "OLD TARGET REACHED • INFO ONLY" :
  3635. tradeInvalid ? "LOCAL TARGET INVALID • INFO ONLY" :
  3636. tradeExpired ? "LOCAL TARGET EXPIRED • INFO ONLY" :
  3637. activeDrawTargetAvailable and not tradeReversalActive ? "LOCAL TARGET ACTIVE • INFO ONLY" :
  3638. "NO ACTIVE LOCAL TARGET") :
  3639. dashboardTargetStatus
  3640.  
  3641. string dashboardFailure =
  3642. htfBiasInheritanceLock ?
  3643. (localStoryOpposed ? "OPPOSED TO HTF" : localStoryAligned ? "ALIGNED TO HTF" : "NONE") :
  3644. tradeReversalActive ?
  3645. (latestFailedCRTReversalDirection == 1 ? "BULL REVERSAL" : "BEAR REVERSAL") :
  3646. "NONE"
  3647.  
  3648. //======================================================================
  3649. // 14C. STORY TRANSLATION + CENTRAL STATE MATRIX — v19.7
  3650. // Student-facing explanation of the local CRT, its implication, its
  3651. // alignment with the inherited HTF story, and the practical action.
  3652. // This changes dashboard wording only; detection logic is untouched.
  3653. //======================================================================
  3654. string dashboardLocalCRT =
  3655. parentStandDownDisplay ? "INFORMATION ONLY • LOCAL CRT IGNORED" :
  3656. localNarrativeArchived ? "OLD CRT ARCHIVED" :
  3657. tradeReversalActive ?
  3658. (latestCRTDirection == 1 ? "BULLISH CRT FAILED" : latestCRTDirection == -1 ? "BEARISH CRT FAILED" : "CRT FAILED") :
  3659. tradeTargetReached ? "CRT DELIVERED" :
  3660. tradeInvalid ? "CRT INVALID" :
  3661. tradeExpired ? "CRT EXPIRED" :
  3662. crtLifecycleActive ?
  3663. (activeCRTDirection == 1 ? "BULLISH CRT ACTIVE" : activeCRTDirection == -1 ? "BEARISH CRT ACTIVE" : "CRT ACTIVE") :
  3664. "NO LOCAL CRT"
  3665.  
  3666. string dashboardLocalImplication =
  3667. parentStandDownDisplay ? "INFORMATION ONLY • PARENT LOCKED" :
  3668. localNarrativeArchived ? "WAIT NEW NARRATIVE" :
  3669. tradeReversalActive ?
  3670. (latestFailedCRTReversalDirection == 1 ? "BULLISH REVERSAL" : "BEARISH REVERSAL") :
  3671. tradeTargetReached ? "OBJECTIVE COMPLETE" :
  3672. tradeInvalid ? "RESET CONTEXT" :
  3673. tradeExpired ? "WAIT NEW CRT" :
  3674. crtLifecycleActive ?
  3675. (activeCRTDirection == 1 ? "BULLISH DELIVERY" : activeCRTDirection == -1 ? "BEARISH DELIVERY" : "ACTIVE DELIVERY") :
  3676. "WAITING"
  3677.  
  3678. string dashboardHTFAlignment =
  3679. parentStandDownDisplay ? "LOCKED • PARENT ARCHIVED" :
  3680. dashboardRoomFilterFailed and htfBiasInheritanceLock ? "CONFIRMED • PARENT ACTIVE" :
  3681. not htfBiasInheritanceLock ? dashboardHTF :
  3682. localStoryAligned or inheritedAlignedLocalCRT ? "ALIGNED" :
  3683. localStoryOpposed or inheritedOpposingLocalCRT ? "OPPOSED" :
  3684. "WAITING"
  3685.  
  3686. string dashboardAction =
  3687. executionChildMode and inheritedNarrativeArchived ? "WAIT NEW QUALIFIED PARENT CRT" :
  3688. not executionChildMode and localNarrativeArchived ? "WAIT NEW QUALIFIED CRT" :
  3689. not executionChildMode ? (localNarrativeRearmed ? "NEW NARRATIVE • RE-ARMED" : "FOLLOW ENGINE VERDICT") :
  3690. enableExecutionAuthorizationEngine and executionAuthorizationState == 4 ? "MANAGE DELIVERY • NO SECOND ENTRY" :
  3691. enableExecutionAuthorizationEngine and executionAuthorizationState == 3 ? "ENTRY AUTHORIZED • EXECUTE RISK PLAN" :
  3692. enableExecutionAuthorizationEngine and executionAuthorizationNoChase ? "STAND DOWN • OBJECTIVE TOO NEAR" :
  3693. enableExecutionAuthorizationEngine and authorizationRequireDistributionWindow and not executionAuthorizationWindowPass ? "WAIT HTF DISTRIBUTION WINDOW" :
  3694. enableExecutionAuthorizationEngine and executionAuthorizationState == 2 ?
  3695. (authorizationRequireLiquidityOrPOI ? "HUNT ALIGNED CRT AT LIQUIDITY / POI" : "HUNT ALIGNED QUALIFIED LTF CRT") :
  3696. enableExecutionAuthorizationEngine and executionAuthorizationState == 1 ? "BUILDING SETUP • WAIT CONDITIONS" :
  3697. inheritedNarrativeRearmedRaw and htfBiasInheritanceLock ? "RE-ARMED • HUNT ALIGNED LTF CRT" :
  3698. not htfBiasInheritanceLock ? "WAIT PARENT STORY" :
  3699. localStoryOpposed or inheritedOpposingLocalCRT ? "IGNORE • WAIT ALIGNED CRT" :
  3700. tradeExpired ? (displayExecutionDirection == 1 ? "LOCAL RESET • WAIT BULL CRT" : "LOCAL RESET • WAIT BEAR CRT") :
  3701. not insideDistributionWindow ? "WAIT EXECUTION WINDOW" :
  3702. localStoryAligned or inheritedAlignedLocalCRT ? "CONFIRM ENTRY + RISK" :
  3703. displayExecutionDirection == 1 ? "WAIT BULLISH LTF CRT" :
  3704. displayExecutionDirection == -1 ? "WAIT BEARISH LTF CRT" :
  3705. "WAIT HTF BIAS"
  3706.  
  3707. //======================================================================
  3708. // 14B. MULTI-TIMEFRAME EXECUTION GUIDANCE — v19.2
  3709. // Translates the HTF lifecycle into the next practical timeframe, the
  3710. // structure to hunt, and whether the existing LTF execution scanner is
  3711. // locked, open, or has confirmed an aligned CRT. This is guidance only.
  3712. //======================================================================
  3713. f_nextExecutionTF(string sourceTF) =>
  3714. sourceTF == "M" ? "W / D" :
  3715. sourceTF == "W" ? "D / H4" :
  3716. sourceTF == "D" ? "H4 / H1" :
  3717. sourceTF == "240" or sourceTF == "180" or sourceTF == "120" ? "H1 / 15M" :
  3718. sourceTF == "60" ? "15M / 5M" :
  3719. sourceTF == "30" ? "5M / 3M" :
  3720. "5M / 3M / 2M / 1M"
  3721.  
  3722. // v20.2 Narrative Candidate State Tracker.
  3723. // Makes every fresh narrative transition visible:
  3724. // WAIT ID -> CANDIDATE ID -> VALIDATING score -> CONFIRMED/RE-ARMED
  3725. // or -> REJECTED ID (permanent).
  3726. string dashboardFreshValidation =
  3727. executionChildMode ?
  3728. (not inheritedFreshNarrative ? "WAIT FRESH PARENT ID" :
  3729. inheritedFreshValidationConfirmed ?
  3730. "CONFIRMED #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) + " • " +
  3731. str.tostring(inheritedFreshValidationScoreRaw) + "/4 • " +
  3732. (inheritedFreshDirectionRaw == 1 ? "BULLISH" : "BEARISH") :
  3733. inheritedFreshValidationRejected ?
  3734. "REJECTED #" + f_narrativeIDText(inheritedRejectedNarrativeIDRaw) + " • PERMANENT" :
  3735. "CANDIDATE #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) +
  3736. " • VALIDATING " + str.tostring(inheritedFreshValidationScoreRaw) + "/4") :
  3737. not hasFreshNarrativeIdentity ? "WAIT FRESH ID" :
  3738. freshValidationConfirmed ?
  3739. "CONFIRMED #" + f_narrativeIDText(latestQualifiedNarrativeID) + " • " +
  3740. str.tostring(freshValidationScore) + "/4 • " +
  3741. (latestNarrativeDirection == 1 ? "BULLISH" : "BEARISH") :
  3742. freshValidationRejected ?
  3743. "REJECTED #" + f_narrativeIDText(latestRejectedNarrativeID) + " • PERMANENT" :
  3744. "CANDIDATE #" + f_narrativeIDText(latestQualifiedNarrativeID) +
  3745. " • VALIDATING " + str.tostring(freshValidationScore) + "/4"
  3746.  
  3747. string dashboardNarrativeMemory =
  3748. executionChildMode ?
  3749. (inheritedFreshValidationPending ?
  3750. "CANDIDATE #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) + " • AGE " + str.tostring(inheritedFreshNarrativeAgeRaw) :
  3751. inheritedNarrativeFreshRaw ?
  3752. "FRESH #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) + " • AGE " + str.tostring(inheritedFreshNarrativeAgeRaw) :
  3753. inheritedFreshValidationRejected ?
  3754. "REJECTED #" + f_narrativeIDText(inheritedRejectedNarrativeIDRaw) + " • WAIT NEWER ID" :
  3755. inheritedFreshNarrative ?
  3756. "ACTIVE #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) :
  3757. inheritedTargetReachedRaw or inheritedInvalidRaw or inheritedExpiredRaw ?
  3758. "RESET #" + f_narrativeIDText(inheritedTerminalNarrativeIDRaw) + " • WAIT NEXT ID" :
  3759. inheritedQualifiedNarrativeIDRaw > 0 ?
  3760. "CURRENT #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) :
  3761. "NO NARRATIVE ID") :
  3762. freshValidationState == 1 and hasFreshNarrativeIdentity ?
  3763. "CANDIDATE #" + f_narrativeIDText(latestQualifiedNarrativeID) + " • AGE " + str.tostring(freshNarrativeAge) :
  3764. localNarrativeFresh ?
  3765. "FRESH #" + f_narrativeIDText(latestQualifiedNarrativeID) + " • AGE " + str.tostring(freshNarrativeAge) :
  3766. freshValidationRejected ?
  3767. "REJECTED #" + f_narrativeIDText(latestRejectedNarrativeID) + " • WAIT NEWER ID" :
  3768. hasFreshNarrativeIdentity and crtLifecycleActive ?
  3769. "ACTIVE #" + f_narrativeIDText(latestQualifiedNarrativeID) :
  3770. tradeTargetReached or tradeInvalid or tradeExpired ?
  3771. "RESET #" + f_narrativeIDText(latestTerminalNarrativeID) + " • WAIT NEXT ID" :
  3772. latestQualifiedNarrativeID > 0 ?
  3773. "CURRENT #" + f_narrativeIDText(latestQualifiedNarrativeID) :
  3774. "NO NARRATIVE ID"
  3775.  
  3776. string dashboardNarrativeState =
  3777. executionChildMode ?
  3778. (inheritedFreshNarrative and inheritedFreshValidationPending ?
  3779. "CANDIDATE #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) + " • PARENT VALIDATING" :
  3780. inheritedFreshNarrative and inheritedFreshValidationRejected ?
  3781. "REJECTED #" + f_narrativeIDText(inheritedRejectedNarrativeIDRaw) + " • WAIT NEWER PARENT" :
  3782. inheritedNarrativeRearmedRaw and htfBiasInheritanceLock ?
  3783. "RE-ARMED #" + f_narrativeIDText(inheritedQualifiedNarrativeIDRaw) + " • PARENT CONFIRMED" :
  3784. inheritedNarrativeArchived ?
  3785. "ARCHIVED #" + f_narrativeIDText(inheritedTerminalNarrativeIDRaw) + " • WAIT NEW PARENT" :
  3786. htfBiasInheritanceLock ? "ARMED • PARENT STORY ACTIVE" :
  3787. "WAIT NEW PARENT NARRATIVE") :
  3788. hasFreshNarrativeIdentity and freshValidationState == 1 ?
  3789. "CANDIDATE #" + f_narrativeIDText(latestQualifiedNarrativeID) + " • VALIDATING" :
  3790. hasFreshNarrativeIdentity and freshValidationState == 3 ?
  3791. "REJECTED #" + f_narrativeIDText(latestRejectedNarrativeID) + " • WAIT NEWER ID" :
  3792. localNarrativeRearmed ?
  3793. "RE-ARMED #" + f_narrativeIDText(latestQualifiedNarrativeID) + " • FRESH CONFIRMED" :
  3794. localNarrativeArchived ?
  3795. "ARCHIVED #" + f_narrativeIDText(latestTerminalNarrativeID) + " • WAIT NEW ID" :
  3796. crtLifecycleActive or tradeReversalActive ? "ARMED • NARRATIVE ACTIVE" :
  3797. "WAIT NEW NARRATIVE"
  3798.  
  3799. string dashboardHTFStory =
  3800. executionChildMode and inheritedNarrativeArchived ?
  3801. inheritanceParentTF + " ARCHIVED #" + f_narrativeIDText(inheritedTerminalNarrativeIDRaw) + " → WAIT NEW STORY" :
  3802. executionChildMode ? inheritedParentStory :
  3803. localNarrativeArchived ?
  3804. "ARCHIVED #" + f_narrativeIDText(latestTerminalNarrativeID) + " → WAIT NEW QUALIFIED CRT" :
  3805. tradeReversalActive ? dashboardCRTState + " → " + dashboardFailure :
  3806. crtLifecycleActive ? dashboardCRTState + " → " + dashboardDelivery :
  3807. "WAIT QUALIFIED HTF CRT"
  3808.  
  3809. string dashboardNextTF =
  3810. parentStandDownDisplay ? "PARENT RE-ARM REQUIRED" :
  3811. localStandDownDisplay ? "NEW QUALIFIED CRT REQUIRED" :
  3812. confirmationOnlyChildMode ? primaryExecutionTimeframeText + " PRIMARY EXECUTION" :
  3813. executionChildMode ?
  3814. (authorizationChildMode ? timeframe.period + " PRIMARY EXECUTION" : f_nextExecutionTF(timeframe.period)) :
  3815. tradeInvalid or tradeExpired ? selectedHTF :
  3816. f_nextExecutionTF(selectedHTF)
  3817.  
  3818. string dashboardHunt =
  3819. confirmationOnlyChildMode and enableExecutionAuthorizationEngine ? "CONFIRM HERE • AUTHORIZE ON " + primaryExecutionTimeframeText :
  3820. authorizationChildMode and enableExecutionAuthorizationEngine ?
  3821. (inheritedFreshNarrative and inheritedFreshValidationPending ? "WAIT PARENT VALIDATION" :
  3822. inheritedFreshNarrative and inheritedFreshValidationRejected ? "WAIT NEXT PARENT CRT" :
  3823. inheritedNarrativeArchived ? "WAIT NEW QUALIFIED PARENT CRT" :
  3824. executionAuthorizationState == 4 or executionAuthorizationState == 3 ? "DELIVERY TO PARENT OBJECTIVE" :
  3825. executionAuthorizationNoChase ? "NO CHASE • OBJECTIVE TOO NEAR" :
  3826. executionAuthorizationState == 2 ?
  3827. (displayExecutionDirection == 1 ? "BULLISH CRT AT SSL / POI" : "BEARISH CRT AT BSL / POI") :
  3828. executionAuthorizationState == 1 ? "LIQUIDITY / POI + ALIGNED CRT" :
  3829. "WAIT PARENT STORY") :
  3830. executionChildMode ?
  3831. (inheritedFreshNarrative and inheritedFreshValidationPending ? "WAIT PARENT VALIDATION" :
  3832. inheritedFreshNarrative and inheritedFreshValidationRejected ? "WAIT NEXT PARENT CRT" :
  3833. inheritedNarrativeRearmedRaw and htfBiasInheritanceLock ? "ALIGNED CRT CONTEXT" :
  3834. inheritedNarrativeArchived ? "WAIT NEW QUALIFIED PARENT CRT" :
  3835. htfBiasInheritanceLock ?
  3836. (displayExecutionDirection == 1 ? "BULLISH LTF CRT" : "BEARISH LTF CRT") :
  3837. "WAIT PARENT STORY") :
  3838. hasFreshNarrativeIdentity and freshValidationState == 1 ? "WAIT VALIDATION" :
  3839. hasFreshNarrativeIdentity and freshValidationState == 3 ? "WAIT NEXT QUALIFIED CRT" :
  3840. localNarrativeRearmed ? "ALIGNED CRT CONTEXT" :
  3841. localNarrativeArchived ? "WAIT NEW QUALIFIED CRT" :
  3842. tradeReversalActive ?
  3843. (executionDirection == 1 ? "BULLISH LTF CRT" : "BEARISH LTF CRT") :
  3844. tradeReady or tradeWatch ?
  3845. (executionDirection == 1 ? "ALIGNED BULLISH CRT" : executionDirection == -1 ? "ALIGNED BEARISH CRT" : "ALIGNED LTF CRT") :
  3846. "HTF RANGE + PURGE"
  3847.  
  3848. string dashboardExecutionState =
  3849. confirmationOnlyChildMode and enableExecutionAuthorizationEngine ? "CONFIRMATION ONLY • PRIMARY " + primaryExecutionTimeframeText :
  3850. authorizationChildMode and enableExecutionAuthorizationEngine ? executionAuthorizationStateText :
  3851. executionChildMode and inheritedFreshNarrative and inheritedFreshValidationPending ? "LOCKED • VALIDATING PARENT" :
  3852. executionChildMode and inheritedFreshNarrative and inheritedFreshValidationRejected ? "LOCKED • PARENT REJECTED" :
  3853. executionChildMode and inheritedNarrativeRearmedRaw and htfBiasInheritanceLock ? "RE-ARMED • SCANNING NEW STORY" :
  3854. executionChildMode and inheritedNarrativeArchived ? "LOCKED • OLD PARENT ARCHIVED" :
  3855. not executionChildMode and localNarrativeArchived ? "LOCKED • OLD NARRATIVE ARCHIVED" :
  3856. htfBiasInheritanceLock and (inheritedOpposingLocalCRT or localStoryOpposed) ? "OPPOSED • IGNORE" :
  3857. htfBiasInheritanceLock and (inheritedAlignedLocalCRT or localStoryAligned) ? "CONFIRMED" :
  3858. qualifiedLTFStructure ? "CONFIRMED" :
  3859. structureEngineUnlocked ? "UNLOCKED • SCANNING" :
  3860. executionTimeframeAllowed and not insideDistributionWindow ? "LOCKED • WAIT WINDOW" :
  3861. tradeReversalActive or crtLifecycleActive ? "LOCKED • MOVE TO LTF" :
  3862. "LOCKED"
  3863.  
  3864. color dashboardExecutionStateColor =
  3865. parentStandDownDisplay ? color.new(color.orange, 65) :
  3866. localStandDownDisplay ? color.new(color.orange, 65) :
  3867. confirmationOnlyChildMode and enableExecutionAuthorizationEngine ? color.new(color.blue, 68) :
  3868. authorizationChildMode and enableExecutionAuthorizationEngine ? executionAuthorizationStateColor :
  3869. executionChildMode and inheritedFreshNarrative and inheritedFreshValidationPending ? color.new(color.orange, 62) :
  3870. executionChildMode and inheritedFreshNarrative and inheritedFreshValidationRejected ? color.new(color.red, 58) :
  3871. executionChildMode and inheritedNarrativeRearmedRaw and htfBiasInheritanceLock ? color.new(color.green, 58) :
  3872. executionChildMode and inheritedTargetReachedRaw ? color.new(color.green, 72) :
  3873. executionChildMode and (inheritedInvalidRaw or inheritedExpiredRaw) ? color.new(color.gray, 72) :
  3874. htfBiasInheritanceLock and (inheritedOpposingLocalCRT or localStoryOpposed) ? color.new(color.red, 58) :
  3875. htfBiasInheritanceLock and (inheritedAlignedLocalCRT or localStoryAligned) ? color.new(color.green, 58) :
  3876. qualifiedLTFStructure ? color.new(color.green, 58) :
  3877. structureEngineUnlocked ? color.new(color.orange, 62) :
  3878. color.new(color.gray, 78)
  3879.  
  3880.  
  3881. string dashboardNarrativeDelivery =
  3882. executionChildMode and inheritedNarrativeArchived ? "ARCHIVED • WAIT NEW STORY" :
  3883. not executionChildMode and localNarrativeArchived ? "ARCHIVED • WAIT NEW STORY" :
  3884. executionChildMode ? inheritedNarrativeTrackerText : narrativeTrackerStateText
  3885.  
  3886. string dashboardNarrativeObjective =
  3887. executionChildMode and inheritedNarrativeArchived ? "OLD OBJECTIVE CLOSED" :
  3888. not executionChildMode and localNarrativeArchived ? "OLD OBJECTIVE CLOSED" :
  3889. executionChildMode ? inheritedNarrativeObjectiveText : narrativeObjectiveText
  3890.  
  3891. color dashboardNarrativeTrackerColor =
  3892. dashboardStandDownDisplay ? color.new(color.gray, 72) :
  3893. executionChildMode ?
  3894. (
  3895. inheritedNarrativeTrackerStateRaw == 3 or
  3896. inheritedNarrativeTrackerStateRaw == 4 or
  3897. inheritedNarrativeTrackerStateRaw == 5 ?
  3898. color.new(color.green, 58) :
  3899. inheritedNarrativeTrackerStateRaw == 1 or
  3900. inheritedNarrativeTrackerStateRaw == 2 ?
  3901. color.new(color.orange, 62) :
  3902. inheritedNarrativeTrackerStateRaw == 6 or
  3903. inheritedNarrativeTrackerStateRaw == 8 ?
  3904. color.new(color.red, 58) :
  3905. color.new(color.gray, 78)
  3906. ) :
  3907. narrativeTrackerColor
  3908.  
  3909. string dashboardGrade = f_gradeText(latestCRTGradeCode)
  3910.  
  3911. string dashboardVerdict =
  3912. executionChildMode and inheritedNarrativeArchived ?
  3913. "PARENT #" + f_narrativeIDText(inheritedTerminalNarrativeIDRaw) + " ARCHIVED • WAIT NEW QUALIFIED PARENT CRT" :
  3914. not executionChildMode and localNarrativeArchived ?
  3915. "NARRATIVE #" + f_narrativeIDText(latestTerminalNarrativeID) + " ARCHIVED • WAIT NEW QUALIFIED CRT" :
  3916. executionChildMode ?
  3917. (htfBiasInheritanceLock ?
  3918. (localStoryOpposed or inheritedOpposingLocalCRT ?
  3919. inheritedParentStory + " • LOCAL STORY OPPOSED • IGNORE" :
  3920. localStoryAligned or inheritedAlignedLocalCRT ?
  3921. inheritedParentStory + " • LTF ALIGNED • CONFIRM RISK" :
  3922. inheritedParentStory + " • WAIT ALIGNED LTF CRT") :
  3923. inheritedParentStory) :
  3924. tradeReversalActive ?
  3925. localLifecycleText + " • " + dashboardFailure + " • WAIT LTF CONFIRMATION" :
  3926. localLifecycleText == "WAITING" ?
  3927. "WAITING FOR QUALIFIED CRT" :
  3928. dashboardGrade + " " + localLifecycleText + " • " +
  3929. (dashboardDelivery == "CONFIRMED" ? "DELIVERY CONFIRMED" : "WAIT FOR DELIVERY") +
  3930. (dashboardTarget != "NONE" ? " • DRAW " + dashboardTarget : "")
  3931.  
  3932. string dashboardDecisionLabel =
  3933. dashboardRoomFilterFailed ? "ROOM FILTER" :
  3934. htfBiasInheritanceLock ? "ACTION" : "ENGINE VERDICT"
  3935.  
  3936. string dashboardDecisionDisplay =
  3937. dashboardRoomFilterFailed ? "FAILED • NO CHASE" :
  3938. executionChildMode ? dashboardAction : dashboardVerdict
  3939.  
  3940. var table intelligenceDashboard = table.new(
  3941. f_dashboardPosition(dashboardPosition),
  3942. 2,
  3943. 29,
  3944. border_width = 1
  3945. )
  3946.  
  3947. if barstate.islast
  3948. if showIntelligenceDashboard
  3949. table.clear(intelligenceDashboard, 0, 0, 1, 28)
  3950. color headerBg = color.new(color.rgb(25, 25, 35), 5)
  3951. color labelBg = color.new(color.rgb(40, 40, 50), 15)
  3952. color verdictBg = color.new(color.rgb(20, 20, 30), 0)
  3953. color actionLabelBg = color.new(color.rgb(20, 20, 30), 0)
  3954. string marketTF = syminfo.ticker + " • " + timeframe.period
  3955. string txtSize = f_dashboardTextSize(dashboardTextSize)
  3956.  
  3957. table.cell(intelligenceDashboard, 0, 0, "ASH CRT INTELLIGENCE", bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  3958. table.cell(intelligenceDashboard, 1, 0, marketTF, bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  3959.  
  3960. table.cell(intelligenceDashboard, 0, 1, "TRADE STATUS", bgcolor = actionLabelBg, text_color = color.white, text_size = txtSize)
  3961. table.cell(intelligenceDashboard, 1, 1, displayTradeStatus, bgcolor = f_tradeStatusColor(displayTradeStatus, displayExecutionDirection), text_color = color.white, text_size = txtSize)
  3962.  
  3963. table.cell(intelligenceDashboard, 0, 2, "HTF STORY", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3964. table.cell(intelligenceDashboard, 1, 2, dashboardHTFStory, bgcolor = displayExecutionDirection == 1 ? color.new(color.green, 72) : displayExecutionDirection == -1 ? color.new(color.red, 72) : f_stateColor(dashboardCRTState), text_color = color.white, text_size = txtSize)
  3965.  
  3966. table.cell(intelligenceDashboard, 0, 3, "NEXT TF", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3967. table.cell(intelligenceDashboard, 1, 3, dashboardNextTF, bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  3968.  
  3969. table.cell(intelligenceDashboard, 0, 4, "HUNT", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3970. table.cell(intelligenceDashboard, 1, 4, dashboardHunt, bgcolor = displayExecutionDirection == 1 ? color.new(color.green, 72) : displayExecutionDirection == -1 ? color.new(color.red, 72) : headerBg, text_color = color.white, text_size = txtSize)
  3971.  
  3972. table.cell(intelligenceDashboard, 0, 5, "EXECUTION", bgcolor = actionLabelBg, text_color = color.white, text_size = txtSize)
  3973. table.cell(intelligenceDashboard, 1, 5, dashboardExecutionState, bgcolor = dashboardExecutionStateColor, text_color = color.white, text_size = txtSize)
  3974.  
  3975. table.cell(intelligenceDashboard, 0, 6, "EXECUTION BIAS", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3976. table.cell(intelligenceDashboard, 1, 6, displayExecutionBias, bgcolor = displayExecutionDirection == 1 ? color.new(color.green, 72) : displayExecutionDirection == -1 ? color.new(color.red, 72) : color.new(color.gray, 82), text_color = color.white, text_size = txtSize)
  3977.  
  3978. table.cell(intelligenceDashboard, 0, 7, "ENTRY CONDITION", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3979. table.cell(intelligenceDashboard, 1, 7, displayEntryCondition, bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  3980.  
  3981. table.cell(intelligenceDashboard, 0, 8, "RISK STATE", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3982. table.cell(intelligenceDashboard, 1, 8, displayRiskState, bgcolor = dashboardStandDownDisplay ? color.new(color.orange, 72) : executionChildMode and inheritedTargetReachedRaw ? color.new(color.green, 72) : executionChildMode and inheritedInvalidRaw ? color.new(color.red, 72) : tradeInvalid ? color.new(color.red, 72) : tradeTargetReached ? color.new(color.green, 72) : headerBg, text_color = color.white, text_size = txtSize)
  3983.  
  3984. table.cell(intelligenceDashboard, 0, 9, "SETUP AGE", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3985. table.cell(intelligenceDashboard, 1, 9, displaySetupAge, bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  3986.  
  3987. table.cell(intelligenceDashboard, 0, 10, parentStandDownDisplay ? "LOCAL CRT (INFO)" : executionChildMode ? "LOCAL CRT" : "CRT STATE", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3988. table.cell(intelligenceDashboard, 1, 10, executionChildMode ? dashboardLocalCRT : dashboardCRTState, bgcolor = f_stateColor(executionChildMode ? dashboardLocalImplication : dashboardCRTState), text_color = color.white, text_size = txtSize)
  3989.  
  3990. table.cell(intelligenceDashboard, 0, 11, "GRADE / SCORE", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3991. table.cell(intelligenceDashboard, 1, 11, dashboardGrade + " • " + str.tostring(latestCRTIntelligenceScore) + "/10", bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  3992.  
  3993. table.cell(intelligenceDashboard, 0, 12, "HTF CONTEXT", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3994. table.cell(intelligenceDashboard, 1, 12, dashboardHTF, bgcolor = f_stateColor(dashboardHTF), text_color = color.white, text_size = txtSize)
  3995.  
  3996. table.cell(intelligenceDashboard, 0, 13, "KEY LEVEL / POI", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  3997. table.cell(intelligenceDashboard, 1, 13, dashboardPOI, bgcolor = f_stateColor(dashboardPOI), text_color = color.white, text_size = txtSize)
  3998.  
  3999. table.cell(intelligenceDashboard, 0, 14, "LIQUIDITY PURGE", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4000. table.cell(intelligenceDashboard, 1, 14, dashboardPurge, bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  4001.  
  4002. table.cell(intelligenceDashboard, 0, 15, "SMT", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4003. table.cell(intelligenceDashboard, 1, 15, dashboardSMT, bgcolor = f_stateColor(dashboardSMT), text_color = color.white, text_size = txtSize)
  4004.  
  4005. table.cell(intelligenceDashboard, 0, 16, "NESTED CRT", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4006. table.cell(intelligenceDashboard, 1, 16, dashboardNested, bgcolor = f_stateColor(dashboardNested), text_color = color.white, text_size = txtSize)
  4007.  
  4008. table.cell(intelligenceDashboard, 0, 17, parentStandDownDisplay ? "LOCAL INFO" : htfBiasInheritanceLock ? "LOCAL IMPLICATION" : "DELIVERY", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4009. table.cell(intelligenceDashboard, 1, 17, executionChildMode ? dashboardLocalImplication : dashboardDelivery, bgcolor = f_stateColor(executionChildMode ? dashboardLocalImplication : dashboardDelivery), text_color = color.white, text_size = txtSize)
  4010.  
  4011. table.cell(intelligenceDashboard, 0, 18, dashboardObjectiveLabel, bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4012. table.cell(intelligenceDashboard, 1, 18, dashboardObjectiveDisplay, bgcolor = dashboardRoomFilterFailed ? color.new(color.orange, 62) : headerBg, text_color = color.white, text_size = txtSize)
  4013.  
  4014. table.cell(intelligenceDashboard, 0, 19, dashboardLocalTargetLabel, bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4015. table.cell(intelligenceDashboard, 1, 19, dashboardLocalTargetDisplay, bgcolor = executionChildMode ? color.new(color.gray, 76) : f_stateColor(dashboardLocalTargetDisplay), text_color = color.white, text_size = txtSize)
  4016.  
  4017. table.cell(intelligenceDashboard, 0, 20, parentStandDownDisplay ? "PARENT LOCK" : htfBiasInheritanceLock ? "HTF ALIGNMENT" : "FAILURE CONTEXT", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4018. table.cell(intelligenceDashboard, 1, 20, executionChildMode ? dashboardHTFAlignment : dashboardFailure, bgcolor = dashboardRoomFilterFailed ? color.new(color.green, 68) : f_stateColor(executionChildMode ? dashboardHTFAlignment : dashboardFailure), text_color = color.white, text_size = txtSize)
  4019.  
  4020. table.cell(intelligenceDashboard, 0, 21, dashboardDecisionLabel, bgcolor = verdictBg, text_color = color.white, text_size = txtSize)
  4021. table.cell(intelligenceDashboard, 1, 21, dashboardDecisionDisplay, bgcolor = dashboardRoomFilterFailed ? color.new(color.orange, 55) : verdictBg, text_color = color.white, text_size = txtSize)
  4022.  
  4023. table.cell(intelligenceDashboard, 0, 22, "KEY LEVEL TF", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4024. table.cell(intelligenceDashboard, 1, 22, dashboardKeyLevelTF, bgcolor = headerBg, text_color = color.white, text_size = txtSize)
  4025.  
  4026. table.cell(intelligenceDashboard, 0, 23, "KEY LEVEL ENGINE", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4027. table.cell(intelligenceDashboard, 1, 23, latestKeyLevelType != 0 ? "TYPE CONFIRMED" : "NONE", bgcolor = latestKeyLevelType != 0 ? color.new(color.green, 72) : color.new(color.gray, 82), text_color = color.white, text_size = txtSize)
  4028.  
  4029. table.cell(intelligenceDashboard, 0, 24, "NARRATIVE ENGINE", bgcolor = actionLabelBg, text_color = color.white, text_size = txtSize)
  4030. table.cell(intelligenceDashboard, 1, 24, dashboardNarrativeState, bgcolor = str.contains(dashboardNarrativeState, "REJECTED") ? color.new(color.red, 58) : str.contains(dashboardNarrativeState, "CANDIDATE") ? color.new(color.orange, 58) : str.contains(dashboardNarrativeState, "RE-ARMED") or str.contains(dashboardNarrativeState, "ARMED") ? color.new(color.green, 65) : str.contains(dashboardNarrativeState, "STAND DOWN") ? color.new(color.orange, 65) : color.new(color.gray, 78), text_color = color.white, text_size = txtSize)
  4031.  
  4032. table.cell(intelligenceDashboard, 0, 25, "NARRATIVE MEMORY", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4033. table.cell(intelligenceDashboard, 1, 25, dashboardNarrativeMemory, bgcolor = str.contains(dashboardNarrativeMemory, "REJECTED") ? color.new(color.red, 58) : str.contains(dashboardNarrativeMemory, "CANDIDATE") ? color.new(color.orange, 58) : str.contains(dashboardNarrativeMemory, "FRESH") ? color.new(color.green, 58) : str.contains(dashboardNarrativeMemory, "RESET") ? color.new(color.orange, 65) : color.new(color.gray, 78), text_color = color.white, text_size = txtSize)
  4034.  
  4035. table.cell(intelligenceDashboard, 0, 26, "FRESH VALIDATION", bgcolor = actionLabelBg, text_color = color.white, text_size = txtSize)
  4036. table.cell(intelligenceDashboard, 1, 26, dashboardFreshValidation, bgcolor = str.contains(dashboardFreshValidation, "CONFIRMED") ? color.new(color.green, 58) : str.contains(dashboardFreshValidation, "REJECTED") ? color.new(color.red, 58) : str.contains(dashboardFreshValidation, "VALIDATING") ? color.new(color.orange, 62) : color.new(color.gray, 78), text_color = color.white, text_size = txtSize)
  4037.  
  4038. table.cell(intelligenceDashboard, 0, 27, "NARRATIVE DELIVERY", bgcolor = actionLabelBg, text_color = color.white, text_size = txtSize)
  4039. table.cell(intelligenceDashboard, 1, 27, dashboardNarrativeDelivery, bgcolor = dashboardNarrativeTrackerColor, text_color = color.white, text_size = txtSize)
  4040.  
  4041. table.cell(intelligenceDashboard, 0, 28, "NARRATIVE OBJECTIVE", bgcolor = labelBg, text_color = color.silver, text_size = txtSize)
  4042. table.cell(intelligenceDashboard, 1, 28, dashboardNarrativeObjective, bgcolor = dashboardNarrativeTrackerColor, text_color = color.white, text_size = txtSize)
  4043. else
  4044. table.clear(intelligenceDashboard, 0, 0, 1, 28)
  4045.  
  4046. //======================================================================
  4047. // 15. ALERTS
  4048. //======================================================================
  4049. bool narrativeRearmSignal =
  4050. executionChildMode ? inheritedNarrativeRearmedRaw : localNarrativeRearmed
  4051.  
  4052. //----------------------------------------------------------------------
  4053. // v20.9.3.2 Forward-Test Runtime Alert Engine.
  4054. // These alert() calls do not consume plot slots. They are deliberately
  4055. // transition-based and fire once per confirmed bar. In TradingView, create
  4056. // one alert and select: "Any alert() function call".
  4057. //----------------------------------------------------------------------
  4058. int forwardAlertParentID = executionChildMode ? inheritedQualifiedNarrativeIDRaw : latestQualifiedNarrativeID
  4059. int forwardAlertDirection =
  4060. executionChildMode ?
  4061. (inheritedFreshDirectionRaw != 0 ? inheritedFreshDirectionRaw : inheritedHTFDirection) :
  4062. latestNarrativeDirection
  4063. string forwardAlertDirectionText = forwardAlertDirection == 1 ? "BULLISH" : forwardAlertDirection == -1 ? "BEARISH" : "NEUTRAL"
  4064. string forwardAlertParentTF = executionChildMode ? inheritanceParentTF : timeframe.period
  4065. float forwardAlertObjective = executionChildMode ? inheritedNarrativeObjectiveRaw : activeDrawTarget
  4066. string forwardAlertObjectiveText = na(forwardAlertObjective) ? "N/A" : str.tostring(forwardAlertObjective, format.mintick)
  4067. string forwardAlertPrefix = "Ash CRT v20.9.3.2 | " + syminfo.ticker + " | Chart " + timeframe.period + " | Parent " + forwardAlertParentTF + " | "
  4068.  
  4069. bool forwardParentConfirmedEvent =
  4070. executionChildMode ?
  4071. inheritedFreshValidationConfirmed and (
  4072. not inheritedFreshValidationConfirmed[1] or
  4073. inheritedQualifiedNarrativeIDRaw != inheritedQualifiedNarrativeIDRaw[1]
  4074. ) :
  4075. freshValidationConfirmed and (
  4076. not freshValidationConfirmed[1] or
  4077. latestQualifiedNarrativeID != latestQualifiedNarrativeID[1]
  4078. )
  4079.  
  4080. bool forwardExecutionArmedEvent = executionAuthorizationState == 2 and executionAuthorizationState[1] != 2
  4081. bool forwardEntryConfirmedEvent = executionAuthorizationState == 3 and executionAuthorizationState[1] != 3
  4082. bool forwardDeliveryNoReentryEvent = executionAuthorizationState == 4 and executionAuthorizationState[1] != 4
  4083.  
  4084. bool forwardParentObjectiveCompletedEvent =
  4085. executionChildMode ?
  4086. inheritedNarrativeTrackerStateRaw == 5 and inheritedNarrativeTrackerStateRaw[1] != 5 :
  4087. narrativeTrackerState == 5 and narrativeTrackerState[1] != 5
  4088.  
  4089. bool forwardParentRejectedEvent =
  4090. executionChildMode ?
  4091. inheritedFreshValidationRejected and not inheritedFreshValidationRejected[1] :
  4092. freshValidationRejected and not freshValidationRejected[1]
  4093.  
  4094. bool forwardParentInvalidatedEvent =
  4095. executionChildMode ?
  4096. inheritedInvalidRaw and not inheritedInvalidRaw[1] :
  4097. tradeInvalid and not tradeInvalid[1]
  4098.  
  4099. bool forwardParentExpiredEvent =
  4100. executionChildMode ?
  4101. inheritedExpiredRaw and not inheritedExpiredRaw[1] :
  4102. tradeExpired and not tradeExpired[1]
  4103.  
  4104. bool forwardNoChaseEvent = executionAuthorizationNoChase and not executionAuthorizationNoChase[1]
  4105.  
  4106. if enableForwardTestAlerts and barstate.isconfirmed
  4107. if alertParentConfirmed and forwardParentConfirmedEvent
  4108. alert(
  4109. forwardAlertPrefix + "PARENT CONFIRMED 4/4 | " + forwardAlertDirectionText + " | Narrative #" + f_narrativeIDText(forwardAlertParentID) + " | Objective " + forwardAlertObjectiveText,
  4110. alert.freq_once_per_bar_close
  4111. )
  4112.  
  4113. if alertExecutionArmed and forwardExecutionArmedEvent
  4114. alert(
  4115. forwardAlertPrefix + "EXECUTION ARMED | " + forwardAlertDirectionText + " | Narrative #" + f_narrativeIDText(executionAuthorizationParentID) + " | Wait aligned qualified LTF CRT",
  4116. alert.freq_once_per_bar_close
  4117. )
  4118.  
  4119. if alertEntryConfirmed and forwardEntryConfirmedEvent
  4120. alert(
  4121. forwardAlertPrefix + "ENTRY CONFIRMED | " + forwardAlertDirectionText + " | Narrative #" + f_narrativeIDText(executionAuthorizationParentID) + " | One-shot authorization consumed | Entry " + str.tostring(executionAuthorizationEntryPrice, format.mintick),
  4122. alert.freq_once_per_bar_close
  4123. )
  4124.  
  4125. if alertDeliveryNoReentry and forwardDeliveryNoReentryEvent
  4126. alert(
  4127. forwardAlertPrefix + "DELIVERY IN PROGRESS | Narrative #" + f_narrativeIDText(executionAuthorizationParentID) + " | NO RE-ENTRY | Manage the authorized execution",
  4128. alert.freq_once_per_bar_close
  4129. )
  4130.  
  4131. if alertParentObjectiveCompleted and forwardParentObjectiveCompletedEvent
  4132. alert(
  4133. forwardAlertPrefix + "PARENT OBJECTIVE COMPLETED | Narrative #" + f_narrativeIDText(forwardAlertParentID) + " | STAND DOWN | No chase",
  4134. alert.freq_once_per_bar_close
  4135. )
  4136.  
  4137. if alertParentRejectedInvalidated and forwardParentRejectedEvent
  4138. alert(
  4139. forwardAlertPrefix + "PARENT CANDIDATE PERMANENTLY REJECTED | Narrative #" + f_narrativeIDText(forwardAlertParentID) + " | Wait newer parent CRT",
  4140. alert.freq_once_per_bar_close
  4141. )
  4142.  
  4143. if alertParentRejectedInvalidated and forwardParentInvalidatedEvent
  4144. alert(
  4145. forwardAlertPrefix + "PARENT NARRATIVE INVALIDATED | Narrative #" + f_narrativeIDText(forwardAlertParentID) + " | Execution locked",
  4146. alert.freq_once_per_bar_close
  4147. )
  4148.  
  4149. if alertParentRejectedInvalidated and forwardParentExpiredEvent
  4150. alert(
  4151. forwardAlertPrefix + "PARENT NARRATIVE EXPIRED | Narrative #" + f_narrativeIDText(forwardAlertParentID) + " | Wait new parent CRT",
  4152. alert.freq_once_per_bar_close
  4153. )
  4154.  
  4155. if alertNoChase and forwardNoChaseEvent
  4156. alert(
  4157. forwardAlertPrefix + "NO CHASE | Parent objective too near or no valid room | Narrative #" + f_narrativeIDText(executionAuthorizationParentID) + " | Objective " + forwardAlertObjectiveText,
  4158. alert.freq_once_per_bar_close
  4159. )
  4160.  
  4161. alertcondition(
  4162. narrativeTrackerState == 3 and narrativeTrackerState[1] != 3,
  4163. "Ash CRT — Narrative Delivery Active",
  4164. "The validated CRT narrative has started directional delivery on {{ticker}} {{interval}}."
  4165. )
  4166.  
  4167. alertcondition(
  4168. narrativeTrackerState == 4 and narrativeTrackerState[1] != 4,
  4169. "Ash CRT — Narrative Objective Near",
  4170. "The active CRT narrative is approaching its selected objective on {{ticker}} {{interval}}."
  4171. )
  4172.  
  4173. alertcondition(
  4174. narrativeTrackerState == 5 and narrativeTrackerState[1] != 5,
  4175. "Ash CRT — Narrative Objective Completed",
  4176. "The active CRT narrative completed its selected objective on {{ticker}} {{interval}}. Stand down and avoid chasing."
  4177. )
  4178.  
  4179. alertcondition(
  4180. narrativeTrackerState == 8 and narrativeTrackerState[1] != 8,
  4181. "Ash CRT — Narrative Permanently Rejected",
  4182. "The fresh CRT narrative failed validation and its narrative ID is permanently rejected on {{ticker}} {{interval}}."
  4183. )
  4184.  
  4185. alertcondition(
  4186. narrativeRearmSignal and not narrativeRearmSignal[1],
  4187. "Ash CRT — Narrative Re-Armed",
  4188. "A genuinely newer qualified parent CRT created a fresh bullish or bearish narrative on {{ticker}} {{interval}}. Execution is re-armed; wait for aligned lower-timeframe confirmation."
  4189. )
  4190.  
  4191. alertcondition(
  4192. tradeReady and not tradeReady[1],
  4193. "Ash CRT — Trade Status READY",
  4194. "CRT Trade Readiness Engine changed to READY on {{ticker}} {{interval}}. Confirm execution and risk before entry."
  4195. )
  4196.  
  4197. alertcondition(
  4198. tradeReversalActive and not tradeReversalActive[1],
  4199. "Ash CRT — Reversal Context Active",
  4200. "CRT failure created an opposite-direction reversal context on {{ticker}} {{interval}}. Wait for aligned lower-timeframe CRT confirmation."
  4201. )
  4202.  
  4203. alertcondition(
  4204. tradeInvalid and not tradeInvalid[1],
  4205. "Ash CRT — Trade Status INVALID",
  4206. "The tracked CRT trade state changed to INVALID on {{ticker}} {{interval}}."
  4207. )
  4208.  
  4209. alertcondition(
  4210. tradeTargetReached and not tradeTargetReached[1],
  4211. "Ash CRT — Trade Status TARGET REACHED",
  4212. "The tracked CRT trade state changed to TARGET REACHED on {{ticker}} {{interval}}. Avoid chasing completed delivery."
  4213. )
  4214.  
  4215. alertcondition(
  4216. gradeAPlusCRT,
  4217. "Ash CRT — A+ Intelligence Grade",
  4218. "A+ CRT intelligence grade confirmed on {{ticker}} {{interval}}."
  4219. )
  4220.  
  4221. alertcondition(
  4222. gradeACRT,
  4223. "Ash CRT — A Intelligence Grade",
  4224. "A-grade CRT intelligence setup confirmed on {{ticker}} {{interval}}."
  4225. )
  4226.  
  4227.  
  4228. alertcondition(
  4229. newDrawTargetReached,
  4230. "Ash CRT — Draw on Liquidity Target Reached",
  4231. "The active CRT reached its selected draw-on-liquidity target on {{ticker}} {{interval}}."
  4232. )
  4233.  
  4234.  
  4235. alertcondition(
  4236. failedCRTEvent and failedCRTReversalDirection == 1,
  4237. "Ash CRT — Failed Bearish CRT / Bullish Reversal Context",
  4238. "A qualified bearish CRT failed through its manipulated-side boundary. Bullish reversal context detected on {{ticker}} {{interval}}."
  4239. )
  4240.  
  4241. alertcondition(
  4242. failedCRTEvent and failedCRTReversalDirection == -1,
  4243. "Ash CRT — Failed Bullish CRT / Bearish Reversal Context",
  4244. "A qualified bullish CRT failed through its manipulated-side boundary. Bearish reversal context detected on {{ticker}} {{interval}}."
  4245. )
  4246.  
  4247.  
  4248. alertcondition(
  4249. meaningfulDeliveryContext and not meaningfulDeliveryContext[1],
  4250. "Ash CRT — Displacement Delivery Confirmed",
  4251. "Post-manipulation displacement and directional delivery confirmed on {{ticker}} {{interval}}."
  4252. )
  4253.  
  4254.  
  4255. alertcondition(
  4256. qualifiedCRT and meaningfulLiquidityPurge,
  4257. "Ash CRT — Qualified CRT with Meaningful Liquidity Purge",
  4258. "Qualified CRT also purged meaningful external liquidity on {{ticker}} {{interval}}."
  4259. )
  4260.  
  4261. alertcondition(
  4262. qualifiedCRT and meaningfulNestedContext,
  4263. "Ash CRT — Qualified CRT Nested in Active HTF Context",
  4264. "Qualified CRT is nested or aligned inside an active parent-timeframe CRT context on {{ticker}} {{interval}}."
  4265. )
  4266.  
  4267.  
  4268. alertcondition(
  4269. bullishManipulation,
  4270. "Ash CRT — Qualified Bullish Manipulation",
  4271. "Qualified bullish CRT manipulation confirmed on {{ticker}} {{interval}}. Range low was purged."
  4272. )
  4273.  
  4274. alertcondition(
  4275. bearishManipulation,
  4276. "Ash CRT — Qualified Bearish Manipulation",
  4277. "Qualified bearish CRT manipulation confirmed on {{ticker}} {{interval}}. Range high was purged."
  4278. )
  4279.  
  4280.  
  4281. alertcondition(
  4282. crtTargetReached and not crtTargetReached[1],
  4283. "Ash CRT — Opposite-Side Target Reached",
  4284. "The active CRT reached its opposite-side Range target on {{ticker}} {{interval}}."
  4285. )
  4286.  
  4287. alertcondition(
  4288. crtInvalidated and not crtInvalidated[1],
  4289. "Ash CRT — Active CRT Invalidated",
  4290. "The active CRT was invalidated through its manipulated-side boundary on {{ticker}} {{interval}}."
  4291. )
  4292.  
  4293. alertcondition(
  4294. crtExpired and not crtExpired[1],
  4295. "Ash CRT — Active CRT Expired",
  4296. "The active CRT expired before opposite-side delivery on {{ticker}} {{interval}}."
  4297. )
  4298.  
  4299.  
  4300. alertcondition(
  4301. bullishSMT and not bullishSMT[1],
  4302. "Ash CRT — Bullish SMT Detected",
  4303. "Bullish SMT divergence detected between {{ticker}} and the configured comparison market on {{interval}}."
  4304. )
  4305.  
  4306. alertcondition(
  4307. bearishSMT and not bearishSMT[1],
  4308. "Ash CRT — Bearish SMT Detected",
  4309. "Bearish SMT divergence detected between {{ticker}} and the configured comparison market on {{interval}}."
  4310. )
  4311.  
  4312. alertcondition(
  4313. bullishLTFStructure,
  4314. "Ash CRT — Bullish LTF Structure Confirmed",
  4315. "Bullish lower-timeframe CRT structure confirmed inside the qualified HTF Distribution window on {{ticker}} {{interval}}."
  4316. )
  4317.  
  4318. alertcondition(
  4319. bearishLTFStructure,
  4320. "Ash CRT — Bearish LTF Structure Confirmed",
  4321. "Bearish lower-timeframe CRT structure confirmed inside the qualified HTF Distribution window on {{ticker}} {{interval}}."
  4322. )
  4323.  
  4324.  
Add Comment
Please, Sign In to add comment