ขอยกตัวอย่างจริงเพื่อตอบคำถามนี้
ฉันต้องการคำนวณค่าเฉลี่ยเคลื่อนที่ถ่วงน้ำหนักบนข้อมูล ohlc ของฉันฉันมีเทียนประมาณ 134,000 ชิ้นที่มีสัญลักษณ์สำหรับให้ทำเช่นนั้น
- ตัวเลือกที่ 1 ทำได้ใน Python / Node ฯลฯ ฯลฯ
- ตัวเลือก 2 ทำใน SQL เอง!
อันไหนดีกว่า?
- ถ้าฉันต้องทำสิ่งนี้ใน Python โดยพื้นฐานแล้วฉันจะต้องดึงข้อมูลที่เก็บไว้ทั้งหมดที่เลวร้ายที่สุดดำเนินการคำนวณและบันทึกทุกอย่างกลับคืนซึ่งในความคิดของฉันนั้นเป็นความสูญเสียครั้งใหญ่ของ IO
- การเปลี่ยนแปลงค่าเฉลี่ยเคลื่อนที่ถ่วงน้ำหนักทุกครั้งที่คุณได้รับเทียนใหม่หมายถึงฉันจะทำ IO จำนวนมากในช่วงเวลาปกติซึ่งไม่ใช่ความคิดที่ดีในสัญลักษณ์ของฉัน
- ใน SQL สิ่งที่ฉันต้องทำก็คือเขียนทริกเกอร์ที่คำนวณและเก็บทุกอย่างดังนั้นจะต้องดึงค่า WMA สุดท้ายสำหรับแต่ละคู่ทุก ๆ คราวแล้วและนั่นก็มีประสิทธิภาพมากกว่า
ความต้องการ
- ถ้าฉันต้องคำนวณ WMA สำหรับเทียนทุกอันและเก็บไว้ฉันจะทำบน Python
- แต่เนื่องจากฉันต้องการค่าสุดท้ายเท่านั้นSQL จึงเร็วกว่า Python มาก
เพื่อให้การสนับสนุนแก่คุณนี่คือรุ่น Python ที่ใช้ค่าเฉลี่ยเคลื่อนที่แบบถ่วงน้ำหนัก
WMA ทำผ่านรหัส
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 ผ่าน 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()
เชื่อหรือไม่แบบสอบถามทำงานเร็วกว่า Pure Python ในการทำ WEVEED MOVING AVERAGE !!!ฉันไปทีละขั้นตอนในการเขียนแบบสอบถามที่ดังนั้นแขวนในที่นั่นและคุณจะทำอะไรได้ดี
ความเร็ว
0.42141127300055814 วินาที Python
0.23801879299935536 วินาทีของ SQL
ฉันมีระเบียน OHLC ปลอม 134,000 รายการในฐานข้อมูลของฉันแบ่งออกเป็น 1,000 หุ้นดังนั้นนี่คือตัวอย่างที่ SQL สามารถมีประสิทธิภาพสูงกว่าเซิร์ฟเวอร์แอปของคุณ