Minimum variance - postscript

The article on the minimum variance portfolio showed that calculation step by step in a q session. This postscript provides functions to calculate the sparse covariance matrix and the minimum variance weights. It also defines another function to reshape a portfolio to the minimum variance weights.

All the functions are in portfolio.q.

Covariance matrix and minimum variance weights

The .portfolio.covariance and .portfolio.minvariance functions cover all the steps in the previous article. Both return tables as a declaration rather than an SQL statement, i.e.

([] sym1: first each p; sym2: last each p; cv: {cov [R first x; R last x]} each p)

Both also use anonymous functions to build columns in those tables. All the data for these anonymous functions could be passed through parameters but the costs are more complicated expressions and memory; parameters are passed by value and, for example, .portfolio.covariance would pass the dictionary of all returns, R, each call. An alternative is to place the data in a global or context variable, exploiting the fact that kdb+ is single threaded.

.portfolio.minvariance has a feature often seen in q applications: using a list as the single parameter so that various function signatures are possible. The parameter may either be a table or a list of a table and a list of symbols, for example:

.portfolio.minvariance .portfolio.covariance prices
.portfolio.minvariance (.portfolio.covariance prices; `BARC.L`HSBA.L`LLOY.L`RBS.L)

Another common alternative is to use a dictionary.

Reshaping a portfolio

The .portfolio.reweight function takes current portfolio holdings, reference prices and the target weights and calculates the smallest portfolio with those weights. As an example:

q)prices: `minute`sym`prx xcol ("USF"; enlist csv) 0: `:portfolio/bids.csv
q)strikes:: 0 ! select last prx by sym from prices
q)holdings: ([] sym: strikes `sym; qty: 1000 * 1 + (count strikes) ? 100)
q)weights: .portfolio.minvariance .portfolio.covariance prices
q).portfolio.reweight [holdings; strikes; weights]
sym    qty   prx    w          wt        qt    qd
BARC.L 27000 720.5  0.09331659 0.1504934 5971  21029
HSBA.L 8000  925.5  0.03551628 0.2589832 8000  0
LLOY.L 94000 560    0.2525091  0.1894035 9669  84331
RBS.L  60000 1974   0.5681454  0.222591  3224  56776
VOD.L  73000 144.25 0.05051261 0.1785288 35382 37618

If this were a programme trade, the reduced portfolio of quantities qt could then be simultaneously executed in slices (to maintain minimum variance) whilst the quantities qd could be traded independently through shortfall or participation strategies, and/or dark pools.

It would also be welcome to see prices regain their levels from this snapshot in December 2006.

Further reading
2.Further updates, and more q code, can be found at This is a secure site: for browsing the user name is anonymous with password anonymous.