I have two tables, a table called companies_display with information about publicly traded companies such as ticker symbol, market cap etc. and a partitioned table stock_prices with the historical stock prices for each company. I want to calculate the beta of each stock and write that into companies_display. For that I wrote the function calculate_beta(ticker) that calculates it:
CREATE OR REPLACE FUNCTION calculate_beta (VARCHAR)
RETURNS float8 AS $beta$
DECLARE
beta float8;
BEGIN
WITH weekly_returns AS (
WITH RECURSIVE
spy AS (
SELECT time, close FROM stock_prices WHERE ticker = 'SPY'
),
stock AS (
SELECT time, close FROM stock_prices WHERE ticker = $1
)
SELECT
spy.time,
stock.close / LAG(stock.close) OVER (ORDER BY spy.time DESC) AS stock,
spy.close / LAG(spy.close) OVER (ORDER BY spy.time DESC) AS spy
FROM stock
JOIN spy
ON stock.time = spy.time
WHERE EXTRACT(DOW FROM spy.time) = 1
ORDER BY spy.time DESC
LIMIT 52
)
SELECT
COVAR_SAMP(stock, spy) / VAR_SAMP(spy) INTO beta
FROM weekly_returns
;
RETURN beta;
END;
$beta$ LANGUAGE plpgsql;
The function works for just a few companies, but when i tried to update the whole table
UPDATE companies_display SET beta = calculate_beta(ticker);
I get an out of shared memory error and it says that max_locks_per_transaction is too low. My guess is that the function creates a lock on the stock_prices table for each company and doesn’t drop them till it would have run to completion. What I tried was to create a loop
DO
$do$
DECLARE
ticker_ VARCHAR;
BEGIN
FOR ticker_ IN SELECT ticker FROM companies_display
LOOP
UPDATE companies_display
SET beta = calculate_beta(ticker_)
WHERE ticker = ticker_
;
END LOOP;
END
$do$;
but I ran into the same problem. Is there a way to drop the lock on stock_prices after each beta calculation or do the update in batches? For about 5 companies at a time my method works.
Advertisement
Answer
If someone runs into the same problem, I avoided the error by calling my sql function from the server I use to update my database. That way I have one transaction per company and I don’t get to many locks.