Pine Script v6 · Cross-script reuse

Pine Script Libraries: Exported Contracts and Versioned Imports

A Pine Script library publishes reusable code for other scripts. Declare it with library(), export its interface, publish it, then import a specific release. The contract includes parameter qualifiers, units and missing-value behavior. A library release number is separate from the Pine language version, and consumers do not automatically follow newer releases.

Review a library contract

The exported signature is the boundary

Exported function parameters require explicit types. Qualifiers control which arguments can reach them: const < input < simple < series. A simple parameter accepts weaker values, but rejects a changing series. Casting a series float to int does not make it simple. Return qualifiers follow the calculation, so a series input can produce a series result even when other parameters are simple.

  • Exported functions cannot read non-const library globals or call input.*(). Have the consumer collect settings and pass them as arguments.
  • Local request.*() calls require dynamic requests, and their expression cannot depend on exported parameters. Do not move an arbitrary request expression into an export.
  • Library function results are simple or series, so they cannot fill a parameter requiring const or input. Keep plot titles and other compile-time settings in the consumer.
Contract elementExample belowConsumer obligation
Name and argument orderrelativeMove(current, reference, unit)Preserve names if callers use named arguments.
series floatcurrent and referenceSupply numeric values; either may change per bar.
simple floatunit defaults to 100Choose a fixed scale per execution; do not pass a bar-dependent scale.
Resultseries floatHandle na before comparing or displaying the result.
Units100 means percent; 1 means fractionDo not compare 10 percent with a 0.10 fraction threshold.

A complete library with a defined numeric contract

This original example calculates unit × (current - reference) / reference. Inputs use the same measurement unit; reference and scale must be positive. Missing arguments return na. A zero or negative current is allowed, so a move from 100 to -50 returns -150 percent. The function has no stored state, rounding, price requests or hidden chart inputs. It does not calculate position P&L or handle currency conversion.

  • On the first chart bar, close[1] is missing, so the demo plot is na. A later valid pair produces a value immediately; there is no warm-up or carried state.
  • A very small positive reference can produce a very large result. This example does not clamp it. Use values within Pine numeric limits and define additional domain bounds before production use.
current / reference / unitExpected outputReason
110 / 100 / omitted10100 × (110 - 100) / 100
90 / 100 / 100-10A decline retains its sign.
110 / 100 / 10.1Fractional units are explicit.
0 / 100 / 100-100Zero current is valid.
-50 / 100 / 100-150Negative current is valid.
100 / 0 / 100naA zero reference is rejected.
100 / -100 / 100naA negative reference is rejected.
Any missing input, or unit ≤ 0naDo not replace invalid results with zero.
Complete library source. RelativeMoveContract is an unpublished example, not an available import.pinescript
//@version=6
// @description Relative movement with explicit invalid-input behavior.
library("RelativeMoveContract", overlay=false)

// @function Calculates scaled relative movement without stored state.
// @param current Current value; zero and negative values are allowed.
// @param reference Positive reference in the same unit as current.
// @param unit Positive fixed scale: 100 for percent, 1 for fraction.
// @returns Scaled movement, or na for missing inputs or invalid reference/scale.
export relativeMove(series float current, series float reference, simple float unit = 100.0) =>
    bool valid = not na(current) and not na(reference) and not na(unit) and reference > 0 and unit > 0
    valid ? unit * ((current - reference) / reference) : na

plot(relativeMove(close, close[1]), "Relative move (%)")

Run the contract fixtures before publishing

This complete indicator runs the same calculation locally so you can test the contract before an import exists. Its fixtures cover defaults, named arguments, signed values, missing data and invalid scales. The tolerance is 0.000000001 in the selected output units. The local adapter is deliberately visible: this script alone does not prove that a published library exports the same function.

Complete pre-publication test indicator. Replace the local adapter only after publishing your library.pinescript
//@version=6
indicator("Relative move contract fixtures")

relativeMove(series float current, series float reference, simple float unit = 100.0) =>
    bool valid = not na(current) and not na(reference) and not na(unit) and reference > 0 and unit > 0
    valid ? unit * ((current - reference) / reference) : na

check(float actual, float expected, string caseName) =>
    bool passed = na(expected) ? na(actual) : not na(actual) and math.abs(actual - expected) <= 0.000000001
    if not passed
        runtime.error("Contract failed: " + caseName)
    passed

float fixedUnit = input.float(100.0, "Chart scale", minval=0.000001)
float missing = na
if barstate.isfirst
    check(relativeMove(110.0, 100.0), 10.0, "default percent")
    check(relativeMove(reference=100.0, current=90.0), -10.0, "named arguments")
    check(relativeMove(110.0, 100.0, 1.0), 0.1, "fraction")
    check(relativeMove(100.0, 100.0), 0.0, "unchanged")
    check(relativeMove(0.0, 100.0), -100.0, "zero current")
    check(relativeMove(-50.0, 100.0), -150.0, "negative current")
    check(relativeMove(100.0, 0.0), na, "zero reference")
    check(relativeMove(100.0, -100.0), na, "negative reference")
    check(relativeMove(missing, 100.0), na, "missing current")
    check(relativeMove(100.0, missing), na, "missing reference")
    check(relativeMove(110.0, 100.0, float(na)), na, "missing scale")
    check(relativeMove(110.0, 100.0, 0.0), na, "zero scale")
    check(relativeMove(110.0, 100.0, -1.0), na, "negative scale")

float changing = bar_index % 2 == 0 ? na : 110.0
float result = relativeMove(changing, 100.0)
check(result, bar_index % 2 == 0 ? na : 10.0, "gap recovery")
plot(result, "Alternating na and 10")
plot(relativeMove(close, close[1], fixedUnit), "Chart movement", display=display.data_window)

Publish, then convert the fixtures into a consumer test

Save the library in Pine Editor, compile it, inspect its demonstration and use Publish Script. Choose private publication for a personal test or public publication for a public dependency. Copy the actual import declaration from the resulting publication. Saving a library locally is insufficient. This page has not published RelativeMoveContract or tested an import of it.

  • In a copy of the fixture indicator, delete the local relativeMove definition. Insert the copied, real import after the indicator declaration and assign the alias contract.
  • Change every relativeMove call to contract.relativeMove, leaving check(), fixtures and expected outputs untouched. Compile this consumer independently; a successful library compilation cannot verify import resolution or exported names.
  • Add the consumer to a chart. All fixture calls must complete without a runtime error; the alternating series must return na, 10, na, 10 from bar zero. Inspect the Data Window for the chart movement.
  • For a negative type test in a separate disposable copy, pass close as unit. Compilation should reject series float where simple float is required. Restore the valid input before saving the release test.
  • Archive the consumer source, exact import, library source, input settings and expected results together. Re-run the imported test after any library change; local fixtures cannot certify the published artifact.
Import-path notation only. Angle-bracket fields must be replaced with actual publication values.text
import <your-author>/<published-library-name>/<published-version> as contract

A real versioned import you can compile now

TradingView publishes the ta library; its release notes identify version 9 as the Pine v6 migration. This consumer pins TradingView/ta/9 and calls ema2() with a constant source of 100 and length 3. Its expected output is 100. This is an import and constant-input smoke test, not coverage of changing lengths, seeding on missing data or the unpublished example above.

Complete consumer using the published TradingView ta library, pinned to release 9.pinescript
//@version=6
indicator("Published library contract check")
import TradingView/ta/9 as tvta

float actual = tvta.ema2(100.0, 3.0)
float expected = 100.0
if na(actual) or math.abs(actual - expected) > 0.000000001
    runtime.error("Constant-source EMA contract failed")

plot(actual, "Imported EMA", color=color.blue)
plot(expected, "Expected constant", color=color.orange, style=plot.style_circles)

Upgrade consumers deliberately

The explicit import release stays fixed until the consumer source changes. Publishing release 2 does not redirect a release-1 import. Treat parameter names, accepted qualifiers, defaults, return order, units and na behavior as compatibility decisions. A change from percent to fraction can compile successfully and still break every threshold in a consumer.

  • Keep the release-1 consumer unchanged as a baseline. Compare missing-value masks before comparing finite outputs; a numeric difference plot alone can hide na mismatches.
  • For stateful libraries, also compare initial bars, call frequency and independent written call sites. Changing chart history or conditionally skipping calls can change state.
  • Update the pinned version only after the new consumer passes. Keep the old consumer source so reverting the import is an explicit, reviewable action.
Proposed changeRiskRelease test
Rename reference to baseNamed-argument callers fail.Keep the old exported wrapper or migrate callers explicitly.
Change unit default from 100 to 1A value of 10 becomes 0.1.Keep the default; introduce a separately named function if needed.
Accept zero reference with a fallbackInvalid data becomes a plausible number.Preserve na semantics or document the new contract in a new export.
Change a simple parameter to seriesReturn qualifiers or downstream calls can change.Compile actual consumers, including calls needing simple results.
Publish a new implementationSame signature can hide changed numerics.Test old and candidate imports under different aliases with identical fixtures.

Public, private and protected describe different boundaries

Libraries are always published with open source. Public versus private controls publication visibility; protected is a consumer-script setting, not a way to publish a closed-source library. TradingView requires attribution to the library author in the publication description. Its help-center rule for public closed-source reuse is more specific than the brief overview in the library manual.

Consumer or publicationDependency boundaryPublication requirement
Public open-source consumerPublic libraries onlyFollow reuse rules and credit authors.
Public protected or invite-only consumerPublic libraries onlyObtain explicit author permission for reuse in that closed-source form.
Private consumer or personal saved scriptPublic or private librariesConfirm access to the actual published dependency; privacy does not publish it.
Library publication itselfOpen source, whether public or privateA private publication is not a protected library.

Give the coding agent a contract it can check

Provide Pineify with both sources, the pinned import, compiler diagnostics and the fixture table. Ask for an exported function that preserves the current argument names, qualifiers, percent units and na behavior, plus a consumer that calls that export. Review the returned code in TradingView and run the consumer tests. Generating source does not publish your library or obtain reuse permission.

Where Pineify fits

Pine Script AI Coding Agent

Request a library refactor or import-error repair with your input types and expected outputs. Check the generated source and consumer behavior before publishing.

Review a library contract

Frequently asked questions

Programming examples, not investment advice. Syntax validation does not prove runtime results, publication permissions or trading performance. Publish and test your own library before relying on an import.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.