Indicator · Pine Script v5 · On the chart

Level Theory + Vector Candles

by g-moe· code credited to goodgains

This overlay indicator draws rounded psychological price levels and optional PVSRA vector candle colors on the price chart.

View on GitHub

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code136
Settings29inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago27 May 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

136 lines of Pine Script v5 from Tradingview/level-theory-vector-candles.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

level-theory-vector-candles.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © goodgains


//@version=5
indicator("Level Theory + Vector Candles",overlay = true, max_lines_count = 500)

// @keywords: level-theory, vector-candles, pvsra, psychological-levels, quarter-levels, half-levels, whole-levels, rounding-value, volume-vector, bar-coloring, vector-zones, zone-boxes, volume-spike, traders-reality, baseline-levels, support-resistance, high-volume-bar, vector-detection, level-lines, price-rounding

import TradersReality/Traders_Reality_Lib/1 as trLib

// --LEVEL SETTINGS-- //
rounding_value = input.float(100, title = 'Rounding Value ', group = 'Level Settings', inline = '1')
use_qtr_levels = input.bool(true, title = 'Quarter Levels', group = 'Level Settings', inline = '3')
css_qtr = input.color(color.new(color.yellow,70), title = '', group = 'Level Settings', inline = '3')
style_qtr = input.string('Solid', title = '', options = ['Solid', 'Dotted', 'Dashed'], group = 'Level Settings', inline = '3')
width_qtr = input.int(1, title = '', minval = 1, maxval = 5, group = 'Level Settings', inline = '3')

use_half_levels = input.bool(true, title = 'Half Levels   ', group = 'Level Settings', inline = '4')
css_half = input.color(color.new(color.yellow,35), title = '', group = 'Level Settings', inline = '4')
style_half = input.string('Solid', title = '', options = ['Solid', 'Dotted', 'Dashed'], group = 'Level Settings', inline = '4')
width_half = input.int(1, title = '', minval = 1, maxval = 5, group = 'Level Settings', inline = '4')

use_whole_levels = input.bool(true, title = 'Whole Levels ', group = 'Level Settings', inline = '5')
css_whole = input.color(color.yellow, title = '', group = 'Level Settings', inline = '5')
style_whole = input.string('Solid', title = '', options = ['Solid', 'Dotted', 'Dashed'], group = 'Level Settings', inline = '5')
width_whole = input.int(1, title = '', minval = 1, maxval = 5, group = 'Level Settings', inline = '5')
// --LEVEL SETTINGS-- //


// --VECTOR SETTINGS-- //
color redVectorColor = input.color(title='Vector: Red', group='PVSRA Colors', defval=color.red, inline='vectors')
color greenVectorColor = input.color(title='Green', group='PVSRA Colors', defval=color.lime, inline='vectors')
color violetVectorColor = input.color(title='Violet', group='PVSRA Colors', defval=color.fuchsia, inline='vectors')
color blueVectorColor = input.color(title='Blue', group='PVSRA Colors', defval=color.blue, inline='vectors', tooltip='Bull bars are green and bear bars are red when the bar is with volume >= 200% of the average volume of the 10 previous bars, or bars where the product of candle spread x candle volume is >= the highest for the 10 previous bars.\n Bull bars are blue and bear are violet when the bar is with with volume >= 150% of the average volume of the 10 previous bars.')
color regularCandleUpColor = input.color(title='Regular: Up Candle', group='PVSRA Colors', defval=#999999, inline='nonVectors')
color regularCandleDownColor = input.color(title='Down Candle', group='PVSRA Colors', defval=#4d4d4d, inline='nonVectors', tooltip='Bull bars are light gray and bear are dark gray when none of the red/green/blue/violet vector conditions are met.')
bool setcandlecolors = input.bool(false, title='Set PVSRA candle colors?', group='PVSRA Colors', inline='setCandle')

int zonesMax = input.int(500, 'Maximum zones to draw', group='Vector Candle Zones')
string zoneType = input.string(group='Vector Candle Zones', defval='Body only', title='Zone top/bottom is defined with: ', options=['Body only', 'Body with wicks'])
string zoneUpdateType = input.string(group='Vector Candle Zones', defval='Body with wicks', title='Zones are cleared using candle: ', options=['Body only', 'Body with wicks'])
int borderWidth = input.int(0, 'Zone border width', group='Vector Candle Zones')
bool colorOverride = input.bool(true, 'Override color?' , group='Vector Candle Zones', inline="vcz1")
color zoneColor = input.color(title='Color', group='Vector Candle Zones', defval=color.rgb(255, 230, 75, 90), inline="vcz1", tooltip='the vector candle zones color to use if you dont not want to use the PVSRA Candle Colors.')
int transperancy = input.int(90, 'Zone Transperancy', minval = 0, maxval = 100, group='Vector Candle Zones', tooltip='If the vector candle zones color is not overriden, then we want to set the transparancy of the vector candle colors as defined by the PBSRA candle colors. This setting only affects the candle zone colors not the candle colors themselves.')

bool overrideSym = input.bool(group='PVSRA Override', title='Override chart symbol?', defval=false, inline='pvsra')
string pvsraSym = input.string(group='PVSRA Override', title='', defval='INDEX:BTCUSD', tooltip='You can use INDEX:BTCUSD or you can combine multiple feeds, for example BINANCE:BTCUSDT+COINBASE:BTCUSD. Note that adding too many will slow things down.', inline='pvsra')





// --FUNCTION TO DRAW PSYCH THEORY LINES -- //
f_draw_lines(lines, baseline, half_value, qtr_value) =>
    
    // clear
    array_size = array.size(lines) 
    if array_size > 0
        for i = 0 to array_size- 1
            line.delete(array.get(lines, i))
        array.clear(lines)


    for i = 0 to 10

        if use_whole_levels
            array.unshift(lines, line.new(x1 = bar_index, y1 = baseline+(i*rounding_value), x2 = bar_index + 1, y2 = baseline+(i*rounding_value), extend = extend.both, width = width_whole,
             style = (style_whole == 'Solid' ? line.style_solid : style_whole == 'Dashed' ? line.style_dashed : style_whole == 'Dotted' ? line.style_dotted : line.style_solid), color = css_whole))
            array.unshift(lines, line.new(x1 = bar_index, y1 = baseline-(i*rounding_value), x2 = bar_index + 1, y2 = baseline-(i*rounding_value), extend = extend.both,  width = width_whole,
             style = (style_whole == 'Solid' ? line.style_solid : style_whole == 'Dashed' ? line.style_dashed : style_whole == 'Dotted' ? line.style_dotted : line.style_solid), color = css_whole))

        if use_half_levels
            array.unshift(lines, line.new(x1 = bar_index, y1 = baseline+half_value+(i*(rounding_value)), x2 = bar_index + 1, y2 = baseline+half_value+(i*(rounding_value)), extend = extend.both, width = width_half,
             style = (style_half == 'Solid' ? line.style_solid : style_half == 'Dashed' ? line.style_dashed : style_half == 'Dotted' ? line.style_dotted : line.style_solid), color = css_half))
            array.unshift(lines, line.new(x1 = bar_index, y1 = baseline-half_value-(i*(rounding_value)), x2 = bar_index + 1, y2 = baseline-half_value-(i*(rounding_value)), extend = extend.both, width = width_half,
             style = (style_half == 'Solid' ? line.style_solid : style_half == 'Dashed' ? line.style_dashed : style_half == 'Dotted' ? line.style_dotted : line.style_solid), color = css_half))

        if use_qtr_levels
            array.unshift(lines, line.new(x1 = bar_index, y1 = baseline+qtr_value+(i*(half_value)), x2 = bar_index + 1, y2 = baseline+qtr_value+(i*(half_value)), extend = extend.both, width = width_qtr,
             style = (style_qtr == 'Solid' ? line.style_solid : style_qtr == 'Dashed' ? line.style_dashed : style_qtr == 'Dotted' ? line.style_dotted : line.style_solid), color = css_qtr))
            array.unshift(lines, line.new(x1 = bar_index, y1 = baseline-qtr_value-(i*(half_value)), x2 = bar_index + 1, y2 = baseline-qtr_value-(i*(half_value)), extend = extend.both, width = width_qtr,
             style = (style_qtr == 'Solid' ? line.style_solid : style_qtr == 'Dashed' ? line.style_dashed : style_qtr == 'Dotted' ? line.style_dotted : line.style_solid), color = css_qtr))
// --FUNCTION TO DRAW PSYCH THEORY LINES -- //



// --DRAW LINES-- //
var lines = array.new_line(100, na)
baseline = math.round( close / rounding_value) * rounding_value
whole_value = rounding_value
half_value = (rounding_value/2)
qtr_value = (half_value/2)
min_increment = use_qtr_levels ? qtr_value : use_half_levels ? half_value : use_whole_levels ? whole_value : na
if barstate.islast or baseline != baseline[1]
    f_draw_lines(lines, baseline, half_value, qtr_value) 
// --DRAW LINES-- //




// --VECTOR CANDLES-- //
pvsraVolume(overrideSymbolX, pvsraSymbolX, tickerIdX) =>
    request.security(overrideSymbolX ? pvsraSymbolX : tickerIdX, '', volume, barmerge.gaps_off, barmerge.lookahead_off)
pvsraHigh(overrideSymbolX, pvsraSymbolX, tickerIdX) =>
    request.security(overrideSymbolX ? pvsraSymbolX : tickerIdX, '', high, barmerge.gaps_off, barmerge.lookahead_off)
pvsraLow(overrideSymbolX, pvsraSymbolX, tickerIdX) =>
    request.security(overrideSymbolX ? pvsraSymbolX : tickerIdX, '', low, barmerge.gaps_off, barmerge.lookahead_off)
pvsraClose(overrideSymbolX, pvsraSymbolX, tickerIdX) =>
    request.security(overrideSymbolX ? pvsraSymbolX : tickerIdX, '', close, barmerge.gaps_off, barmerge.lookahead_off)
pvsraOpen(overrideSymbolX, pvsraSymbolX, tickerIdX) =>
    request.security(overrideSymbolX ? pvsraSymbolX : tickerIdX, '', open, barmerge.gaps_off, barmerge.lookahead_off)


pvsraVolume = pvsraVolume(overrideSym, pvsraSym, syminfo.tickerid)
pvsraHigh = pvsraHigh(overrideSym, pvsraSym, syminfo.tickerid)
pvsraLow = pvsraLow(overrideSym, pvsraSym, syminfo.tickerid)
pvsraClose = pvsraClose(overrideSym, pvsraSym, syminfo.tickerid)
pvsraOpen = pvsraOpen(overrideSym, pvsraSym, syminfo.tickerid)
[pvsraColor, alertFlag, averageVolume, volumeSpread, highestVolumeSpread] = trLib.calcPvsra(pvsraVolume, pvsraHigh, pvsraLow, pvsraClose, pvsraOpen, redVectorColor, greenVectorColor, violetVectorColor, blueVectorColor, regularCandleDownColor, regularCandleUpColor)


var zoneBoxesAbove = array.new_box()
var zoneBoxesBelow = array.new_box()


barcolor(setcandlecolors ? pvsraColor : na)
pvsra = trLib.getPvsraFlagByColor(pvsraColor, redVectorColor, greenVectorColor, violetVectorColor, blueVectorColor, regularCandleUpColor)
trLib.updateZones(pvsra, 0, zoneBoxesBelow, zonesMax, pvsraHigh, pvsraLow, pvsraOpen, pvsraClose, transperancy, zoneUpdateType, zoneColor, zoneType, borderWidth, colorOverride, redVectorColor, greenVectorColor, violetVectorColor, blueVectorColor)
trLib.updateZones(pvsra, 1, zoneBoxesAbove, zonesMax, pvsraHigh, pvsraLow, pvsraOpen, pvsraClose, transperancy, zoneUpdateType, zoneColor, zoneType, borderWidth, colorOverride, redVectorColor, greenVectorColor, violetVectorColor, blueVectorColor)
trLib.cleanarr(zoneBoxesAbove)
trLib.cleanarr(zoneBoxesBelow)


// --VECTOR CANDLES-- //

Overview

Level Theory + Vector Candles plots quarter, half, and whole levels from a user-set rounding value, with separate color, line style, and width for each. Vector coloring marks high-volume or high spread-times-volume bars against the prior ten bars, and regular bars use gray when those conditions fail. It can draw vector zones from candle bodies, clear them with wick-inclusive candles, and optionally source volume from another symbol. Candle coloring is off by default.

Details

Published by

g-moe on GitHub

Code credit

goodgains, as written in the script's header

Draws

On the price chart

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Rounding Value float100rounding_value
Quarter Levelsbooltrueuse_qtr_levels
css_qtrcolorcolor.new(color.yellow,70)css_qtr
style_qtrstringSolidstyle_qtr
width_qtrint1width_qtr
Half Levels   booltrueuse_half_levels
css_halfcolorcolor.new(color.yellow,35)css_half
style_halfstringSolidstyle_half
width_halfint1width_half
Whole Levels booltrueuse_whole_levels
css_wholecolorcolor.yellowcss_whole
style_wholestringSolidstyle_whole
Show all 29 settings
SettingTypeDefaultVariable
width_wholeint1width_whole
Vector: Redcolorcolor.redredVectorColor
Greencolorcolor.limegreenVectorColor
Violetcolorcolor.fuchsiavioletVectorColor
Bluecolorcolor.blueblueVectorColor
Regular: Up Candlecolor#999999regularCandleUpColor
Down Candlecolor#4d4d4dregularCandleDownColor
Set PVSRA candle colors?boolfalsesetcandlecolors
Maximum zones to drawint500zonesMax
Zone top/bottom is defined with: stringBody onlyzoneType
Zones are cleared using candle: stringBody with wickszoneUpdateType
Zone border widthint0borderWidth
Override color?booltruecolorOverride
Colorcolorcolor.rgb(255, 230, 75, 90)zoneColor
Zone Transperancyint90transperancy
Override chart symbol?boolfalseoverrideSym
pvsraSymstringINDEX:BTCUSDpvsraSym
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

2 stars

This overlay approximates order-book liquidity from intrabar OHLCV buckets because true depth-of-market data is unavailable. It paints a decaying volume heatmap around price and labels absorption, exhaustion, rejection, and momentum when wick, body, delta, and

Indicator v6 VolumeSupport & resistance
Updated 4 months ago · None stated GitHub repository of Bookmap Liquidity Mapper [TReset]
2 stars

Ghost Zone v9 GTI Signals v18 is an overlay technical indicator designed to replicate Ghost Trade Pro methodology. It calculates anchored Supertrend channels, previous weekly close levels, fair value gaps, and volume profile high-volume nodes. The script evalu

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 6 months ago · None stated GitHub repository of Ghost Zone v9 GTI Signals v18

HTF Candles & Pivots

by itmakesyousick
2 stars

This overlay indicator draws higher-timeframe candles as boxes on the price chart, with a selectable timeframe, candle thickness, wicks, history, vertical divisions, and optional fill for negative candles. It can plot pivot levels, including an optional centra

Indicator v5 Candlestick patternsSupport & resistance
Updated 3 years ago · None stated GitHub repository of HTF Candles & Pivots
2 stars

The LSD-15 indicator detects liquidity sweeps on 15-minute crypto charts by identifying price movements that exceed a threshold from swing highs and lows. It plots swing high and low lines on the price chart and highlights sweep candles in color. Multiple conf

Indicator v5 ScalpingSupport & resistance Repaints
Updated 7 months ago · None stated GitHub repository of LSD-15 Liquidity Sweep Detector

This indicator provides four selectable analytical datasets directly on the price chart: quartile volume analysis, volume aggregation bars, US range bars, and gap tracking. Depending on the active mode, it plots synthetic candle structures, historical congesti

Indicator v5 VolumeSupport & resistance Repaints
Updated 8 months ago · None stated GitHub repository of Quartile Volume, Volume Aggregation, US Range Bars, Gaps
1 stars

This indicator plots bullish and bearish order-block boxes on the price chart. It marks the prior candle when the current bar engulfs it and volume exceeds a twenty-bar average times a multiplier, then stores the zone in a matrix. Volume threshold and box colo

Indicator v5 SMC / ICT / price actionSupport & resistance Repaints
Updated 6 months ago · MIT GitHub repository of Order Blocks Matrix - Castle Trade

More Support & resistance scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers