AshICT

Ash ICT CRT — Protocol Engine v20.9.4.0 Dashboard Archive Synchronization

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