My goal is to detect price trends for cryptocurrencies. For that I'm getting OHLC pricing data for multiple currencies vs. multiple quote symbols (e.g. candles for Bitcoin/USD, Bitcoin/EUR, Litecoin/USD etc.). To accomplish calculating trends I use the Supertrend indicator. I have the following 2 tables:
-- This is where price candles AKA OHLC data gets stored. Interval can be '1h', '4h', '1d', etc.
CREATE TABLE ohlc (
id integer DEFAULT nextval('ohlc_id_seq'::regclass) PRIMARY KEY,
open numeric(65,30) NOT NULL,
high numeric(65,30) NOT NULL,
low numeric(65,30) NOT NULL,
close numeric(65,30) NOT NULL,
coinid character varying(255) NOT NULL REFERENCES coin(id) ON DELETE RESTRICT ON UPDATE CASCADE,
closetime timestamp(3) without time zone NOT NULL,
quotesymbol text NOT NULL,
interval text NOT NULL
);
-- This is a caching table that gets automatically populated by a stored procedure that runs AFTER every ohlc insert. "trend" can be 'UP' or 'DOWN'.
CREATE TABLE supertrend (
id integer DEFAULT nextval('supertrend_id_seq'::regclass) PRIMARY KEY,
coinid character varying(255) NOT NULL REFERENCES coin(id) ON DELETE RESTRICT ON UPDATE CASCADE,
quotesymbol text NOT NULL,
date timestamp(3) without time zone NOT NULL,
trend text NOT NULL,
interval text NOT NULL
);
Sample data for the supertrend table:
coinid | quotesymbol | date | trend | interval |
---|---|---|---|---|
'bitcoin' | 'usd' | '2024-04-18 00:00:00' | 'UP' | '1d' |
'bitcoin' | 'usd' | '2024-04-17 00:00:00' | 'UP' | '1d' |
'bitcoin' | 'usd' | '2024-04-16 00:00:00' | 'UP' | '1d' |
'bitcoin' | 'usd' | '2024-04-15 00:00:00' | 'DOWN' | '1d' |
'bitcoin' | 'eur' | '2024-04-18 00:00:00' | 'UP' | '1d' |
'bitcoin' | 'eur' | '2024-04-17 00:00:00' | 'UP' | '1d' |
'bitcoin' | 'eur' | '2024-04-16 00:00:00' | 'DOWN' | '1d' |
'bitcoin' | 'eur' | '2024-04-15 00:00:00' | 'DOWN' | '1d' |
'bitcoin' | 'cny' | '2024-04-18 00:00:00' | 'DOWN' | '1d' |
'bitcoin' | 'cny' | '2024-04-17 00:00:00' | 'UP' | '1d' |
'bitcoin' | 'cny' | '2024-04-16 00:00:00' | 'UP' | '1d' |
'bitcoin' | 'cny' | '2024-04-15 00:00:00' | 'UP' | '1d' |
'litecoin' | 'usd' | '2024-04-18 00:00:00' | 'DOWN' | '1d' |
'litecoin' | 'usd' | '2024-04-17 00:00:00' | 'UP' | '1d' |
'litecoin' | 'usd' | '2024-04-16 00:00:00' | 'DOWN' | '1d' |
'litecoin' | 'usd' | '2024-04-15 00:00:00' | 'DOWN' | '1d' |
'bitcoin' | 'usd' | '2024-04-18 00:00:00' | 'UP' | '4h' |
'bitcoin' | 'usd' | '2024-04-17 20:00:00' | 'UP' | '4h' |
'bitcoin' | 'usd' | '2024-04-17 16:00:00' | 'DOWN' | '4h' |
Let's say I want to query for the latest (ORDER BY date DESC
) trend for every coinid/quotesymbol with interval = '1d' (1 day). Or in other words I want to WHERE interval = '1d' GROUP BY coinid, quotesymbol
Also, I want to know the trend streak, so for how many time periods that trend is already the same.
Given the above example supertrend table data, my result should look like:
coinid | quotesymbol | latest_trend | trend_streak |
---|---|---|---|
'bitcoin' | 'usd' | 'UP' | 3 |
'bitcoin' | 'eur' | 'UP' | 2 |
'bitcoin' | 'cny' | 'DOWN' | 1 |
'litecoin' | 'usd' | 'DOWN' | 1 |
To clarify the above result: 'Bitcoin', 'usd' is 'UP' for 3 periods, because the trend for Bitcoin/USD was up on April 18, April 17 and April 16. And 'DOWN' on April 15, see sample supertrend table.
Additionally, I would like to know the aggregated supertrend over all quotesymbols (via mode function). That result should look like this:
coinid | latest_trend | trend_streak |
---|---|---|
'bitcoin' | 'UP' | 2 |
'litecoin' | 'DOWN' | 1 |
To clarify the above result: The latest Bitcoin/USD trend is 'UP, Bitcoin/EUR is 'EUR' is 'UP' and Bitcoin/CNY is 'DOWN'. The mode function takes ('UP', 'UP', 'DOWN') and returns the most frequent occuring value ('UP').
How can I query for this data in an efficient way considering the supertrend table has millions or billions of rows?
I was thinking of a materialized view but the lowest possible intervals for those supertrends are 1 minute and the might be written at distinct times, so that might be too high of a needed refresh rate.
I'm trying to avoid using a separate caching solution like Redis to keep the amount of needed architecture/environments simple, but I guess that could be an option especially for counters.
trend_streak
numbers? Phrases that are unclear: "trend ... with interval = '1d'" (there are no dates in your sample data), "quotesymbols", "mode function".