Reputation: 149
I am trying to calculate the exponential moving average (EMA) of a stock price. I am using a formula to calculate EMA from this site: http://www.iexplain.org/ema-how-to-calculate/
I am totally stuck calculating the proper EMA. The query runs and returns results but does not return an accurate EMA. Help is greatly appreciated. You can see the attempt to calculate EMA using the EMA formula starting at line 4.
SELECT current_day.date as current_date, current_day.avg_price as current_date_price,
prev_day.prev_avg_price as previous_date_price, prev_2_day.prev_avg_price,
( ( current_day.avg_price * (2 / (22 + 1) ) ) + ( ( ( prev_day.prev_avg_price * (2 / (22
+ 1) ) ) +
( prev_2_day.prev_avg_price * (2 / (22 + 1) ) ) ) * (1 -( 2 / (22 + 1) ) ) ) ) as EMA
FROM
(select DATE(time) as date, ROUND(AVG(price),2) as avg_price FROM ds_5.tb_4978 group by
date) as
current_day
JOIN
(select DATE(USEC_TO_TIMESTAMP(time- 86400000000)) as prev_date, ROUND(AVG(price),2) as
prev_avg_price from ds_5.tb_4978 GROUP BY prev_date) as prev_day
ON current_day.date=prev_day.prev_date
JOIN
(select DATE(USEC_TO_TIMESTAMP(time- (86400000000*2))) as prev_2_date, ROUND(AVG(price),2)
as
prev_avg_price from ds_5.tb_4978 GROUP BY prev_2_date) as prev_2_day
ON current_day.date=prev_2_day.prev_2_date
GROUP BY current_date, current_date_price, previous_date_price,
prev_2_day.prev_avg_price, EMA
This is the json response from the above query: https://json.datadives.com/01843e08d5127e9d26d03fe0f842e735.json
Upvotes: 2
Views: 2305
Reputation: 26637
This isn't a full answer, but rather than doing a self JOIN to get the current date and the previous date, you can use the LEAD() function to get the previous day's time and price rather than doing the multiple joins. This can lead to more natural code and faster queries.
For example:
SELECT <calculate avg here> FROM (
SELECT DATE(time) as date, ROUND(AVG(price),2) as avg_price,
LEAD(time, 1) OVER (ORDER BY time DESC) as prev_day_time,
LEAD(price, 1) OVER (ORDER BY time DESC) as prev_price,
LEAD(time, 2) OVER (ORDER BY time DESC) as prev_2_day_time,
LEAD(price, 2) OVER (ORDER BY time DESC) as prev_2_price,
FROM [...])
That said this only works if you have a bounded moving average (i.e. you're only going to keep track of moving average for the last N days. If you are trying to chain the moving average indefinitely, SQL is not going to be a good solution.
Upvotes: 1
Reputation: 17280
I don't think you take the previous day avg_price. You need to take the previous day EMA.
I would rather calculate the EMA upfront; if not possible, maybe look into MapReduce.
Upvotes: 2