TradingCharts

Libraries

A library is a reusable module of exported functions, types, and enums. Scripts import a library by owner, name, and version — version-pinned so a library update never silently breaks…

Creating a library

//@version=1
library("MyMa")

export smooth(float source, int length) =>
    ta.ema(source, length)

export method square(float this) =>
    this * this

export type Pivot
    int   bar
    float price
    bool  isHigh

Rules the compiler enforces

  • The declaration must be library("Name"). The name must match [A-Za-z0-9_]+ — library names ride import paths.
  • At least one export function, type, or enum is required.
  • Every exported function parameter needs an explicit type keyword (float, int, bool, string, color, a UDT, an enum, an array/map/matrix type).
  • Exported function bodies cannot call input.*() or reference globals initialised from input.*(). Inputs belong to the consuming script.
  • alert() is allowed inside exported bodies; the consumer surfaces the alerts.
  • request.*() is allowed when the library's declaration keeps dynamic_requests at true.

Publishing

A library is a script, so publishing is the normal "▷ Publish library" flow from the editor. The result lives at:

<ownerId>/<Name>/<version>

Each save bumps the version — a library at /1 cannot be edited in place; the next save becomes /2. Consumers pin a specific version (import ownerId/Name/1 as m), so your updates never silently reach them.

Importing a library

//@version=1
indicator("Uses MyMa")
import 1000000072/MyMa/1 as m

plot(m.smooth(close, 20),  "smoothed")
plot((5.0).square())
  • The import path's owner id can be alphanumeric or fully numeric (your platform client id — 1000000072).
  • as alias is optional; omitted → the alias defaults to the library name.
  • Imports are top level only. They cannot live inside a function or a conditional.
  • Imports are version-pinned: import x/MyMa/1 and import x/MyMa/2 are separate libraries that can coexist in one script.

Libraries importing libraries

A library can import other libraries. The chain is resolved recursively; names imported inside a nested library are available to it under its own alias:

//@version=1
library("Outer")

import 1000000072/Signal/1 as sig

export wrap(float s) =>
    sig.smooth(s, 5)

The consumer only sees Outer's exports — the inner Signal import is a private detail.

Circular imports are detected and rejected with the full chain shown.

Visibility

  • A library created in your account is private by default — only you can import it.
  • Making a library public exposes it to the marketplace's kind=library listing.

Private libraries can still be imported from the editor's "Import library…" dialog by their owner.

Idiomatic style

  • Keep library functions pure: a result depends only on its arguments plus the current bar's series values.
  • Export every type a function signature references — the compiler enforces this for UDTs and enums.
  • Group related helpers in one library rather than splitting fine-grained libraries.
  • Document each export with a comment above the export line.

Example — a reusable zone helper

//@version=1
library("Zones")

export type Zone
    int   leftBar
    float top
    float bottom
    color col

export method draw(Zone this) =>
    box.new(this.leftBar, this.top, bar_index, this.bottom,
            bgcolor      = color.new(this.col, 85),
            border_color = this.col)

export of(bool isDemand, float px, float atrSize) =>
    isDemand ? Zone.new(bar_index, px, px - atrSize * 2, color.lime)
             : Zone.new(bar_index, px + atrSize * 2, px, color.red)

Consumer:

//@version=1
indicator("Zone user", overlay=true)
import 1000000072/Zones/1 as zones

zone = zones.of(close > open, close, ta.atr(14))
zone.draw()

See also