//@version=6 // Konatus Market Anatomy 0.1.0 — experimental interpretation tool. // Copyright (c) 2026 Kutty Stauder. No profitability or causal identification claim. // Formula/verification contract: SPEC.md and docs/VERIFICATION.md. indicator("KONATUS | Market Anatomy [Research 0.1]", "K Anatomy", overlay = true, max_bars_back = 1200) // One common measurement system; horizon is always measured in chart bars. int horizon = input.int(20, "Observation horizon (bars)", minval = 5, maxval = 200, group = "Understanding") string volumeInput = input.string("Auto", "Volume meaning", options = ["Auto", "Trade units", "Tick count", "Quote value", "Off"], group = "Data", tooltip = "Auto follows feed metadata. Only declared trade units enable VWAP. Unknown volume stays unverified; tick activity is not traded quantity.") string anchorInput = input.string("Auto", "VWAP calendar anchor", options = ["Auto", "Day", "Week", "Month", "Year", "Off"], group = "Data", tooltip = "Exchange-calendar boundaries on the bars loaded in the chart. Auto: intraday/day, daily/month, weekly or monthly/year. First partial anchor is withheld. This is not a regular-session filter.") bool detailed = input.bool(false, "Detailed explanation", group = "Display") bool showPanel = input.bool(true, "Explanation panel", group = "Display") bool showEnvelope = input.bool(true, "Descriptive extension envelope", group = "Display", tooltip = "Filtered price +/- 1.5 prior mean true ranges. This is not a probability interval or a stop.") bool showVwap = input.bool(true, "Volume-weighted reference", group = "Display") bool showScenario = input.bool(true, "Frozen scenario boundary", group = "Display") bool paintBars = input.bool(false, "Color confirmed candles", group = "Display") string corner = input.string("Top right", "Panel position", options = ["Top right", "Bottom right", "Top left", "Bottom left"], group = "Display") f_number(float value) => na(value) ? "Unavailable" : str.tostring(value, "#.###") f_row(table panel, int row, string caption, string value, color tone) => table.cell(panel, 0, row, caption, text_color = color.new(chart.fg_color, 30), text_size = size.small, text_halign = text.align_left) table.cell(panel, 1, row, value, text_color = tone, text_size = size.small, text_halign = text.align_left) color upColor = color.rgb(38, 171, 145) color downColor = color.rgb(224, 102, 108) color cautionColor = color.rgb(213, 158, 66) color neutralColor = color.new(chart.fg_color, 25) bool timedChart = timeframe.isseconds or timeframe.isminutes or timeframe.isdaily or timeframe.isweekly or timeframe.ismonthly bool supported = chart.is_standard and timedChart bool validPrice = supported and not na(open) and not na(high) and not na(low) and not na(close) and low <= math.min(open, close) and high >= math.max(open, close) var int priceCount = 0 priceCount := validPrice ? priceCount + 1 : 0 bool previousValid = validPrice[1] float trueRange = validPrice ? (previousValid ? math.max(high - low, math.max(math.abs(high - close[1]), math.abs(low - close[1]))) : high - low) : na float shortRange = ta.sma(trueRange, horizon) float longRange = ta.sma(trueRange, 4 * horizon) float scale = shortRange[1] bool warm = priceCount >= 4 * horizon + 2 bool scaleKnown = warm and not na(scale) and scale > 0 // Two-pole SuperSmoother in signed price space. No log-price clipping. float decay = math.exp(-math.sqrt(2.0) * math.pi / horizon) float c2 = 2.0 * decay * math.cos(math.sqrt(2.0) * math.pi / horizon) float c3 = -decay * decay float c1 = 1.0 - c2 - c3 var float level = na float level1 = previousValid ? nz(level[1], close) : close float level2 = previousValid ? nz(level[2], level1) : close level := validPrice ? c1 * (close + (previousValid ? close[1] : close)) / 2.0 + c2 * level1 + c3 * level2 : na float velocity = scaleKnown ? (level - level1) / scale : na float acceleration = scaleKnown ? (level - 2.0 * level1 + level2) / scale : na float curvature = scaleKnown ? acceleration / math.pow(1.0 + velocity * velocity, 1.5) : na float extension = scaleKnown ? (close - level) / scale : na float distance = math.sum(math.abs(close - close[1]), horizon) float efficiency = warm ? (distance > 0 ? math.abs(close - close[horizon]) / distance : 0.0) : na float volatility = warm and longRange > 0 ? shortRange / longRange : na float shockRatio = scaleKnown ? trueRange / scale : na bool shock = scaleKnown and shockRatio >= 3.0 int direction = scaleKnown ? (velocity > 0.08 ? 1 : velocity < -0.08 ? -1 : 0) : 0 // Volume semantics remain separate from directional evidence. string volumeKind = volumeInput == "Auto" ? (syminfo.volumetype == "base" ? "Trade units" : syminfo.volumetype == "tick" ? "Tick count" : syminfo.volumetype == "quote" ? "Quote value" : "Unverified") : volumeInput bool validVolume = validPrice and not na(volume) and volume >= 0 var int volumeCount = 0 volumeCount := validVolume ? volumeCount + 1 : 0 float volumeMean = ta.sma(validVolume ? volume : na, horizon)[1] float relativeVolume = volumeInput != "Off" and volumeCount >= horizon + 1 and volumeMean > 0 ? volume / volumeMean : na string anchorTf = switch anchorInput "Day" => "1D" "Week" => "1W" "Month" => "1M" "Year" => "12M" => timeframe.isintraday ? "1D" : timeframe.isdaily ? "1M" : "12M" float chartSeconds = timedChart ? timeframe.in_seconds() : na bool anchorLonger = timedChart and timeframe.in_seconds(anchorTf) > chartSeconds bool anchorEnabled = supported and anchorInput != "Off" and volumeKind == "Trade units" and anchorLonger bool anchorChanged = timeframe.change(anchorTf) and not barstate.isfirst var bool anchorComplete = false var bool anchorPoisoned = false var float anchorWeight = 0.0 var float anchorMean = 0.0 if anchorChanged anchorComplete := true anchorPoisoned := false anchorWeight := 0.0 anchorMean := 0.0 if not validVolume anchorPoisoned := true else if volume > 0 and anchorEnabled float totalWeight = anchorWeight + volume anchorMean += volume / totalWeight * (hlc3 - anchorMean) anchorWeight := totalWeight float vwapReference = anchorEnabled and anchorComplete and not anchorPoisoned and anchorWeight > 0 ? anchorMean : na // A scenario freezes a previously observable boundary. It is not a trade ledger. float priorHigh = ta.highest(high, horizon)[1] float priorLow = ta.lowest(low, horizon)[1] var int scenario = 0 var float boundary = na bool invalidated = false int breakout = 0 if not scaleKnown scenario := 0 boundary := na else if scenario != 0 and (close - boundary) * scenario < 0 invalidated := true scenario := 0 boundary := na else if scenario == 0 if close > priorHigh scenario := 1 boundary := priorHigh breakout := 1 else if close < priorLow scenario := -1 boundary := priorLow breakout := -1 // Each message is a direct explanation of a measurement or a named hypothesis. string state = not supported ? "UNSUPPORTED CHART" : not validPrice ? "INVALID PRICE DATA" : not warm ? "BUILDING HISTORY" : not scaleKnown ? (trueRange == 0 ? "FLAT" : "SCALE UNAVAILABLE") : direction > 0 ? "UPWARD" : direction < 0 ? "DOWNWARD" : "BALANCED" string organization = not warm ? "Awaiting history" : efficiency >= 0.55 ? "Directional path" : efficiency < 0.25 ? "Backtracking path" : "Mixed path" float directionalAcceleration = acceleration * direction string pace = not scaleKnown ? "Unavailable" : direction == 0 ? "No directional pace" : directionalAcceleration > 0.015 ? "Gaining pace" : directionalAcceleration < -0.015 ? "Losing pace" : "Steady pace" string volatilityText = not warm ? "Awaiting history" : shock ? "SHOCK / " + f_number(shockRatio) + " x prior range" : na(volatility) ? "No range" : volatility > 1.3 ? "Expanding" : volatility < 0.7 ? "Contracting" : "Near longer baseline" string locationText = not scaleKnown ? "Unavailable" : (math.abs(extension) >= 1.5 ? "Extended / " : "Near reference / ") + f_number(extension) + " range units" string participation = volumeInput == "Off" ? "Off / price-only context" : not validVolume ? "Missing volume" : na(relativeVolume) ? "Baseline unavailable" : f_number(relativeVolume) + " x / " + volumeKind if timeframe.isintraday and volumeInput != "Off" participation += "\nNot time-of-day adjusted" string anchorText = anchorInput == "Off" ? "Off" : volumeKind != "Trade units" ? "Requires declared trade units" : not anchorLonger ? "Anchor must exceed chart interval" : not anchorComplete ? "First partial anchor withheld" : anchorPoisoned ? "Anchor has missing data" : anchorWeight <= 0 ? "No positive anchor volume" : (close > vwapReference ? "Above " : close < vwapReference ? "Below " : "At ") + anchorTf + " VWAP" string scenarioText = invalidated ? "Prior breakout failed" : scenario > 0 ? "Upward range breakout" : scenario < 0 ? "Downward range breakout" : "No active breakout scenario" string failureText = scenario > 0 ? "Close below " + str.tostring(boundary, format.mintick) : scenario < 0 ? "Close above " + str.tostring(boundary, format.mintick) : "No scenario boundary" string reading = not warm ? "Waiting for " + str.tostring(4 * horizon + 2) + " consecutive valid bars." : not scaleKnown ? "Normalized movement is unavailable." : shock ? "Range jumped relative to its prior baseline.\nThe previous pace may no longer describe conditions." : direction != 0 and efficiency < 0.25 ? "The smoother points one way; raw price backtracks.\nDirection and path organization conflict." : direction != 0 and math.abs(extension) >= 1.5 ? "Price is far from the smoothed reference.\nExtension alone does not imply reversal." : direction != 0 ? "The filtered path is directional.\nRead pace and participation separately." : "Directional movement is weak under this definition.\nA balanced reading does not predict a breakout." string hypothesis = not scaleKnown ? "Insufficient normalized evidence." : shock ? "Information arrival or a liquidity change are possible.\nThe chart does not identify the cause." : direction != 0 and efficiency >= 0.55 ? "Persistent execution demand is one possible explanation.\nParticipant identity and intent are unobserved." : "Two-sided trade is one possible explanation.\nOHLCV cannot identify who supplied liquidity." color stateColor = not warm or not scaleKnown ? neutralColor : direction > 0 ? upColor : direction < 0 ? downColor : neutralColor // Developing bars carry no final plot/marker. The table holds the last closed bar. bool confirmed = barstate.isconfirmed plot(confirmed and warm ? level : na, "Filtered price", color = stateColor, linewidth = 2, style = plot.style_linebr) upperPlot = plot(confirmed and scaleKnown and showEnvelope ? level + 1.5 * scale : na, "Upper descriptive envelope", color = color.new(neutralColor, 80), style = plot.style_linebr) lowerPlot = plot(confirmed and scaleKnown and showEnvelope ? level - 1.5 * scale : na, "Lower descriptive envelope", color = color.new(neutralColor, 80), style = plot.style_linebr) fill(upperPlot, lowerPlot, color = color.new(stateColor, 95), title = "Descriptive extension area") plot(confirmed and showVwap ? vwapReference : na, "Calendar VWAP", color = color.new(cautionColor, 15), style = plot.style_linebr) plot(confirmed and showScenario ? boundary : na, "Scenario boundary (not stop)", color = cautionColor, linewidth = 1, style = plot.style_circles) barcolor(paintBars and confirmed and warm ? stateColor : na) plotshape(confirmed and breakout == 1, "Upward breakout observation", shape.circle, location.belowbar, upColor, size = size.tiny) plotshape(confirmed and breakout == -1, "Downward breakout observation", shape.circle, location.abovebar, downColor, size = size.tiny) plotshape(confirmed and invalidated, "Scenario invalidated", shape.xcross, location.abovebar, cautionColor, size = size.tiny) string panelPosition = corner == "Top right" ? position.top_right : corner == "Bottom right" ? position.bottom_right : corner == "Top left" ? position.top_left : position.bottom_left var table panel = table.new(panelPosition, 2, detailed ? 18 : 12, bgcolor = color.new(chart.bg_color, 5), frame_color = color.new(chart.fg_color, 80), frame_width = 1) if barstate.islast and showPanel int snapshot = confirmed ? 0 : 1 color tone = stateColor[snapshot] string clockText = na(time_close[snapshot]) ? "No confirmed bar" : str.format_time(time_close[snapshot], "MM-dd HH:mm", syminfo.timezone) f_row(panel, 0, "KONATUS", "MARKET ANATOMY / 0.1", chart.fg_color) f_row(panel, 1, syminfo.ticker + " / " + timeframe.period, state[snapshot], tone) f_row(panel, 2, "Path / efficiency", organization[snapshot] + " / " + f_number(efficiency[snapshot]), tone) f_row(panel, 3, "Pace", pace[snapshot], tone) f_row(panel, 4, "Volatility", volatilityText[snapshot], shock[snapshot] ? cautionColor : chart.fg_color) f_row(panel, 5, "Location", locationText[snapshot], chart.fg_color) f_row(panel, 6, "Activity / rolling", participation[snapshot], chart.fg_color) f_row(panel, 7, "Anchor context", anchorText[snapshot], chart.fg_color) f_row(panel, 8, "Scenario", scenarioText[snapshot] + "\nInvalidation: " + failureText[snapshot], cautionColor) f_row(panel, 9, "Reading", reading[snapshot], chart.fg_color) if detailed f_row(panel, 10, "Possible mechanism", hypothesis[snapshot], neutralColor) f_row(panel, 11, "Velocity / acceleration", f_number(velocity[snapshot]) + " / " + f_number(acceleration[snapshot]), tone) f_row(panel, 12, "Local curvature", f_number(curvature[snapshot]) + " / defined coordinates", neutralColor) f_row(panel, 13, "Prior range scale", f_number(scale[snapshot]) + " / SMA true range", neutralColor) f_row(panel, 14, "Data meaning", volumeKind + " / " + syminfo.type, neutralColor) f_row(panel, 15, "Activity limitation", "Rolling baseline; no time-of-day adjustment.", neutralColor) f_row(panel, detailed ? 16 : 10, "Confirmed through", clockText + " / " + syminfo.timezone, neutralColor) f_row(panel, detailed ? 17 : 11, "Evidence", "Descriptive / parameters unvalidated", neutralColor) // Exports enable a native TradingView versus Python fixture comparison. plot(confirmed ? velocity : na, "Velocity", display = display.data_window) plot(confirmed ? acceleration : na, "Acceleration", display = display.data_window) plot(confirmed ? efficiency : na, "Efficiency", display = display.data_window) plot(confirmed ? extension : na, "Extension", display = display.data_window) plot(confirmed ? curvature : na, "Curvature", display = display.data_window) plot(confirmed and warm ? volatility : na, "Volatility ratio", display = display.data_window) plot(confirmed ? relativeVolume : na, "Relative activity", display = display.data_window) plot(confirmed and warm ? scale : na, "Prior scale", display = display.data_window) plot(confirmed and warm ? direction : na, "Direction", display = display.data_window) bool directionChanged = scaleKnown and scaleKnown[1] and direction != direction[1] alertcondition(confirmed and directionChanged, "Direction changed", "KONATUS {{ticker}} {{interval}}: confirmed direction changed. Read the explanation panel; this is not an entry order.") alertcondition(confirmed and shock and not shock[1], "Volatility shock", "KONATUS {{ticker}} {{interval}}: confirmed range shock relative to prior history.") alertcondition(confirmed and breakout != 0, "Range breakout observed", "KONATUS {{ticker}} {{interval}}: confirmed range breakout. A descriptive scenario boundary is now frozen.") alertcondition(confirmed and invalidated, "Scenario invalidated", "KONATUS {{ticker}} {{interval}}: a confirmed close invalidated the frozen breakout scenario.")