Du har dina grupperade ner till minut. Vilket jag kommer att anta är fel eftersom dessa vanligtvis görs på dagen. Om jag har fel måste du ändra tillbaka det.
SELECT DISTINCT contract_id, ts::date,
min(price) OVER w,
max(price) OVER w,
first_value(price) OVER w,
last_value(price) OVER w
FROM fill
WINDOW w AS (PARTITION BY contract_id, ts::date ORDER BY ts)
ORDER BY 1,2