I have the following query:
SELECT
date_trunc('minute', ts) ts,
instrument,
MAX(price) high,
MIN(price) low,
(SUM(price * price * quantity) / SUM(price * quantity)) midpoint,
SUM(price * quantity) volume,
(SUM(direction * price * quantity) / SUM(price * quantity)) direction,
EXTRACT(SECOND FROM MIN(ts)) < 15 AND EXTRACT(SECOND FROM MAX(ts)) > 45 AND count(*) > 20 complete
FROM {tableName exchangeName}
WHERE instrument = '{instrument.Ticker}' AND ts BETWEEN '{fromTime}' AND '{toTime}'
GROUP BY date_trunc('minute', ts), instrument
ORDER BY ts
LIMIT 4500
It takes a list of financial trades and aggregates them into candles for a given time range.
I'm trying to add a few fields:
- Open, which is be the first price (sorted by ts)
- Close, which is the last price (sorted by ts)
- Count, which is the amount of trades / rows in the time range
- and update Direction which is a bit more complex:
the trades are constructed like this:
instrument VARCHAR NOT NULL,
ts TIMESTAMP WITHOUT TIME ZONE NOT NULL,
quantity FLOAT8 NOT NULL,
price FLOAT8 NOT NULL,
direction INTEGER NOT NULL
and the direction field can have two values: +1 or -1 (it's essentially a bool) and, for a group of trades / candle, the calculations are like this:
candle.volume = trades -> add (trade.quantity * trade.price)
candle.direction = trades -> keep only when direction is +1 -> add (trade.quantity * trade.price) / candle.volume
The first three are very simple, but I'm not sure what to google for the syntax to use. The last one, I'm not sure how to write that in SQL.
Any help would be greatly appreciated.
edit:
based on the link provided by LukStorms, I came up with something ugly for open and close. Maybe someone can propose something nicer:
(array_agg(price order by ts))[1] open,
(array_agg(price order by ts))[array_upper((array_agg(price order by ts)), 1)] close,