KDB knowledge

Finance and price functions

Money math like Excel (interest, loan EMI, NPV, IRR, XIRR, CAGR), price ticks and pivot points for traders.

These functions do the money math that people usually do in Excel: interest, loan installments, the value of future money today, and the yearly return of an investment. There are also two tools for traders: price ticks and pivot points.

The sample data of this page (fixture analysis-finance, made-up numbers) has cash_flows (money out and in of two investments, with dates), loans and invoices.

Example: The monthly EMI of every loan, and the interest paid in total (sample data: analysis-finance)

SELECT purpose, principal, annual_rate, years,
       round(-pmt(annual_rate / 12, years * 12, principal), 2) AS monthly_emi,
       round(-pmt(annual_rate / 12, years * 12, principal) * years * 12 - principal, 2) AS total_interest
FROM loans
ORDER BY id;

Result:

purpose (STRING)principal (DOUBLE)annual_rate (DOUBLE)years (INT)monthly_emi (DOUBLE)total_interest (DOUBLE)
Home loan50000000.1052049918.996980558.64
Car loan18000000.12731774.92869093.2
Education loan8000000.09516606.68196401.05

(3 rows)

Example: Yearly return of two investments from their dated cash flows (sample data: analysis-finance)

SELECT project, count(*) AS cash_flows, sum(amount) AS money_gained,
       round(xirr(amount, flow_date) * 100, 2) AS yearly_return_pct
FROM cash_flows
GROUP BY project
ORDER BY project;

Result:

project (STRING)cash_flows (LONG)money_gained (DOUBLE)yearly_return_pct (DOUBLE)
SOLAR_ROOF101070007.77
VOLT_SHARES4187003.8

(2 rows)

cagr

Syntax:

cagr(start_value, end_value, years)

The compound annual growth rate: the same yearly growth that turns start_value into end_value in years years. If a share went from 400 to 505 in 3 years, it grew about 8.08% every year on average (not 26.25% / 3). The formula is (end / start) ^ (1 / years) - 1.

ArgumentTypeMeaning
start_valuenumberthe value at the start, more than 0
end_valuenumberthe value at the end, 0 or more
yearsnumberhow many years between them, more than 0; a fraction like 0.7 is fine

Example (sample data: analysis-finance)

SELECT round(cagr(400, 505, 3), 4) AS share_growth, round(cagr(100000, 146932.81, 5), 4) AS deposit, cagr(100, 0, 2) AS lost_all, cagr(0, 50, 2) AS bad_start;

Result:

share_growth (DOUBLE)deposit (DOUBLE)lost_all (DOUBLE)bad_start (STRING)
0.08080.08-1NULL

(1 row)

Example: Yearly growth of each share from its first to its last close (sample data: sample)

SELECT symbol, first_close, last_close, days,
       round(cagr(first_close, last_close, days / 365.0) * 100, 2) AS cagr_pct
FROM (SELECT symbol, first(close) AS first_close, last(close) AS last_close,
             datediff('d', min(time), max(time)) AS days
      FROM ochl_day
      GROUP BY symbol) t
ORDER BY symbol;

Result:

symbol (SYMBOL)first_close (DOUBLE)last_close (DOUBLE)days (LONG)cagr_pct (DOUBLE)
CITY542.2504.9256-9.66
COAST424.8376.1256-15.94
VOLT191.7191.2256-0.37

(3 rows)

Example: Yearly growth of two mutual funds over two years (sample data: analysis-market)

SELECT fund, first(nav) AS start_nav, last(nav) AS end_nav,
       round(cagr(first(nav), last(nav), 23 / 12.0) * 100, 2) AS cagr_pct
FROM fund_nav
GROUP BY fund
ORDER BY fund;

Result:

fund (SYMBOL)start_nav (DOUBLE)end_nav (DOUBLE)cagr_pct (DOUBLE)
GROWTH1012.1810.84
INCOME1010.784

(2 rows)

compound_interest

Syntax:

compound_interest(principal, rate, years)
compound_interest(principal, rate, years, times_per_year)

The interest you earn when interest is added to the money again and again (compounding), so later interest is also paid on earlier interest. It gives only the interest, not the total: add principal for the final amount.

ArgumentTypeMeaning
principalnumberthe money you put in
ratenumberthe yearly interest rate as a fraction (0.08 for 8%)
yearsnumberhow many years; a fraction like 0.5 is fine
times_per_yearnumberhow often interest is added in a year; default 1. 4 = every quarter, 12 = every month

Example: Interest on 100,000 at 8% for 5 years: yearly, quarterly and monthly (sample data: analysis-finance)

SELECT round(compound_interest(100000, 0.08, 5), 2) AS yearly,
       round(compound_interest(100000, 0.08, 5, 4), 2) AS quarterly,
       round(compound_interest(100000, 0.08, 5, 12), 2) AS monthly,
       round(100000 + compound_interest(100000, 0.08, 5), 2) AS final_amount;

Result:

yearly (DOUBLE)quarterly (DOUBLE)monthly (DOUBLE)final_amount (DOUBLE)
46932.8148594.7448984.57146932.81

(1 row)

Example: Interest must be added at least once a year (sample data: analysis-finance; shows an error)

SELECT compound_interest(100000, 0.08, 5, 0);

Result:

Error: line 1, column 8: compound_interest: the number of times per year must be more than 0

fv

Syntax:

fv(rate, periods, payment)
fv(rate, periods, payment, present_value)
fv(rate, periods, payment, present_value, type)

The future value: how much money you have after periods periods, when you save payment every period and/or put in present_value at the start, with interest rate per period. The same as Excel FV.

ArgumentTypeMeaning
ratenumberinterest per period as a fraction (monthly: 0.12 / 12)
periodsnumberhow many periods
paymentnumbermoney paid in every period; negative when you pay it
present_valuenumbermoney at the start; default 0; negative when you put it in
type0 or 10 (default): payments at the end of each period; 1: at the start

Example: Save 5,000 a month for 10 years at 10% a year (a SIP) (sample data: analysis-finance)

SELECT round(fv(0.10 / 12, 120, -5000), 2) AS after_10_years,
       5000 * 120 AS paid_in,
       round(fv(0.10 / 12, 120, -5000, 0, 1), 2) AS paying_at_month_start;

Result:

after_10_years (DOUBLE)paid_in (LONG)paying_at_month_start (DOUBLE)
1024224.896000001032760.1

(1 row)

Example: A fixed deposit of 100,000 for 5 years at 8% (nothing added every year) (sample data: analysis-finance)

SELECT round(fv(0.08, 5, 0, -100000), 2) AS maturity_amount;

Result:

maturity_amount (DOUBLE)
146932.81

(1 row)

pv

Syntax:

pv(rate, periods, payment)
pv(rate, periods, payment, future_value)
pv(rate, periods, payment, future_value, type)

The present value: how much future money is worth today. Money later is worth less than money now, because money now can earn interest. The same as Excel PV.

ArgumentTypeMeaning
ratenumberinterest (or discount rate) per period as a fraction
periodsnumberhow many periods
paymentnumbermoney received (positive) or paid (negative) every period
future_valuenumbermoney at the end; default 0
type0 or 10 (default): payments at the end of each period; 1: at the start

Example: What is a pension of 20,000 a month for 15 years worth today, at 9% a year? (sample data: analysis-finance)

SELECT round(-pv(0.09 / 12, 15 * 12, 20000), 2) AS worth_today, 20000 * 15 * 12 AS paid_in_total;

Result:

worth_today (DOUBLE)paid_in_total (LONG)
1971868.183600000

(1 row)

Example: How much to put in today to have 500,000 in 4 years at 7%? (sample data: analysis-finance)

SELECT round(pv(0.07, 4, 0, 500000), 2) AS deposit_today;

Result:

deposit_today (DOUBLE)
-381447.61

(1 row)

pmt

Syntax:

pmt(rate, periods, present_value)
pmt(rate, periods, present_value, future_value)
pmt(rate, periods, present_value, future_value, type)

The payment for every period of a loan or a savings plan. For a loan it is the EMI (equated monthly installment): the same amount every month that pays back the loan and its interest. The same as Excel PMT.

ArgumentTypeMeaning
ratenumberinterest per period (monthly: yearly rate / 12)
periodsnumberhow many payments (months: years × 12), not 0
present_valuenumberthe loan amount you get (positive)
future_valuenumbermoney left at the end; default 0. For a savings goal, use 0 as present_value and the goal here
type0 or 10 (default): pay at the end of each period; 1: at the start

Example: EMI of a 1,000,000 loan for 5 years at 12% a year (sample data: analysis-finance)

SELECT round(pmt(0.12 / 12, 5 * 12, 1000000), 2) AS emi,
       round(-pmt(0.12 / 12, 5 * 12, 1000000) * 60, 2) AS paid_back_in_total,
       pmt(0, 12, 120000) AS no_interest;

Result:

emi (DOUBLE)paid_back_in_total (DOUBLE)no_interest (DOUBLE)
-22244.451334666.86-10000

(1 row)

Example: Save for a goal: how much a month to have 100,000 in a year at 12%? (sample data: analysis-finance)

SELECT round(-pmt(0.01, 12, 0, 100000), 2) AS save_each_month;

Result:

save_each_month (DOUBLE)
7884.88

(1 row)

Example: The EMI table of all loans (sample data: analysis-finance)

SELECT purpose, principal, round(annual_rate * 100, 2) AS rate_pct, years,
       round(-pmt(annual_rate / 12, years * 12, principal), 2) AS emi
FROM loans
ORDER BY emi DESC;

Result:

purpose (STRING)principal (DOUBLE)rate_pct (DOUBLE)years (INT)emi (DOUBLE)
Home loan500000010.52049918.99
Car loan180000012731774.92
Education loan8000009516606.68

(3 rows)

Example: The number of payments cannot be 0 (sample data: analysis-finance; shows an error)

SELECT pmt(0.01, 0, 100000);

Result:

Error: line 1, column 8: pmt: the number of periods must not be 0

nper

Syntax:

nper(rate, payment, present_value)
nper(rate, payment, present_value, future_value)
nper(rate, payment, present_value, future_value, type)

The number of periods: how many payments it takes to pay back a loan (or reach a savings goal) with a fixed payment. The same as Excel NPER.

ArgumentTypeMeaning
ratenumberinterest per period
paymentnumberthe payment every period; negative when you pay
present_valuenumberthe loan amount (positive)
future_valuenumbermoney left at the end; default 0
type0 or 10 (default): pay at the end of each period; 1: at the start

Example: How many months to pay back 1,000,000 at 12% a year, paying 25,000 a month? (sample data: analysis-finance)

SELECT round(nper(0.12 / 12, -25000, 1000000), 2) AS months,
       ceil(nper(0.12 / 12, -25000, 1000000)) AS whole_months,
       nper(0, -10000, 120000) AS no_interest,
       nper(0.01, -100, 100000) AS never_paid_back;

Result:

months (DOUBLE)whole_months (DOUBLE)no_interest (DOUBLE)never_paid_back (STRING)
51.345212NULL

(1 row)

npv

Syntax:

npv(rate, value1, value2, ...)

The net present value: all future cash flows brought back to today's value with the discount rate, and added up. A discount rate is the yearly return you could get somewhere else (for example from a fixed deposit). When the NPV is above 0, the project earns more than that; below 0, less. The same as Excel NPV.

ArgumentTypeMeaning
ratenumberdiscount rate per period, more than -1
value1, value2, ...numbersthe cash flow at the end of period 1, 2, ... (up to 63 values)

Example: Is a 1,000,000 project with these yearly profits worth it at a 10% discount rate? (sample data: analysis-finance)

SELECT round(-1000000 + npv(0.10, 300000, 350000, 400000, 250000), 2) AS npv_at_10_pct,
       round(-1000000 + npv(0.15, 300000, 350000, 400000, 250000), 2) AS npv_at_15_pct;

Result:

npv_at_10_pct (DOUBLE)npv_at_15_pct (DOUBLE)
33262.76-68535.35

(1 row)

Example: Careful: the first value is one year away (sample data: analysis-finance)

SELECT round(npv(0.10, -1000, 300, 400, 500), 2) AS all_discounted,
       round(-1000 + npv(0.10, 300, 400, 500), 2) AS today_not_discounted;

Result:

all_discounted (DOUBLE)today_not_discounted (DOUBLE)
-19.12-21.04

(1 row)

irr

Syntax:

irr(value0, value1, value2, ...)

The internal rate of return: the discount rate that makes the NPV of the cash flows exactly 0. It is the yearly (or per period) return of the investment. Compare it with a bank rate: an IRR of 12% is better than a deposit at 8%. The same as Excel IRR.

ArgumentTypeMeaning
value0numberthe cash flow today (usually the money you invest, negative)
value1, value2, ...numbersthe cash flow at the end of period 1, 2, ... (2 to 64 values in total)

Example: Return of a project: invest 1,000,000, get money back for 4 years (sample data: analysis-finance)

SELECT round(irr(-1000000, 300000, 350000, 400000, 250000) * 100, 2) AS irr_pct,
       irr(-1000, 1100) AS ten_pct,
       irr(100, 200) AS no_negative_value;

Result:

irr_pct (DOUBLE)ten_pct (DOUBLE)no_negative_value (STRING)
11.540.1NULL

(1 row)

Example: NPV at the IRR is 0 (sample data: analysis-finance)

SELECT round(-1000000 + npv(irr(-1000000, 300000, 350000, 400000, 250000), 300000, 350000, 400000, 250000), 6) AS npv_at_irr;

Result:

npv_at_irr (DOUBLE)
0

(1 row)

xnpv

Syntax:

xnpv(rate, amount, date)

The net present value of cash flows on real dates. It is an aggregate: every row is one cash flow. Each amount is discounted by the years between its date and the earliest date of the group (days / 365), so money on the first date is not discounted. The same as Excel XNPV.

ArgumentTypeMeaning
ratenumberyearly discount rate as a fraction, more than -1; read from the first row
amountnumberthe cash flow of the row: negative for money out, positive for money in
dateDATE, TIMESTAMP or date textthe day of the cash flow

Example: NPV of each investment at a 5% and a 10% discount rate (sample data: analysis-finance)

SELECT project,
       round(xnpv(0.05, amount, flow_date), 2) AS xnpv_5_pct,
       round(xnpv(0.10, amount, flow_date), 2) AS xnpv_10_pct
FROM cash_flows
GROUP BY project
ORDER BY project;

Result:

project (STRING)xnpv_5_pct (DOUBLE)xnpv_10_pct (DOUBLE)
SOLAR_ROOF34320.05-25132.15
VOLT_SHARES-5423.7-25726.21

(2 rows)

Example: The date must be a date (sample data: analysis-finance; shows an error)

SELECT xnpv(0.1, amount, memo) FROM cash_flows;

Result:

Error: line 1, column 8: xnpv: needs a date, got 'Buy 1000 VOLT shares at 185'

xirr

Syntax:

xirr(amount, date)
xirr(amount, date, guess)

The yearly return of cash flows on real dates: the rate where xnpv is 0. It is an aggregate: every row is one cash flow. Use it for a share you bought, got dividends for, and sold; or for a SIP with payments on different days. The same as Excel XIRR.

ArgumentTypeMeaning
amountnumberthe cash flow: negative for money out (buy), positive for money in (dividend, sell)
dateDATE, TIMESTAMP or date textthe day of the cash flow
guessnumberwhere the search starts; default 0.1 (10%). Rarely needed

Example: Every cash flow of the VOLT shares, and the yearly return (sample data: analysis-finance)

SELECT flow_date, amount, memo FROM cash_flows WHERE project = 'VOLT_SHARES' ORDER BY flow_date;

SELECT round(xirr(amount, flow_date) * 100, 2) AS yearly_return_pct
FROM cash_flows
WHERE project = 'VOLT_SHARES';

Result:

SELECT flow_date, amount, memo FROM cash_flows WHERE project = 'VOLT_SHARES' ORDER BY flow_date

flow_date (DATE)amount (DOUBLE)memo (STRING)
2024-01-15-185000Buy 1000 VOLT shares at 185
2024-12-205000Cash dividend
2025-12-187500Cash dividend
2026-09-10191200Sell 1000 VOLT shares at 191.2

(4 rows)

SELECT round(xirr(amount, flow_date) * 100, 2) AS yearly_return_pct FROM cash_flows WHERE project =

yearly_return_pct (DOUBLE)
3.8

(1 row)

Example: Check: XNPV at the XIRR rate is 0 (the rate comes from a subquery) (sample data: analysis-finance)

SELECT round(abs(xnpv(r.rate, c.amount, c.flow_date)), 4) AS xnpv_at_xirr
FROM cash_flows c
CROSS JOIN (SELECT xirr(amount, flow_date) AS rate FROM cash_flows WHERE project = 'VOLT_SHARES') r
WHERE c.project = 'VOLT_SHARES';

Result:

xnpv_at_xirr (DOUBLE)
0

(1 row)

Example: An aggregate cannot be inside another aggregate (sample data: analysis-finance; shows an error)

SELECT xnpv(xirr(amount, flow_date), amount, flow_date) FROM cash_flows;

Result:

Error: line 1, column 13: 'xirr' is an aggregate and cannot be used inside the aggregate 'xnpv'; compute it in a subquery first: SELECT xnpv(x) FROM (SELECT xirr(...) AS x FROM t GROUP BY ...) s

Example: Only money in: no return can be found (sample data: analysis-finance)

SELECT xirr(amount, flow_date) AS xirr
FROM cash_flows
WHERE amount > 0;

Result:

xirr (STRING)
NULL

(1 row)

round_tick, floor_tick, ceil_tick

Syntax:

round_tick(price)
round_tick(price, tick)
floor_tick(price)
floor_tick(price, tick)
ceil_tick(price)
ceil_tick(price, tick)

Moves a price to the nearest allowed tick. The tick size is the smallest step a price can move on the exchange. On some exchanges it is 0.1: 512.3 and 512.4 are prices, 512.35 is not. Use these functions for order prices, stop-losses and targets that you compute (like close - 2 × ATR).

FunctionMoves the price512.37 with tick 0.1
round_tickto the nearest tick (a half goes up, away from zero)512.4
floor_tickdown to the tick at or below512.3
ceil_tickup to the tick at or above512.4
ArgumentTypeMeaning
pricenumberthe price
ticknumberthe tick size, more than 0; default 0.1

Example (sample data: analysis-finance)

SELECT round_tick(512.34) AS a, round_tick(512.35) AS half_up, floor_tick(512.39) AS down, ceil_tick(512.31) AS up,
       round_tick(512.37, 0.05) AS tick_005, round_tick(512.3, 1) AS whole_dollar;

Result:

a (DOUBLE)half_up (DOUBLE)down (DOUBLE)up (DOUBLE)tick_005 (DOUBLE)whole_dollar (DOUBLE)
512.3512.4512.3512.4512.35512

(1 row)

Example: A stop-loss 2 × ATR below the close, as a price the exchange accepts (sample data: sample)

SELECT symbol, close, atr5, round(close - 2 * atr5, 4) AS raw_stop, floor_tick(close - 2 * atr5) AS stop_price
FROM (SELECT time, symbol, close, atr(high, low, close, 5) OVER (PARTITION BY symbol ORDER BY time) AS atr5
      FROM ochl_day) t
WHERE time IN '2026-09-10'
ORDER BY symbol;

Result:

symbol (SYMBOL)close (DOUBLE)atr5 (DOUBLE)raw_stop (DOUBLE)stop_price (DOUBLE)
CITY504.97.65324002169651489.5935489.5
COAST376.19.98787632660481356.1242356.1
VOLT191.27.42858372551475176.3428176.3

(3 rows)

Example: The tick size must be more than 0 (sample data: analysis-finance; shows an error)

SELECT round_tick(512.34, 0);

Result:

Error: line 1, column 8: round_tick: the tick size must be more than 0

pivot_point

Syntax:

pivot_point(high, low, close)
pivot_point(high, low, close, method)

The pivot point of the next day, made from the high, low and close of one day. Day traders draw it as a line on the chart. When the price is above the pivot, they see the day as strong (bullish); below, weak (bearish). The other lines, support (a price where falls often stop) and resistance (a price where rises often stop), come from pivot_level.

ArgumentTypeMeaning
highnumberthe high of the day (usually yesterday)
lownumberthe low of that day
closenumberthe close of that day
methodtext'classic' (default; 'standard' is the same), 'fibonacci' (or 'fib'), 'camarilla' or 'woodie' (any case)

Example (sample data: analysis-finance)

SELECT round(pivot_point(507.0, 500.7, 504.9), 2) AS classic,
       round(pivot_point(507.0, 500.7, 504.9, 'fibonacci'), 2) AS fibonacci,
       round(pivot_point(507.0, 500.7, 504.9, 'woodie'), 3) AS woodie;

Result:

classic (DOUBLE)fibonacci (DOUBLE)woodie (DOUBLE)
504.2504.2504.375

(1 row)

pivot_level

Syntax:

pivot_level(high, low, close, level)
pivot_level(high, low, close, level, method)

One line of the pivot point system: the pivot 'p', the resistance lines 'r1', 'r2', 'r3' above it, or the support lines 's1', 's2', 's3' below it. r1 and s1 are close to the pivot; r3 and s3 are far away and are only reached on days with big moves.

ArgumentTypeMeaning
high, low, closenumbersthe candle of one day (usually yesterday)
leveltext'p' (also 'pp', 'pivot'), 'r1', 'r2', 'r3', 's1', 's2', 's3'; 'camarilla' also has 'r4' and 's4' (any case)
methodtext'classic' (default, or 'standard'), 'fibonacci' (or 'fib'), 'camarilla', 'woodie'

The lines, with P = the pivot and range = high - low:

MethodR1 / S1R2 / S2R3 / S3R4 / S4
classic, woodie2P - low / 2P - highP ± rangehigh + 2(P - low) / low - 2(high - P)none
fibonacciP ± 0.382 × rangeP ± 0.618 × rangeP ± rangenone
camarillaclose ± range × 1.1/12close ± range × 1.1/6close ± range × 1.1/4close ± range × 1.1/2

Example: Today's pivot lines for every symbol, from yesterday's candle (sample data: sample)

SELECT symbol,
       round_tick(pivot_level(high, low, close, 's2')) AS s2,
       round_tick(pivot_level(high, low, close, 's1')) AS s1,
       round_tick(pivot_point(high, low, close)) AS pivot,
       round_tick(pivot_level(high, low, close, 'r1')) AS r1,
       round_tick(pivot_level(high, low, close, 'r2')) AS r2
FROM ochl_day
WHERE time IN '2026-09-09'
ORDER BY symbol;

Result:

symbol (SYMBOL)s2 (DOUBLE)s1 (DOUBLE)pivot (DOUBLE)r1 (DOUBLE)r2 (DOUBLE)
CITY498.6501.6507510515.4
COAST366.4373.3386392.9405.6
VOLT178.4182.8186.2190.6194

(3 rows)

Example: Did the price stop at yesterday's lines? Today's high and low next to R1 and S1 (sample data: sample)

SELECT symbol, time, low, high, s1, r1,
       CASE WHEN high >= r1 THEN 'broke R1' WHEN low <= s1 THEN 'broke S1' ELSE 'stayed between' END AS result
FROM (SELECT time, symbol, low, high,
             round_tick(pivot_level(prev_high, prev_low, prev_close, 's1')) AS s1,
             round_tick(pivot_level(prev_high, prev_low, prev_close, 'r1')) AS r1
      FROM (SELECT time, symbol, low, high,
                   lag(high) OVER (PARTITION BY symbol ORDER BY time) AS prev_high,
                   lag(low) OVER (PARTITION BY symbol ORDER BY time) AS prev_low,
                   lag(close) OVER (PARTITION BY symbol ORDER BY time) AS prev_close
            FROM ochl_day) c) t
WHERE time IN '2026-09-10'
ORDER BY symbol;

Result:

symbol (SYMBOL)time (TIMESTAMP)low (DOUBLE)high (DOUBLE)s1 (DOUBLE)r1 (DOUBLE)result (STRING)
CITY2026-09-10T00:00:00.000Z500.7507501.6510broke S1
COAST2026-09-10T00:00:00.000Z373.2382373.3392.9broke S1
VOLT2026-09-10T00:00:00.000Z184.2192.1182.8190.6broke R1

(3 rows)

Example: The four methods side by side (CITY, 2026-09-10 candle) (sample data: sample)

SELECT m.method,
       round(pivot_level(d.high, d.low, d.close, 's1', m.method), 2) AS s1,
       round(pivot_level(d.high, d.low, d.close, 'p', m.method), 2) AS pivot,
       round(pivot_level(d.high, d.low, d.close, 'r1', m.method), 2) AS r1
FROM ochl_day d
CROSS JOIN (SELECT 'classic' AS method UNION ALL SELECT 'fibonacci' UNION ALL SELECT 'camarilla' UNION ALL SELECT 'woodie') m
WHERE d.symbol = 'CITY' AND d.time IN '2026-09-10'
ORDER BY s1;

Result:

method (STRING)s1 (DOUBLE)pivot (DOUBLE)r1 (DOUBLE)
classic501.4504.2507.7
woodie501.75504.38508.05
fibonacci501.79504.2506.61
camarilla504.32504.2505.48

(4 rows)

Example: Classic pivots have no R4 (sample data: analysis-finance; shows an error)

SELECT pivot_level(507.0, 500.7, 504.9, 'r4');

Result:

Error: line 1, column 8: pivot_level: level must be p, r1, r2, r3, s1, s2 or s3 for classic pivots, got 'r4'