//@version=6 indicator("Time Cycles — AMD", "Cycles", overlay = true, max_boxes_count = 500) // ============================================================================= // Alleen de tijdcycli. Niets anders. // // Vier groepen van het 02:30-15:59 raster, elk als een box OM de kaarsen: // top = hoogste high, bodem = laagste low van die cyclus, levend meegroeiend. // // Sessions 4/dag Asia . Londen . NY AM . NY PM // 90M 9/dag elk de A, M of D van zijn sessie // 30M 27/dag elk de A, M of D van zijn 90M // 10M 81/dag elk de A, M of D van zijn 30M // // WAAROM ER GEEN AMD-KEUZE IS. Een cyclus wordt niet in een AMD gesplitst -- // hij IS er een. 30M nummer twee is de M van zijn 90M. De ladder is // zelf-gelijkvormig, dus de kleur volgt uit de positie in de ouder. // // DE GRENS. Een cyclus eindigt op zijn eigen laatste minuut, niet op de eerste // van de volgende. De rechterrand wordt daarom een kaars teruggetrimd. Het gat // van een bar dat dat oplevert is de juiste grens: de openingskaars hoort bij // de nieuwe cyclus, niet bij de oude. // // DE BOXEN NESTELEN. 10M in 30M in 90M in sessie. Ze vechten dus niet, ze // omlijsten elkaar -- mits je niet alle vier een vulling geeft. // // Asia loopt 18:00-02:29 en valt buiten het raster, dus die krijgt een eigen // kleur in plaats van een rol die hij niet heeft. 16:00-17:59 is leeg met opzet. // // BUDGET. Niets wordt verwijderd, dus TradingView gooit de oudste box weg bij // 500. Alle vier aan = 121 boxen per dag, ongeveer vier dagen historie. Zet // 10M uit en het worden er 40 per dag, dus ruwweg twaalf dagen. // // Alle tijden New York, zomer/wintertijd automatisch. // ============================================================================= tz = "America/New_York" f_style(string s) => s == "Solid" ? line.style_solid : s == "Dashed" ? line.style_dashed : line.style_dotted // ───────────────────────────── Sessions ───────────────────────────── gS = "Sessions · 4 per dag" sOn = input.bool(true, "Tonen", group = gS) sA = input.color(#2962ff, "A", inline = "sc", group = gS) sM = input.color(#f23645, "M", inline = "sc", group = gS) sD = input.color(#089981, "D", inline = "sc", group = gS) sX = input.color(color.gray, "Asia", inline = "sc", group = gS, tooltip = "Asia loopt 18:00-02:29 en valt buiten het 02:30-15:59 raster, dus heeft geen A-, M- of D-rol. Londen, NY AM en NY PM zijn samen de A, M en D van de handelsdag.") sTr = input.int(100, "Vulling", minval = 0, maxval = 100, group = gS, tooltip = "100 = alleen kader. Voor een box van acht uur breed is dat meestal wat je wilt.") sBd = input.bool(true, "Rand", inline = "sb", group = gS) sBs = input.string("Solid", "", options = ["Solid", "Dashed", "Dotted"], inline = "sb", group = gS) sBw = input.int(1, "dikte", minval = 1, maxval = 4, inline = "sb", group = gS) // ───────────────────────────── 90M ───────────────────────────── g9 = "90M · 9 per dag" nOn = input.bool(true, "Tonen", group = g9) nA = input.color(#2962ff, "A", inline = "nc", group = g9) nM = input.color(#f23645, "M", inline = "nc", group = g9) nD = input.color(#089981, "D", inline = "nc", group = g9) nTr = input.int(88, "Vulling", minval = 0, maxval = 100, group = g9) nBd = input.bool(true, "Rand", inline = "nb", group = g9) nBs = input.string("Dotted", "", options = ["Solid", "Dashed", "Dotted"], inline = "nb", group = g9) nBw = input.int(1, "dikte", minval = 1, maxval = 4, inline = "nb", group = g9) // ───────────────────────────── 30M ───────────────────────────── g3 = "30M · 27 per dag" tOn = input.bool(true, "Tonen", group = g3) tA = input.color(#2962ff, "A", inline = "tc", group = g3) tM = input.color(#f23645, "M", inline = "tc", group = g3) tD = input.color(#089981, "D", inline = "tc", group = g3) tTr = input.int(100, "Vulling", minval = 0, maxval = 100, group = g3) tBd = input.bool(true, "Rand", inline = "tb", group = g3) tBs = input.string("Dotted", "", options = ["Solid", "Dashed", "Dotted"], inline = "tb", group = g3) tBw = input.int(1, "dikte", minval = 1, maxval = 4, inline = "tb", group = g3) // ───────────────────────────── 10M ───────────────────────────── g1 = "10M · 81 per dag" oOn = input.bool(true, "Tonen", group = g1, tooltip = "81 boxen per dag. Met deze groep aan is de zichtbare historie ongeveer vier dagen; uit wordt het er twaalf. Vraagt een timeframe dat op 10 minuten deelt.") oA = input.color(#2962ff, "A", inline = "oc", group = g1) oM = input.color(#f23645, "M", inline = "oc", group = g1) oD = input.color(#089981, "D", inline = "oc", group = g1) oTr = input.int(100, "Vulling", minval = 0, maxval = 100, group = g1) oBd = input.bool(true, "Rand", inline = "ob", group = g1) oBs = input.string("Dotted", "", options = ["Solid", "Dashed", "Dotted"], inline = "ob", group = g1) oBw = input.int(1, "dikte", minval = 1, maxval = 4, inline = "ob", group = g1) // ───────────────────────────── tijd ───────────────────────────── tfSec = timeframe.in_seconds() // Een boxgrens moet op een barrand vallen, anders wordt de cyclus midden in een // kaars afgesneden. Stil afgevangen: de groep tekent dan gewoon niet. ali10 = timeframe.isintraday and 600 % tfSec == 0 ali30 = timeframe.isintraday and 1800 % tfSec == 0 mnts = hour(time, tz) * 60 + minute(time, tz) // Het raster: 02:30 (minuut 150) tot en met 15:59 (minuut 959). inRas = mnts >= 150 and mnts <= 959 // Sleutels. 0 betekent "hier geen cyclus", dan sluit de box. int() om de deling // omdat Pine een float teruggeeft en een int-parameter die niet aanneemt. k10 = inRas ? int((mnts - 150) / 10) + 1 : 0 k30 = inRas ? int((mnts - 150) / 30) + 1 : 0 k90 = inRas ? int((mnts - 150) / 90) + 1 : 0 // Sessies tellen vanaf 18:00 in plaats van vanaf middernacht, want Asia gaat // over middernacht heen en moet onderweg dezelfde sleutel houden -- een sleutel // die om 00:00 verspringt zou Asia doormidden knippen. tmins = mnts >= 1080 ? mnts - 1080 : mnts + 360 kSes = tmins <= 509 ? 1 : tmins <= 779 ? 2 : tmins <= 1049 ? 3 : tmins <= 1319 ? 4 : 0 // ───────────────────────────── kleur ───────────────────────────── f_amd(int idx, color ca, color cm, color cd) => int m = idx % 3 m == 0 ? ca : m == 1 ? cm : cd // Rand volgt de vulling maar 45 stappen steviger, zodat een groep op vulling 100 // nog steeds een zichtbare lijn houdt. Rand uit = volledig doorzichtig. f_border(color base, int tr, bool on) => on ? color.new(base, math.max(0, tr - 45)) : color.new(color.white, 100) // ───────────────────────────── de box ───────────────────────────── // Een functie met `var` krijgt in Pine eigen state per AANROEPPLEK. Daarom staan // de vier groepen hieronder los uitgeschreven in plaats van in een lus -- een // lus zou een enkele plek zijn en dan deelden alle vier de groepen een box. f_cycleBox(bool active, int key, color bg, color bcol, int bw, string bstyle) => var bool inC = false var int prevK = 0 var box curB = na // GEEN OFFSET BIJ DEZE TWEE. Met xloc.bar_time landt een tijdstempel op de // MIDDENLIJN van zijn kaars, niet op de linkerrand -- dat geeft het gewenste // gat van precies een kaars al vanzelf. liveR = time + timeframe.in_seconds() * 1000 gapR = nz(time[1], time) if inC and active and key == prevK box.set_top(curB, math.max(box.get_top(curB), high)) box.set_bottom(curB, math.min(box.get_bottom(curB), low)) box.set_right(curB, liveR) else if inC box.set_right(curB, gapR) // laatste kaars terugtrimmen -> gat curB := na inC := false if active and not inC curB := box.new(time, high, liveR, low, xloc = xloc.bar_time, bgcolor = bg, border_color = bcol, border_width = bw, border_style = bstyle) prevK := key inC := true int(na) // CE10235 guard. Niet weghalen. // ───────────────────────────── tekenen ───────────────────────────── // Buitenste groep eerst, zodat de kleinere boxen er bovenop komen te liggen. kS = (sOn and ali30) ? kSes : 0 cS = kS == 1 ? sX : kS >= 2 ? f_amd(kS - 2, sA, sM, sD) : color.gray f_cycleBox(kS != 0, kS, color.new(cS, sTr), f_border(cS, sTr, sBd), sBw, f_style(sBs)) k9 = (nOn and ali30) ? k90 : 0 c9 = k9 != 0 ? f_amd(k9 - 1, nA, nM, nD) : color.gray f_cycleBox(k9 != 0, k9, color.new(c9, nTr), f_border(c9, nTr, nBd), nBw, f_style(nBs)) k3 = (tOn and ali30) ? k30 : 0 c3 = k3 != 0 ? f_amd(k3 - 1, tA, tM, tD) : color.gray f_cycleBox(k3 != 0, k3, color.new(c3, tTr), f_border(c3, tTr, tBd), tBw, f_style(tBs)) k1 = (oOn and ali10) ? k10 : 0 c1 = k1 != 0 ? f_amd(k1 - 1, oA, oM, oD) : color.gray f_cycleBox(k1 != 0, k1, color.new(c1, oTr), f_border(c1, oTr, oBd), oBw, f_style(oBs))