For TradingView charts

PRISM on TradingView.

TradingView scripts cannot download data, so the PRISM Forecast indicator takes one pasted forecast code instead: copy it here or with the TradingView button on the live chart, paste it into the indicator, and the 48-hour forecast β€” the expected close path, the shaded 80% range of closes, the central scenario and the key levels of the AI briefing β€” is drawn on your chart from the forecast's anchor bar forward. Included with every plan that opens the charts, for the markets it opens.

How it works

Copy, paste, forecast.

1Copy the code

On the live forecast page click TradingView in the chart header (or pick the market below): the forecast code of that market is copied β€” about 2,000 characters, the H1 forecast of the hour. Your website login gates the code, like the chart.

2Paste it into the indicator

On TradingView open the same market, open the PRISM Forecast indicator's settings and paste the code into Forecast code.

3Read the forecast

The dashed expected path, the 80% band, the central scenario and the key levels appear from the anchor bar forward, with the end close, its 80% interval and the honest end-direction label. A new forecast is issued every hour β€” copy a new code whenever you want it; after 48 hours the indicator says forecast expired.

Your forecast code

Sign in to get your codes.

Create an account and watch the live forecast for 2 days β€” all 17 markets with the AI news briefing, ad-free β€” no card needed. After the demo your account continues on the Free plan: all 17 markets, supported by advertising.

Sign in β†’ Create a demo account β†’
Every plan that opens the charts includes the TradingView indicator for the markets it opens.
Install once

The PRISM Forecast indicator.

A Pine Script v6 indicator β€” open source, nothing to buy on TradingView. It draws only what the pasted code carries; it never connects anywhere and it never trades.

⬇ Download PRISM_Forecast.pine

Install in 4 steps:
1 Β· On TradingView open any chart and the Pine Editor (bottom panel)
2 Β· Replace the editor's content with the script (download above, or copy it from the box below)
3 Β· Add to chart β€” and Save it if you want it under Indicators β†’ My scripts
4 Β· Open the indicator's settings (gear) and paste your forecast code β€” done
Best on the H1 chart (the code is the H1 forecast); M15 draws the same points, H4 every 4th hour. The drawing is rebased to your chart's open at the anchor bar, so a broker feed that differs from the website's prices does not shift it (switch it off in the settings for the raw prices).
Show the script
//@version=6
// PRISM Forecast - draws a PRISM Forecasting 48-hour forecast on the chart from a pasted "forecast code".
// Copy the code on www.prismforecasting.com (the TradingView button on the live chart, or tradingview.php), open this
// indicator's settings and paste it into "Forecast code". The code is one line:
//   PRISM1|SYMBOL|anchor_unix|decimals|base|p_up_end|candles|S|R|model
// candles = h:o/h/l/c/s/lo/hi per H1 candle (h = hours after the anchor; integer price offsets from base in 10^-decimals
// units: expected open/high/low/close, central-scenario close, 80% range of the simulated closes). See the README.
// Draws: the expected (median) close path (dashed), the 80% range of closes (filled band), the central-scenario path,
// the AI briefing's key levels, labels for the expected end close, the 80% interval and the end direction ("no clear
// edge" within 6 points of 50%, the website's rule), "forecast expired" when the code is older than 48 h.
// Pine Script cannot fetch URLs: paste a fresh code when a new forecast is issued (every hour on the website).
indicator("PRISM Forecast", "PRISM", overlay = true, max_lines_count = 50, max_labels_count = 50, max_polylines_count = 10)

// ---------------------------------------------------------------------------------------------------------- inputs
string code     = input.text_area("", "Forecast code", tooltip = "Paste the code copied from www.prismforecasting.com (TradingView button on the chart). One forecast = one code; copy a new one after the next hourly issue.")
bool   showExp  = input.bool(true, "Expected (median) close path", group = "Draw")
bool   showBand = input.bool(true, "80% range of closes (filled band)", group = "Draw")
bool   showScen = input.bool(true, "Central scenario path", group = "Draw")
bool   showLvls = input.bool(true, "Key levels (AI briefing)", group = "Draw")
bool   showLbls = input.bool(true, "Labels", group = "Draw")
bool   rebase   = input.bool(true, "Rebase to this chart's open at the anchor bar", group = "Prices", tooltip = "With this on, every forecast price is scaled by (this chart's open at the anchor bar / the forecast's anchor open) so feed differences do not shift the drawing. Off = raw website prices.")
color  cExp     = input.color(#6366f1, "Expected close", group = "Colours")
color  cBandFill= input.color(color.new(#6366f1, 86), "80% band fill", group = "Colours")
color  cBandEdge= input.color(color.new(#6366f1, 60), "80% band edge", group = "Colours")
color  cScen    = input.color(#f59e0b, "Central scenario", group = "Colours")
color  cSup     = input.color(#10b981, "Support", group = "Colours")
color  cRes     = input.color(#ef4444, "Resistance", group = "Colours")
color  cLabelBg = input.color(color.new(#1e2537, 10), "Label background", group = "Colours")
color  cLabelTx = input.color(#ffffff, "Label text", group = "Colours")

// ------------------------------------------------------------------------------------------- parsed state (once)
var bool         ok       = false
var string       status   = "Paste a PRISM forecast code into the indicator settings (Forecast code)."
var string       sym      = ""
var int          anchorMs = 0
var float        scale    = 1.0
var float        base     = 0.0
var float        pUp      = na
var string       modelTag = ""
var array<int>   H  = array.new<int>()
var array<float> EO = array.new<float>()
var array<float> EH = array.new<float>()
var array<float> EL = array.new<float>()
var array<float> EC = array.new<float>()
var array<float> SC = array.new<float>()
var array<float> LO = array.new<float>()
var array<float> HI = array.new<float>()
var array<float> SUP = array.new<float>()
var array<float> RES = array.new<float>()

// an offset field -> price (na for an empty field)
toPrice(string s, float b, float sc) =>
    float o = str.tonumber(s)
    na(o) ? na : (b + o) / sc

if barstate.isfirst
    string c = str.replace_all(str.replace_all(str.replace_all(code, "\n", ""), "\r", ""), " ", "")
    array<string> f = str.split(c, "|")
    if str.length(c) == 0
        status := "Paste a PRISM forecast code into the indicator settings (Forecast code)."
    else if array.size(f) < 10 or array.get(f, 0) != "PRISM1"
        status := "This is not a PRISM1 forecast code - copy it again from www.prismforecasting.com."
    else
        float an = str.tonumber(array.get(f, 2))
        float dc = str.tonumber(array.get(f, 3))
        float bs = str.tonumber(array.get(f, 4))
        if na(an) or na(dc) or na(bs) or bs <= 0
            status := "The forecast code is damaged (anchor / decimals / base) - copy it again."
        else
            sym      := array.get(f, 1)
            anchorMs := int(an) * 1000
            scale    := math.pow(10, dc)
            base     := bs
            pUp      := str.tonumber(array.get(f, 5))
            modelTag := array.get(f, 9)
            array<string> cs = str.split(array.get(f, 6), ";")
            for s in cs
                array<string> hv = str.split(s, ":")
                if array.size(hv) == 2
                    float hh = str.tonumber(array.get(hv, 0))
                    array<string> v = str.split(array.get(hv, 1), "/")
                    if not na(hh) and array.size(v) == 7
                        array.push(H,  int(hh))
                        array.push(EO, toPrice(array.get(v, 0), base, scale))
                        array.push(EH, toPrice(array.get(v, 1), base, scale))
                        array.push(EL, toPrice(array.get(v, 2), base, scale))
                        array.push(EC, toPrice(array.get(v, 3), base, scale))
                        array.push(SC, toPrice(array.get(v, 4), base, scale))
                        array.push(LO, toPrice(array.get(v, 5), base, scale))
                        array.push(HI, toPrice(array.get(v, 6), base, scale))
            for s in str.split(array.get(f, 7), ",")
                float p = toPrice(s, base, scale)
                if not na(p)
                    array.push(SUP, p)
            for s in str.split(array.get(f, 8), ",")
                float p = toPrice(s, base, scale)
                if not na(p)
                    array.push(RES, p)
            if array.size(H) == 0
                status := "The forecast code carries no candles - copy it again."
            else
                ok := true
                status := ""

// -------------------------------------------------------------------------- the chart's price at the anchor (rebase)
var float anchorOpenChart = na
var bool  anchorExact     = false
int tfSec = timeframe.in_seconds()
int tfMs  = tfSec * 1000
if ok and not anchorExact
    if time == anchorMs
        anchorOpenChart := open
        anchorExact     := true
    else if time <= anchorMs and anchorMs < time + tfMs
        anchorOpenChart := open

// ------------------------------------------------------------------------------------------------------- drawing
var array<line>  LINES  = array.new<line>()
var array<label> LABELS = array.new<label>()
var polyline pExp  = na
var polyline pScen = na
var polyline pBand = na
var bool drawn = false

fmtPx(float p) =>
    str.tostring(math.round_to_mintick(p), format.mintick)

if ok and barstate.islast and (not drawn or barstate.isnew)
    drawn := true
    // ---- clear the previous drawing
    for l in LINES
        line.delete(l)
    array.clear(LINES)
    for lb in LABELS
        label.delete(lb)
    array.clear(LABELS)
    if not na(pExp)
        polyline.delete(pExp)
    if not na(pScen)
        polyline.delete(pScen)
    if not na(pBand)
        polyline.delete(pBand)
    pExp  := na
    pScen := na
    pBand := na

    // ---- the price factor (rebase) and the time step the chart can show
    float basePx = base / scale
    float k = rebase and not na(anchorOpenChart) and anchorOpenChart > 0 and basePx > 0 ? anchorOpenChart / basePx : 1.0
    int   stepH = tfSec > 3600 ? math.max(1, math.round(tfSec / 3600.0)) : 1   // H4: every 4th hour, D1: every 24th
    int   endMs = anchorMs + 48 * 3600000
    bool  expired = timenow > endMs
    // objects may not lie more than ~500 bars right of the last bar: on M1 / M5 the 48 hours do not fit - say so
    int   maxFutureMs = last_bar_time + 480 * tfMs
    bool  tooFine = anchorMs + 47 * 3600000 > maxFutureMs

    int n = array.size(H)
    array<chart.point> ptsExp  = array.new<chart.point>()
    array<chart.point> ptsScen = array.new<chart.point>()
    array<chart.point> ptsHi   = array.new<chart.point>()
    array<chart.point> ptsLo   = array.new<chart.point>()
    float lastC = na
    float lastLo = na
    float lastHi = na
    int   lastT = anchorMs
    float minLo = na
    float maxHi = na
    for i = 0 to n - 1
        int  hh = array.get(H, i)
        int  t  = anchorMs + hh * 3600000
        bool keep = (hh % stepH == 0) or i == n - 1
        if keep and t <= maxFutureMs
            float c  = array.get(EC, i) * k
            float sc = array.get(SC, i) * k
            float lo = array.get(LO, i) * k
            float hi = array.get(HI, i) * k
            if not na(c)
                array.push(ptsExp, chart.point.from_time(t, c))
                lastC := c
                lastT := t
            if not na(sc)
                array.push(ptsScen, chart.point.from_time(t, sc))
            if not na(lo) and not na(hi)
                array.push(ptsHi, chart.point.from_time(t, hi))
                array.push(ptsLo, chart.point.from_time(t, lo))
                lastLo := lo
                lastHi := hi
                minLo := na(minLo) ? lo : math.min(minLo, lo)
                maxHi := na(maxHi) ? hi : math.max(maxHi, hi)

    if not expired
        // the 80% band: one closed polygon - the upper edge left to right, the lower edge back
        if showBand and array.size(ptsHi) >= 2
            array<chart.point> ring = array.copy(ptsHi)
            for j = array.size(ptsLo) - 1 to 0
                array.push(ring, array.get(ptsLo, j))
            pBand := polyline.new(ring, false, true, xloc.bar_time, cBandEdge, cBandFill, line.style_solid, 1)
        if showScen and array.size(ptsScen) >= 2
            pScen := polyline.new(ptsScen, false, false, xloc.bar_time, cScen, na, line.style_solid, 2)
        if showExp and array.size(ptsExp) >= 2
            pExp := polyline.new(ptsExp, false, false, xloc.bar_time, cExp, na, line.style_dashed, 2)
        // the AI briefing's key levels across the horizon
        if showLvls
            for p in SUP
                float y = p * k
                array.push(LINES, line.new(anchorMs, y, endMs, y, xloc.bar_time, extend.none, cSup, line.style_dotted, 1))
                if showLbls
                    array.push(LABELS, label.new(endMs, y, "S " + fmtPx(y), xloc.bar_time, yloc.price, color.new(cSup, 100), label.style_label_left, cSup, size.tiny))
            for p in RES
                float y = p * k
                array.push(LINES, line.new(anchorMs, y, endMs, y, xloc.bar_time, extend.none, cRes, line.style_dotted, 1))
                if showLbls
                    array.push(LABELS, label.new(endMs, y, "R " + fmtPx(y), xloc.bar_time, yloc.price, color.new(cRes, 100), label.style_label_left, cRes, size.tiny))

    // ---- labels
    if showLbls
        string issued = str.format_time(anchorMs, "dd MMM HH:mm", "UTC") + " UTC"
        string head = (modelTag == "" ? "PRISM" : modelTag) + " forecast " + sym + " - issued " + issued
        if expired
            head := "FORECAST EXPIRED - " + head + "\ncopy a fresh code on www.prismforecasting.com"
        else
            if not str.contains(str.upper(syminfo.ticker), str.upper(sym))
                head += "\n(code is for " + sym + ", this chart is " + syminfo.ticker + ")"
            if rebase
                head += na(anchorOpenChart) ? "\nnot rebased: the anchor bar is not on this chart" : (anchorExact ? "" : "\nrebased on the bar containing the anchor (approximate)")
            if tooFine
                head += "\nthis timeframe cannot show 48 h ahead - switch to M15, H1 or H4"
            else if tfSec > 3600
                head += "\n" + timeframe.period + " chart: every " + str.tostring(stepH) + "th hour of the H1 forecast is drawn - best on H1"
        float headY = na(maxHi) ? basePx * k : maxHi
        array.push(LABELS, label.new(anchorMs, headY, head, xloc.bar_time, yloc.price, expired ? color.new(#b91c1c, 10) : cLabelBg, label.style_label_down, cLabelTx, size.small))
        if not expired and not na(lastC)
            float basePxK = basePx * k
            float chg = basePxK > 0 ? (lastC / basePxK - 1) * 100 : na
            float half = not na(lastLo) and not na(lastHi) ? (lastHi - lastLo) / 2 : na
            bool  flat = not na(half) and half > 0 and math.abs(lastC - basePxK) < 0.10 * half
            string chgTxt = na(chg) ? "" : (flat ? "about flat " : (chg >= 0 ? "bullish " : "bearish ")) + (chg >= 0 ? "+" : "") + str.tostring(chg, "#.##") + "%"
            string dirTxt = na(pUp) ? "" : (math.abs(pUp - 50) < 6 ? "no clear edge - " + str.tostring(pUp, "#") + "% of paths end up" : (pUp >= 50 ? "up " + str.tostring(pUp, "#") + "% of paths" : "down " + str.tostring(100 - pUp, "#") + "% of paths"))
            string endTxt = "expected end close " + fmtPx(lastC) + (chgTxt == "" ? "" : " (" + chgTxt + ")")
            if not na(lastLo) and not na(lastHi)
                endTxt += "\n80% of closes: " + fmtPx(lastLo) + " - " + fmtPx(lastHi)
            if dirTxt != ""
                endTxt += "\nend direction: " + dirTxt
            array.push(LABELS, label.new(lastT, lastC, endTxt, xloc.bar_time, yloc.price, cLabelBg, label.style_label_left, cLabelTx, size.small))

if not ok and barstate.islast
    for lb in LABELS
        label.delete(lb)
    array.clear(LABELS)
    array.push(LABELS, label.new(bar_index, close, "PRISM Forecast: " + status, xloc.bar_index, yloc.price, cLabelBg, label.style_label_left, cLabelTx, size.small))
What you see

The website's forecast, on your chart.

γ€°Expected path & central scenario

The dashed line is the expected (median) close of every forecast hour; the solid line the central scenario β€” the most representative of the 256 simulated paths, the candles the website draws.

β–’80% range of closes

The shaded band is the 10th–90th percentile of the simulated closes at every hour β€” the same cone as on the website and in MT5; the end label gives the 80% interval of the end close.

βš–Honest labels

The end label reads β€œno clear edge” when the share of paths ending up is within 6 points of 50% and β€œabout flat” when the expected move is smaller than a tenth of the 80% half-width β€” the website's rules, not a trading signal.

✦Key levels

On plans with the AI briefing the code also carries the briefing's support and resistance levels, drawn dotted across the horizon.

πŸ•’UTC and your broker

Forecast hours are UTC candle boundaries, placed at the chart's bar times; the model's prices are rebased onto your chart's anchor bar.

🧭Prefer MetaTrader?

The MT5 expert fetches the forecast itself every minute and adds the AI briefing on the chart β€” for the plans that include it.

Coverage

What it forecasts β€” exactly.

17
Supported markets
XAUUSDGold XAGUSDSilver EURUSDEuro GBPUSDPound USDJPYYen USDCHFFranc NZDUSDKiwi US500S&P 500 US30Dow Jones WTICrude Oil BTCUSDBitcoin AUDUSDAussie USDCADLoonie EURJPYEuro/Yen GBPJPYPound/Yen EURGBPEuro/Pound NAS100Nasdaq 100

Metals Β· FX majors & crosses Β· US indices Β· Energy Β· Crypto β€” forecast jointly by one engine.

4
Supported timeframes
M1515 minutes H11 hour H44 hours D1Daily

All four views describe the same 48 hours and agree with each other exactly β€” the 15-minute candles aggregate perfectly into their hour, their 4-hour block, their day.

254
Future candles per forecast
M15192 candles
H148 candles
H412 candles
D12 candles

Every candle with full OHLC, the central scenario and its 80% range β€” a new forecast every hour, fixed at issue.

PRISM in your pocket

Forecasts wherever you trade.

Install the PRISM app on your phone β€” full-screen live charts, your own icon, and live alerts from the AI assistant as phone notifications. Free, no store account needed.