I have data on stock prices for multiple companies for the last 10 years. I want to be able to query this table to return the annual (calendar year) stock price return for each of these stocks. Note that the same dates for each stock may not exist, so I am trying to dynamically calculate the return using the earliest and latest available date for each stock.
My table looks like this:
Date | Stock | Price ========== | ======== | ===== 2018-01-03 | AAPL | 200 2018-04-20 | AAPL | 210 2018-07-10 | AAPL | 230 2018-10-05 | AAPL | 250 2018-12-20 | AAPL | 290 2019-01-06 | AAPL | 300 2019-06-15 | AAPL | 280 2019-09-10 | AAPL | 340 2019-12-28 | AAPL | 400 2018-01-02 | MSFT | 80 2018-04-20 | MSFT | 90 2018-07-10 | MSFT | 110 2018-10-05 | MSFT | 100 2018-12-22 | MSFT | 95 2019-01-10 | MSFT | 110 2019-04-20 | MSFT | 105 2019-06-19 | MSFT | 120 2019-09-11 | MSFT | 140 2019-12-30 | MSFT | 150
I am looking to grab the earliest and latest stock price for each stock, as follows:
Date | Stock | Price ========== | ======== | ===== 2018-01-03 | AAPL | 200 2018-12-20 | AAPL | 290 2019-01-06 | AAPL | 300 2019-12-28 | AAPL | 400 2018-01-02 | MSFT | 80 2018-12-22 | MSFT | 95 2019-01-10 | MSFT | 110 2019-12-30 | MSFT | 150
And finally, I am trying to calculate the return (End of year price / Start of year price – 1)
Year | Stock | Return ===== | ======== | ===== 2018 | AAPL | 0.45 2019 | AAPL | 0.3333 2018 | MSFT | 0.1875 2019 | MSFT | 0.3636
What would be the most efficient way to achieve this result (as I will be running this on over 1000 stocks in a 10 year period, which is likely to get computationally intensive)?
Advertisement
Answer
It shouldn’t be too bad. I have built this query based on your sample (plus a single row for 2017):
DECLARE @stocks TABLE ( Date DATETIME, Stock VARCHAR(10), Price MONEY ) INSERT INTO @stocks ( Date, Stock, Price ) VALUES (' 2017-01-03' , 'AAPL', 200), (' 2018-01-03' , 'AAPL', 200), (' 2018-04-20' , 'AAPL', 210), (' 2018-07-10' , 'AAPL', 230), (' 2018-10-05' , 'AAPL', 250), (' 2018-12-20' , 'AAPL', 290), (' 2019-01-06' , 'AAPL', 300), (' 2019-06-15' , 'AAPL', 280), (' 2019-09-10' , 'AAPL', 340), (' 2019-12-28' , 'AAPL', 400), (' 2018-01-02' , 'MSFT', 80 ), (' 2018-04-20' , 'MSFT', 90 ), (' 2018-07-10' , 'MSFT', 110), (' 2018-10-05' , 'MSFT', 100), (' 2018-12-22' , 'MSFT', 95 ), (' 2019-01-10' , 'MSFT', 110), (' 2019-04-20' , 'MSFT', 105), (' 2019-06-19' , 'MSFT', 120), (' 2019-09-11' , 'MSFT', 140), (' 2019-12-30' , 'MSFT', 150) SELECT S1.Stock, S1.MinDate, S2.Price, S1.MaxDate, S3.Price , (S3.Price / S2.Price) - 1 AS 'Return' FROM ( SELECT Stock, MIN(date) AS MinDate, MAX(date) AS MaxDate FROM @stocks GROUP BY Stock, YEAR(date) ) AS S1 LEFT JOIN @stocks AS S2 ON S2.Stock = S1.Stock AND S2.Date = S1.MinDate LEFT JOIN @stocks AS S3 ON S3.Stock = S1.Stock AND S3.Date = S1.MaxDate ORDER BY S1.Stock, YEAR(S1.MinDate)