//@version=6 indicator("Key Opens + AMD", shorttitle="Opens/AMD", overlay=true, max_boxes_count=500, max_lines_count=500, max_labels_count=500) // ═══════════════════════════════════════════════════════════════════════════ // The key opens, and the AMD phases that hang off them. // // ── WHAT AN AMD ACTUALLY IS ON HIS GRID ──────────────────────────────────── // On the reference chart A runs 10:00-10:30, M 10:30-11:00, D 11:00-11:30. // Those are exactly the three 30M cycles that make up AM3 (10:00-11:29) in his // own ladder. So an AMD is not a new idea: it is a 90M cycle read as its three // 30M children, and the same construction works off any anchor. // // Which is why the phase length is one setting and not three. Change it to 10 // and you get the 30M cycle read as its three 10M children — the ladder is // self-similar and so is this. // // ── WHY THE OPENS NEED THEIR OWN ANCHORS ─────────────────────────────────── // His 90M grid is anchored on 02:30, so 07:00 and 10:00 fall on it but 03:00, // 09:30, 12:00 and 14:00 do not. Those get their own AMD, anchored on the open // itself rather than on the grid. Both kinds are listed below; nothing is // derived from the other. // // ── THE BOX IS THE PHASE'S RANGE, NOT A BACKGROUND ───────────────────────── // On the reference chart each block is drawn to the high and low of its own // phase, which is what makes the accumulation visibly narrow and the // manipulation visibly tall. A full-height background would lose exactly that. // The cost: a box can only be as tall as the bars it has seen, so it grows // while its phase runs and is finished when the phase ends. The vertical // dividers DO project forward, because their times are known in advance. // // NOT A SIGNAL. This labels the clock, nothing else. // ═══════════════════════════════════════════════════════════════════════════ NY = "America/New_York" // ───────────────────────── the opens ───────────────────────── // Six slots, pre-filled with his: 03:00, 07:00, 09:30, 10:00, 12:00, 14:00. // Each can draw a divider, the open price, and an AMD. gK = "Key opens (New York)" o1On = input.bool(true, "", inline="k1", group=gK) o1Tm = input.string("03:00", "", inline="k1", group=gK) o1Am = input.bool(false, "AMD", inline="k1", group=gK) o2On = input.bool(true, "", inline="k2", group=gK) o2Tm = input.string("07:00", "", inline="k2", group=gK) o2Am = input.bool(false, "AMD", inline="k2", group=gK) o3On = input.bool(true, "", inline="k3", group=gK) o3Tm = input.string("09:30", "", inline="k3", group=gK) o3Am = input.bool(false, "AMD", inline="k3", group=gK) o4On = input.bool(true, "", inline="k4", group=gK) o4Tm = input.string("10:00", "", inline="k4", group=gK) o4Am = input.bool(true, "AMD", inline="k4", group=gK) o5On = input.bool(true, "", inline="k5", group=gK) o5Tm = input.string("12:00", "", inline="k5", group=gK) o5Am = input.bool(false, "AMD", inline="k5", group=gK) o6On = input.bool(true, "", inline="k6", group=gK) o6Tm = input.string("14:00", "", inline="k6", group=gK) o6Am = input.bool(false, "AMD", inline="k6", group=gK) phaseMin = input.int(30, "AMD phase length (minutes)", minval=1, maxval=240, group=gK, tooltip="Three phases of this length. 30 gives the 90-minute AMD on the reference chart. 10 gives the 30M cycle read as its three 10M children — the same shape one rung down the ladder.") // AMD only where you ask for it, because two AMD's that overlap are unreadable: // 09:30 and 10:00 are half an hour apart and a 30-minute phase makes each of // them ninety minutes long. Default is 10:00 only, as on the reference chart. // ───────────────────────── what to draw ───────────────────────── gD = "Draw" showDiv = input.bool(true, "Vertical divider at each open", group=gD) showOpen = input.bool(true, "Horizontal line at the open price", group=gD, tooltip="Appears when that open happens — a price cannot be drawn before it exists. The dividers do run ahead, because their times are known.") showPD = input.bool(true, "Previous day high and low", group=gD, tooltip="The reference chart calls the previous day low its draw on liquidity. Shown as two lines with labels.") extendBars = input.int(40, "Extend lines right (bars)", minval=0, maxval=500, group=gD) daysAhead = input.int(1, "Days drawn", minval=1, maxval=3, group=gD) // ───────────────────────── look ───────────────────────── gS = "Look" colA = input.color(color.new(color.green, 88), "A — accumulation", group=gS) colM = input.color(color.new(color.red, 88), "M — manipulation", group=gS) colD = input.color(color.new(color.blue, 88), "D — distribution", group=gS) colDiv = input.color(color.new(color.gray, 55), "Divider", group=gS) colOpen = input.color(color.new(color.red, 30), "Open price", group=gS) colPD = input.color(color.new(color.black, 10), "PDH / PDL", group=gS) showLet = input.bool(true, "A / M / D letters", group=gS) letSzIn = input.string("large", " └ size", options=["small","normal","large","huge"], group=gS) letSz = letSzIn == "small" ? size.small : letSzIn == "normal" ? size.normal : letSzIn == "large" ? size.large : size.huge // ═══════════════════════ helpers ═══════════════════════ // "09:30" -> 570. Written out rather than parsed loosely, because a silent // failure here would put every block an hour off and still look plausible. f_min(string s) => int colon = str.pos(s, ":") int h = na(colon) ? 0 : math.round(str.tonumber(str.substring(s, 0, colon))) int m = na(colon) ? 0 : math.round(str.tonumber(str.substring(s, colon + 1))) h * 60 + m f_hhmm(int m) => int h = m / 60 int mm = m % 60 (h < 10 ? "0" : "") + str.tostring(h) + ":" + (mm < 10 ? "0" : "") + str.tostring(mm) barMs = timeframe.in_seconds() * 1000 int l_min = hour(time, NY) * 60 + minute(time, NY) // ═══════════════════════ the open prices ═══════════════════════ // One slot per open. Reset at the start of each trading day so yesterday's // open never leaks into today's line. var array opPrice = array.new_float(6, na) var array opTime = array.new_int(6, na) var array opLine = array.new_line(6, na) var array