Lassen Sie mich ein reales Beispiel nehmen, um diese Frage zu beantworten
Ich musste einen gewichteten gleitenden Durchschnitt für meine Ohlc-Daten berechnen. Ich habe ungefähr 134000 Kerzen mit einem Symbol für jede, um dies zu tun
- Option 1 Machen Sie es in Python / Node etc etc.
- Option 2 Machen Sie es in SQL selbst!
Welches ist besser?
- Wenn ich dies in Python tun müsste, müsste ich im schlimmsten Fall alle gespeicherten Datensätze abrufen, die Berechnung durchführen und alles zurückspeichern, was meiner Meinung nach eine enorme Verschwendung von E / A darstellt
- Gewichtete Änderungen des gleitenden Durchschnitts jedes Mal, wenn Sie eine neue Kerze erhalten, was bedeutet, dass ich in regelmäßigen Abständen große Mengen an E / A durchführen würde, was in meinem Zeichen keine gute Meinung ist
- In SQL muss ich wahrscheinlich nur einen Trigger schreiben, der alles berechnet und speichert, sodass nur ab und zu die endgültigen WMA-Werte für jedes Paar abgerufen werden müssen, und das ist viel effizienter
Bedarf
- Wenn ich WMA für jede Kerze berechnen und speichern müsste, würde ich es auf Python tun
- Da ich aber nur den letzten Wert benötige, ist SQL viel schneller als Python
Um Sie zu ermutigen, ist dies die Python-Version, um einen gewichteten gleitenden Durchschnitt zu erstellen
WMA erfolgt über Code
import psycopg2
import psycopg2.extras
from talib import func
import timeit
import numpy as np
with psycopg2.connect('dbname=xyz user=xyz') as conn:
with conn.cursor() as cur:
t0 = timeit.default_timer()
cur.execute('select distinct symbol from ohlc_900 order by symbol')
for symbol in cur.fetchall():
cur.execute('select c from ohlc_900 where symbol = %s order by ts', symbol)
ohlc = np.array(cur.fetchall(), dtype = ([('c', 'f8')]))
wma = func.WMA(ohlc['c'], 10)
# print(*symbol, wma[-1])
print(timeit.default_timer() - t0)
conn.close()
WMA durch SQL
"""
if the period is 10
then we need 9 previous candles or 15 x 9 = 135 mins on the interval department
we also need to start counting at row number - (count in that group - 10)
For example if AAPL had 134 coins and current row number was 125
weight at that row will be weight = 125 - (134 - 10) = 1
10 period WMA calculations
Row no Weight c
125 1
126 2
127 3
128 4
129 5
130 6
131 7
132 8
133 9
134 10
"""
query2 = """
WITH
condition(sym, maxts, cnt) as (
select symbol, max(ts), count(symbol) from ohlc_900 group by symbol
),
cte as (
select symbol, ts,
case when cnt >= 10 and ts >= maxts - interval '135 mins'
then (row_number() over (partition by symbol order by ts) - (cnt - 10)) * c
else null
end as weighted_close
from ohlc_900
INNER JOIN condition
ON symbol = sym
WINDOW
w as (partition by symbol order by ts rows between 9 preceding and current row)
)
select symbol, sum(weighted_close)/55 as wma
from cte
WHERE weighted_close is NOT NULL
GROUP by symbol ORDER BY symbol
"""
with psycopg2.connect('dbname=xyz user=xyz') as conn:
with conn.cursor() as cur:
t0 = timeit.default_timer()
cur.execute(query2)
# for i in cur.fetchall():
# print(*i)
print(timeit.default_timer() - t0)
conn.close()
Ob Sie es glauben oder nicht, die Abfrage wird schneller ausgeführt als die Pure Python-Version eines WEIGHTED MOVING AVERAGE !!! Ich habe Schritt für Schritt diese Abfrage geschrieben, also bleib dran und du wirst es gut machen
Geschwindigkeit
0,42141127300055814 Sekunden Python
0,23801879299935536 Sekunden SQL
Ich habe 134000 gefälschte OHLC-Datensätze in meiner Datenbank, die auf 1000 Aktien aufgeteilt sind. Dies ist ein Beispiel dafür, wo SQL Ihren App-Server übertreffen kann