institutional-trader/backend/database/nearterm.sql

97 lines
3.7 KiB
SQL

WITH base AS (
SELECT
"Symbol" AS symbol,
"ExpirationDate"::date AS expiry,
UPPER("CallPut") AS callput,
"Strike"::float AS strike,
"Spot"::float AS spot, -- replace/join if missing
"Volume"::float AS vol,
"OI"::float AS oi
FROM public."OptionsFlow_monthly"
WHERE "ExpirationDate" BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL '30 days'
),
range_filtered AS (
SELECT *
FROM base
WHERE strike BETWEEN spot * 0.9 AND spot * 1.1
),
side_calc AS (
SELECT
symbol,
SUM(CASE WHEN callput = 'CALL' THEN vol ELSE 0 END) AS call_1m_vol,
SUM(CASE WHEN callput = 'PUT' THEN vol ELSE 0 END) AS put_1m_vol,
SUM(CASE WHEN callput = 'CALL' THEN oi ELSE 0 END) AS call_1m_oi,
SUM(CASE WHEN callput = 'PUT' THEN oi ELSE 0 END) AS put_1m_oi
FROM range_filtered
GROUP BY symbol
),
-- helper for K/M/B formatting
fmt AS (
SELECT
symbol,
call_1m_vol, put_1m_vol, call_1m_oi, put_1m_oi,
(call_1m_oi + put_1m_oi) AS tot_oi,
NULLIF(call_1m_oi,0) / NULLIF(put_1m_oi,0) AS oi_ratio_cp,
CASE WHEN call_1m_oi >= put_1m_oi THEN 'CALL' ELSE 'PUT' END AS dom_side
FROM side_calc
),
pretty AS (
SELECT
symbol,
-- human-readable K/M/B
CASE
WHEN call_1m_vol >= 1e9 THEN to_char(round((call_1m_vol/1e9)::numeric, 1), 'FM999,999,990.0') || 'B'
WHEN call_1m_vol >= 1e6 THEN to_char(round((call_1m_vol/1e6)::numeric, 1), 'FM999,999,990.0') || 'M'
WHEN call_1m_vol >= 1e3 THEN to_char(round((call_1m_vol/1e3)::numeric, 1), 'FM999,999,990.0') || 'K'
ELSE to_char(round(call_1m_vol::numeric), 'FM999,999,990')
END AS "Call_1M_Vol",
CASE
WHEN put_1m_vol >= 1e9 THEN to_char(round((put_1m_vol/1e9)::numeric, 1), 'FM999,999,990.0') || 'B'
WHEN put_1m_vol >= 1e6 THEN to_char(round((put_1m_vol/1e6)::numeric, 1), 'FM999,999,990.0') || 'M'
WHEN put_1m_vol >= 1e3 THEN to_char(round((put_1m_vol/1e3)::numeric, 1), 'FM999,999,990.0') || 'K'
ELSE to_char(round(put_1m_vol::numeric), 'FM999,999,990')
END AS "Put_1M_Vol",
CASE
WHEN call_1m_oi >= 1e9 THEN to_char(round((call_1m_oi/1e9)::numeric, 1), 'FM999,999,990.0') || 'B'
WHEN call_1m_oi >= 1e6 THEN to_char(round((call_1m_oi/1e6)::numeric, 1), 'FM999,999,990.0') || 'M'
WHEN call_1m_oi >= 1e3 THEN to_char(round((call_1m_oi/1e3)::numeric, 1), 'FM999,999,990.0') || 'K'
ELSE to_char(round(call_1m_oi::numeric), 'FM999,999,990')
END AS "Call_1M_OI",
CASE
WHEN put_1m_oi >= 1e9 THEN to_char(round((put_1m_oi/1e9)::numeric, 1), 'FM999,999,990.0') || 'B'
WHEN put_1m_oi >= 1e6 THEN to_char(round((put_1m_oi/1e6)::numeric, 1), 'FM999,999,990.0') || 'M'
WHEN put_1m_oi >= 1e3 THEN to_char(round((put_1m_oi/1e3)::numeric, 1), 'FM999,999,990.0') || 'K'
ELSE to_char(round(put_1m_oi::numeric), 'FM999,999,990')
END AS "Put_1M_OI",
-- highlights
dom_side,
CASE
WHEN dom_side = 'CALL' AND (call_1m_oi >= put_1m_oi * 1.3) THEN 'CALL 🚀'
WHEN dom_side = 'PUT' AND (put_1m_oi >= call_1m_oi * 1.3) THEN 'PUT 🛑'
ELSE dom_side
END AS "Highlight",
-- keep raw metrics for sorting
call_1m_oi, put_1m_oi, (call_1m_oi + put_1m_oi) AS tot_oi,
oi_ratio_cp
FROM fmt
)
SELECT
symbol,
"Call_1M_Vol",
"Put_1M_Vol",
"Call_1M_OI",
"Put_1M_OI",
"Highlight"
FROM pretty
-- 🔽 pick one ORDER BY pattern you prefer:
-- 1) Overall liquidity leaders:
ORDER BY tot_oi DESC, GREATEST(call_1m_oi, put_1m_oi) DESC, symbol
-- 2) Side dominance (comment the above ORDER BY and uncomment below):
-- ORDER BY ABS(COALESCE(oi_ratio_cp,0) - 1) DESC, tot_oi DESC, symbol
LIMIT 10000;