fix(db): fill-forward candles buckets
This commit is contained in:
@@ -162,10 +162,12 @@ RETURNS SETOF public.drift_candles
|
||||
LANGUAGE sql
|
||||
STABLE
|
||||
AS $$
|
||||
-- Zwraca zawsze "ciągłe" buckety (fill forward), nawet jeśli nie było ticków w danej sekundzie/minucie.
|
||||
-- Dzięki temu frontend może rysować regularną oś czasu (np. 1px = 1s) bez dziwnych przeskoków.
|
||||
WITH src AS (
|
||||
SELECT COALESCE(p_source, '') AS source_key
|
||||
),
|
||||
cached AS (
|
||||
raw_cached AS (
|
||||
SELECT
|
||||
c.bucket,
|
||||
c.open,
|
||||
@@ -181,7 +183,7 @@ AS $$
|
||||
ORDER BY c.bucket DESC
|
||||
LIMIT p_limit
|
||||
),
|
||||
fallback AS (
|
||||
raw_fallback AS (
|
||||
SELECT
|
||||
time_bucket(make_interval(secs => p_bucket_seconds), ts) AS bucket,
|
||||
ts,
|
||||
@@ -201,13 +203,88 @@ AS $$
|
||||
(array_agg(px ORDER BY ts DESC))[1] AS close,
|
||||
(array_agg(oracle_px ORDER BY ts DESC))[1] AS oracle_close,
|
||||
count(*) AS ticks
|
||||
FROM fallback
|
||||
FROM raw_fallback
|
||||
GROUP BY bucket
|
||||
)
|
||||
SELECT * FROM cached
|
||||
),
|
||||
data AS (
|
||||
SELECT * FROM raw_cached
|
||||
UNION ALL
|
||||
SELECT * FROM computed
|
||||
WHERE NOT EXISTS (SELECT 1 FROM cached)
|
||||
WHERE NOT EXISTS (SELECT 1 FROM raw_cached)
|
||||
),
|
||||
bounds AS (
|
||||
SELECT max(bucket) AS end_bucket FROM data
|
||||
),
|
||||
params AS (
|
||||
SELECT
|
||||
make_interval(secs => p_bucket_seconds) AS step,
|
||||
make_interval(secs => (p_bucket_seconds * (p_limit - 1))) AS span
|
||||
),
|
||||
series AS (
|
||||
SELECT generate_series(
|
||||
bounds.end_bucket - params.span,
|
||||
bounds.end_bucket,
|
||||
params.step
|
||||
) AS bucket
|
||||
FROM bounds, params
|
||||
WHERE bounds.end_bucket IS NOT NULL
|
||||
),
|
||||
joined AS (
|
||||
SELECT
|
||||
s.bucket,
|
||||
d.open,
|
||||
d.high,
|
||||
d.low,
|
||||
d.close,
|
||||
d.oracle_close,
|
||||
d.ticks
|
||||
FROM series s
|
||||
LEFT JOIN data d USING (bucket)
|
||||
ORDER BY s.bucket ASC
|
||||
),
|
||||
grouped AS (
|
||||
SELECT
|
||||
*,
|
||||
sum(CASE WHEN close IS NOT NULL THEN 1 ELSE 0 END) OVER (ORDER BY bucket ASC) AS grp_close,
|
||||
sum(CASE WHEN oracle_close IS NOT NULL THEN 1 ELSE 0 END) OVER (ORDER BY bucket ASC) AS grp_oracle
|
||||
FROM joined
|
||||
),
|
||||
first_vals AS (
|
||||
SELECT
|
||||
(SELECT close FROM grouped WHERE close IS NOT NULL ORDER BY bucket ASC LIMIT 1) AS first_close,
|
||||
(SELECT oracle_close FROM grouped WHERE oracle_close IS NOT NULL ORDER BY bucket ASC LIMIT 1) AS first_oracle
|
||||
),
|
||||
ff AS (
|
||||
SELECT
|
||||
g.bucket,
|
||||
g.open,
|
||||
g.high,
|
||||
g.low,
|
||||
g.close,
|
||||
g.oracle_close,
|
||||
g.ticks,
|
||||
COALESCE(
|
||||
g.close,
|
||||
max(g.close) OVER (PARTITION BY g.grp_close),
|
||||
f.first_close
|
||||
) AS ff_close,
|
||||
COALESCE(
|
||||
g.oracle_close,
|
||||
max(g.oracle_close) OVER (PARTITION BY g.grp_oracle),
|
||||
f.first_oracle
|
||||
) AS ff_oracle
|
||||
FROM grouped g
|
||||
CROSS JOIN first_vals f
|
||||
)
|
||||
SELECT
|
||||
bucket,
|
||||
COALESCE(open, ff_close) AS open,
|
||||
COALESCE(high, ff_close) AS high,
|
||||
COALESCE(low, ff_close) AS low,
|
||||
COALESCE(close, ff_close) AS close,
|
||||
COALESCE(oracle_close, ff_oracle) AS oracle_close,
|
||||
COALESCE(ticks, 0) AS ticks
|
||||
FROM ff
|
||||
ORDER BY bucket DESC
|
||||
LIMIT p_limit;
|
||||
$$;
|
||||
|
||||
Reference in New Issue
Block a user