//@version=6 // KONATUS Horizon 0.1.0 — Kutty Stauder. Macro price-trend research edition. // Native TradingView compilation, chart behavior and alerts remain unverified. // Bias is descriptive, not an entry, exit, protective stop or profit forecast. indicator("KONATUS Horizon · Macro Regime 0.1.0", shorttitle="Horizon", overlay=false, max_bars_back=600, dynamic_requests=true) string mode = input.string("Balanced", "Confirmation", options=["Balanced", "Patient"], tooltip="Balanced: 2 daily observations; Patient: 3 and higher entry thresholds. Both use identical holding rules. Neither preset is performance-optimized.") bool showComponents = input.bool(false, "Show the three components", group="Display") bool showBackground = input.bool(true, "Shade the active bias", group="Display") bool showMarks = input.bool(true, "Mark bias changes", group="Display") bool showPanel = input.bool(true, "Show explanation panel", group="Display") color longColor = input.color(#36C9A0, "Long bias", group="Colors") color shortColor = input.color(#F0717C, "Short bias", group="Colors") color waitColor = input.color(#C3AC78, "Neutral / transition", group="Colors") f_valid() => not na(open) and not na(high) and not na(low) and not na(close) and high >= math.max(open, close) and low <= math.min(open, close) and high >= low f_efficiency(int length, bool valid, int count) => float step = valid and count > 1 ? math.abs(close - close[1]) : 0.0 float path = math.sum(step, length) count > length and path > 0 ? math.max(-1.0, math.min(1.0, (close - close[length]) / path)) : 0.0 f_weekly() => bool valid = f_valid() var int count = 0 count := valid ? count + 1 : 0 float backbone = 0.5 * f_efficiency(13, valid, count) + 0.5 * f_efficiency(26, valid, count) bool ready = count >= 27 // Every requested field is shifted; no developing weekly vote. [backbone[1], ready[1], time_close[1]] f_daily() => // Executed inside the DAILY request, so counters cannot accelerate on 5m. // Weekly evidence here is what was confirmed at this daily bar's OPEN. [weekly, weeklyReady, weeklyClosed] = request.security(syminfo.tickerid, "1W", f_weekly(), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on) bool valid = f_valid() bool longGap = not na(time_close[1]) and time - time_close[1] > 7 * 86400000 var int count = 0 count := not valid ? 0 : longGap ? 1 : count + 1 float tr = valid ? (count > 1 ? math.max(high - low, math.max(math.abs(high - close[1]), math.abs(low - close[1]))) : high - low) : na float scale = ta.sma(tr, 20) float pressure = 0.20 * f_efficiency(21, valid, count) + 0.35 * f_efficiency(63, valid, count) + 0.45 * f_efficiency(126, valid, count) float priorHigh = ta.highest(high[1], 63) float priorLow = ta.lowest(low[1], 63) float structure = priorHigh > priorLow ? math.max(-1.0, math.min(1.0, 2.0 * (close - priorLow) / (priorHigh - priorLow) - 1.0)) : 0.0 float balance = ta.median(close[1], 21) float extension = scale > 0 ? (close - balance) / scale : 0.0 float impulse = close - close[5] bool freshWeek = not na(weeklyClosed) and time >= weeklyClosed and time - weeklyClosed <= 21 * 86400000 bool ready = count >= 127 and weeklyReady and freshWeek and not na(scale) and not na(balance) and not na(priorHigh) and not na(priorLow) bool shock = valid and count >= 21 and not na(scale[1]) and tr > 3.0 * scale[1] float td = mode == "Patient" ? 0.30 : 0.20 float tw = mode == "Patient" ? 0.25 : 0.15 float ts = mode == "Patient" ? 0.30 : 0.20 int required = mode == "Patient" ? 3 : 2 var int bias = 0 var int candidate = 0 var int run = 0 var int pause = 0 bool invalidated = false if not ready bias := 0 candidate := 0 run := 0 pause := 0 else pause := shock ? 3 : math.max(0, pause - 1) if pause > 0 bias := 0 candidate := 0 run := 0 else invalidated := bias != 0 and (bias * pressure <= -0.05 or bias * weekly <= 0 or bias * structure <= -0.20) if invalidated bias := 0 candidate := 0 run := 0 else if bias == 0 int next = pressure >= td and weekly >= tw and structure >= ts ? 1 : pressure <= -td and weekly <= -tw and structure <= -ts ? -1 : 0 run := next != 0 ? (next == candidate ? run + 1 : 1) : 0 candidate := next if run >= required bias := candidate candidate := 0 run := 0 // 0 transition, 1 trend, 2 pullback, 3 stretched, 4 conflict, 5 pause, 6 unavailable. int condition = not ready ? 6 : pause > 0 ? 5 : bias != 0 ? (bias * extension > 3 ? 3 : bias * impulse < 0 ? 2 : 1) : invalidated ? 0 : pressure * weekly < 0 ? 4 : 0 float score = ready ? 100.0 * (0.45 * pressure + 0.35 * weekly + 0.20 * structure) : na // A daily result is published in the NEXT daily interval on every chart. [bias[1], condition[1], score[1], pressure[1], weekly[1], structure[1], ready[1], time_close[1], weeklyClosed[1], run[1], invalidated[1]] f_condition(int value) => switch value 1 => "TREND" 2 => "PULLBACK" 3 => "STRETCHED" 4 => "CONFLICT" 5 => "SHOCK PAUSE" 6 => "UNAVAILABLE" => "TRANSITION" f_reason(int value, bool invalidated) => switch value 1 => "Macro hold rules intact" 2 => "5-day counter-move; macro bias still intact" 3 => "Extended from median; bias is not an entry" 4 => "Daily and weekly evidence oppose" 5 => "Range shock; wait for fresh confirmation" 6 => "Need 127 daily and 27 weekly valid bars" => invalidated ? "Prior bias broke; fresh confirmation required" : "Waiting for agreement and daily confirmation" bool supported = chart.is_standard and ((timeframe.isminutes and timeframe.multiplier < 1440) or (timeframe.isdaily and timeframe.multiplier == 1)) int sourceBias = 0 int condition = 6 float score = na float dailyPressure = na float weeklyBackbone = na float structure = na bool sourceReady = false int dailyClosed = na int weeklyClosed = na int confirmationRun = 0 bool invalidated = false if supported [b, c, s, d, w, r, ready, dc, wc, n, invalid] = request.security(syminfo.tickerid, "1D", f_daily(), gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on) sourceBias := b condition := c score := s dailyPressure := d weeklyBackbone := w structure := r sourceReady := ready dailyClosed := dc weeklyClosed := wc confirmationRun := n invalidated := invalid bool fresh = not na(dailyClosed) and time >= dailyClosed and time - dailyClosed <= 7 * 86400000 bool available = supported and sourceReady and fresh int bias = available ? sourceBias : 0 color biasColor = bias == 1 ? longColor : bias == -1 ? shortColor : waitColor string title = not supported ? "USE STANDARD 1m–1D" : not available ? "UNAVAILABLE" : bias == 1 ? "LONG BIAS" : bias == -1 ? "SHORT BIAS" : "NEUTRAL" string detail = not supported ? "Standard minute candles or exactly 1D" : not fresh and not na(dailyClosed) ? "Daily data stale; no active bias" : f_reason(available ? condition : 6, invalidated) hline(0, "Balance", color=color.new(color.gray, 55)) hline(100, "Index ceiling", color=color.new(color.gray, 85)) hline(-100, "Index floor", color=color.new(color.gray, 85)) plot(available ? score : na, "Macro evidence index (not probability)", color=biasColor, linewidth=3, style=plot.style_stepline) plot(showComponents and available ? 100 * dailyPressure : na, "Daily pressure", color=#5AA8D1) plot(showComponents and available ? 100 * weeklyBackbone : na, "Weekly backbone", color=#B19AE1) plot(showComponents and available ? 100 * structure : na, "Range structure", color=#C4A46B) bgcolor(showBackground and available ? color.new(biasColor, bias == 0 ? 96 : 91) : na) bool newSnapshot = not na(dailyClosed[1]) and dailyClosed != dailyClosed[1] bool changed = available and available[1] and newSnapshot and sourceBias != sourceBias[1] bool newLong = changed and sourceBias == 1 bool newShort = changed and sourceBias == -1 bool cleared = changed and sourceBias == 0 plotshape(showMarks and newLong, title="New long bias", style=shape.triangleup, location=location.bottom, color=longColor, size=size.tiny, text="L") plotshape(showMarks and newShort, title="New short bias", style=shape.triangledown, location=location.top, color=shortColor, size=size.tiny, text="S") plotshape(showMarks and cleared, title="Bias cleared", style=shape.xcross, location=location.bottom, color=waitColor, size=size.tiny) alertcondition(newLong and barstate.isconfirmed, "New macro long bias", "KONATUS Horizon: new confirmed macro LONG bias on {{ticker}}. Review condition; this is not an entry order.") alertcondition(newShort and barstate.isconfirmed, "New macro short bias", "KONATUS Horizon: new confirmed macro SHORT bias on {{ticker}}. Review condition; this is not an entry order.") alertcondition(cleared and barstate.isconfirmed, "Macro bias cleared", "KONATUS Horizon: prior bias cleared to NEUTRAL on {{ticker}}.") alertcondition(changed and barstate.isconfirmed, "Any macro bias change", "KONATUS Horizon: confirmed macro bias changed on {{ticker}}. Review the Horizon panel.") var table panel = table.new(position.top_right, 2, 9, bgcolor=color.new(#101D29, 6), border_width=1, border_color=color.new(color.gray, 70)) if barstate.islast if showPanel table.cell(panel, 0, 0, "KONATUS HORIZON", text_color=color.white, text_size=size.small) table.cell(panel, 1, 0, title, text_color=available ? biasColor : color.gray, text_size=size.small) table.cell(panel, 0, 1, "Condition", text_color=color.silver) table.cell(panel, 1, 1, available ? f_condition(condition) : "UNAVAILABLE", text_color=color.white) table.cell(panel, 0, 2, "Why", text_color=color.silver) table.cell(panel, 1, 2, detail, text_color=color.white, text_size=size.small) table.cell(panel, 0, 3, "Daily / Weekly / Range", text_color=color.silver) table.cell(panel, 1, 3, available ? str.tostring(100*dailyPressure, "#.0") + " / " + str.tostring(100*weeklyBackbone, "#.0") + " / " + str.tostring(100*structure, "#.0") : "—", text_color=color.white) table.cell(panel, 0, 4, "Daily snapshot", text_color=color.silver) table.cell(panel, 1, 4, not na(dailyClosed) ? str.format_time(dailyClosed, "yyyy-MM-dd HH:mm", syminfo.timezone) : "—", text_color=color.white, text_size=size.small) table.cell(panel, 0, 5, "Weekly evidence closed", text_color=color.silver) table.cell(panel, 1, 5, not na(weeklyClosed) ? str.format_time(weeklyClosed, "yyyy-MM-dd", syminfo.timezone) : "—", text_color=color.white) table.cell(panel, 0, 6, "Confirmation", text_color=color.silver) table.cell(panel, 1, 6, mode + (available and bias == 0 ? " · " + str.tostring(confirmationRun) + "/" + (mode == "Patient" ? "3" : "2") : ""), text_color=color.white) table.cell(panel, 0, 7, "Timing", text_color=color.silver) table.cell(panel, 1, 7, "Previous daily close; weekly at its open", text_color=color.silver, text_size=size.small) table.cell(panel, 0, 8, "RESEARCH 0.1.0", text_color=waitColor, text_size=size.small) table.cell(panel, 1, 8, "Bias ≠ entry · Native validation pending", text_color=color.silver, text_size=size.small) else table.clear(panel, 0, 0, 1, 8)