exact_change

Compares two fixed-point observations of one quantity exactly (two blocks, two windows, two venues, two rates): each value is raw with its own decimals and both are rescaled to the larger decimals. Returns new - old in units, that change as a percent and in basis points of old, and new as a percent of old, as exact decimal text. No floating point; NULL input returns NULL.

Example

Runs locally

SELECT (exact_change(1500000::UINT256, 6, 1200000::UINT256, 6)).change AS change;
-- => [{"change":"-0.3"}]

API reference

exact_change(UINT256 | INT256, INTEGER, UINT256 | INT256, INTEGER) #

Change, percent, bps and share of two fixed-point values.

Exact signatures (4)
  • exact_change(UINT256, INTEGER, UINT256, INTEGER)
  • exact_change(INT256, INTEGER, INT256, INTEGER)
  • exact_change(INT256, INTEGER, UINT256, INTEGER)
  • exact_change(UINT256, INTEGER, INT256, INTEGER)

Inputs

Name Type Use
old UINT256 | INT256

UINT256 or INT256 raw value; the base of the percents and bps.

required positional
old_decimals INTEGER

INTEGER 0 to 77: old is old / 10^old_decimals units.

required positional
new UINT256 | INT256

UINT256 or INT256 raw value; native integers need a cast to either.

required positional
new_decimals INTEGER

INTEGER 0 to 77; may differ from old_decimals.

required positional

Returns

Name Type
comparison STRUCT(change VARCHAR, change_percent VARCHAR, change_bps VARCHAR, share_percent VARCHAR)

Exact change, percent, bps and share. STRUCT(change VARCHAR, change_percent VARCHAR, change_bps VARCHAR, share_percent VARCHAR): change = new - old at the larger decimals; change_percent = (new - old) / old * 100, change_bps = (new - old) / old * 10000, share_percent = new / old * 100, each to 6 decimal places truncated toward zero. Trailing zeros trimmed, '-' for negatives. The three ratios are NULL when old is 0. Decimals outside 0 to 77 error.

Overload examples

Runs locally

SELECT (exact_change(2410::INT256, 0, 2400::INT256, 0)).change_bps AS bps;
-- => [{"bps":"-41.493775"}]

Runs locally

-- A Chainlink answer (8 decimals) against a pool quote (6 decimals)
SELECT c.* FROM (SELECT exact_change(200000000000::INT256, 8, 2050500000::UINT256, 6) AS c);
-- => [{"change":"50.5","change_percent":"2.525","change_bps":"252.5","share_percent":"102.525"}]