Enter your visualization key to unlock CM Pro data available for your account.

The key you provided is not a data visualization key and/or has been revoked. Please use a different key.

Your visualization key was changed in another tab. After saving your work, you can reload the application for the changes to take effect in this tab.

Your chart list could not be loaded due to a server error. Please try reloading the page.

The chart list is empty

The saved chart file is not compatible with this app. Please try a different file.

Share this URL with others

The Formula Builder supports a variety of argument types, depending on the
specific function. Many formulas take both **real numbers** and **time series** as
arguments. However, some functions will only take real numbers, and others
will take only time series. There are a handful of functions that support
**dates**. Some functions support **lists**. Most operations can be used in
combination. To learn more about each function, view the "Syntax" tab, which
will list the data type supported and will provide the appropriate syntax.

CM crypto data **time series** are represented by the AssetID.MetricID (e.g.,
BTC.PriceUSD) notation.

To find MetricIDs and AssetIDs use the search functions
located on the "Editor" tab. An AssetID can represent cryptoassets, exchanges, exchange-assets or indexes:

- Cryptoasset: BTC, ETH
- Exchange: COINBASE, KRAKEN
- Exchange-Asset: COINBASE-BTC, BINANCE-ETH
- Indexes: CMBI10, CMBIBTC

If an AssetID has a "-" (e.g., COINBASE-BTC),
use the asset("Asset-ID").metricID notation e.g.,
asset("COINBASE-BTC").volume_reported_spot_usd_1d - for the time series.
If a MetricID has a "." (e.g., SplyAdrBalNtv0.1), use the AssetID.metric("Metric.ID") notation (e.g.,
BTC.metric("SplyAdrValNtv.01") for the time series.
**Time series** can be added, multiplied, subtracted and divided by one another (to
name a few of the functions available). These operations are applied on a
per-element basis. If one series does not have a value for a specific date, it
is treated as zero at this date. Additionally, multiplication, division, and
exponentiation can be applied by scalar and addition/subtraction by scalar on
per element basis.

**Integers and real numbers** can also be added, multiplied, subtracted and divided
by one another. And, formulas support both integers and real numbers. The
standard operators are used for these operations: addition (+), subtraction
(-), multiplication (*), division (/), modulo (%) and exponentiation (^). You
can also check numbers for equality (=) and they can be compared (<,>,=<, >=),
which return boolean (true/false) values. Boolean values support "and", "or"
and "not" operations.

**Dates** are often called as an argument in a formula. Internally, a date is
represented as the number of milliseconds passed since January 1st, 1970. Dates
are written in the date(YYYY, MM, DD) format. Numeric values can be
added/subtracted to/from dates, with the number interpreted as the number of
days to add/subtract (e.g., date(2016, 4, 1) + 2 will add two days, returning
April 3rd, 2016. Dates can also be subtracted from each other, returning the
difference in days: date(2017, 3, 5) - date(2017, 3, 3) will return 2, for
instance.

Certain formulas can also be applied to **lists**. Lists are ordered collections
of elements, similar to Python lists and Javascript arrays. Unlike Python and
Javascript, the index for the first element is 1, not 0. Lists can be
concatenated via the (+) operator. A list can be created using list(member0,
member1, ..., membern) where members can be numbers or time series. For
example, list(BTC.PriceUSD, ETH,PriceUSD) returns the list containing the two
time series. Lists can be saved/named (e.g., MyList), with the saved name being
used as the argument.

**Subformulas** are arguments for some functions. They are identical to anonymous
functions from Javascript, Python and other programming languages, the syntax
is: fn(argName_1, ..., argName_n)( ... some computation ... ). For example
fn(coin)(coin.networkValueUsd / coin.txVolumeUsd) returns the subformula that
computes NVT for a coin. They are useful in cases where you want to calculate
some metric for multiple currencies without code duplication: metric's code can
be put into the first formula and later addressed by subsequent formulas via
designated name.

Operations follow the expected order of operations.

Formulas support **conditional expressions** with the following syntax: if
(...) then (...) else (...). For example rsi.map(fn(date, value) (if value >
75 then 1 else 0)) where rsi is rsi(BTC.priceUsd, 90) draws a time series which
has value of 1 on dates when BTC's 90 day RSI is higher than 75, and zero
otherwise.