Minimum variance portfolio

This article looks at calculating the global minimum variance portfolio as an illustration of the interactive way of developing solutions with kdb+.

We will calculate the portfolio using an arbitrary collection of assets, in this case a basket of five equities: BARC.L, HSBA.L, LLOY.L, RBS.L and VOD.L. Before calculating the portfolio we need some recent time series of prices for the assets. A sample of bid prices for the assets, at 15 minute intervals, is in this csv file. We load this into q and parse it into a table.

q)bids: ("USF"; enlist csv) 0: `:bids.csv
q)show bids
minute sym    bid
--------------------
08:00  BARC.L 720
08:00  HSBA.L 922
08:00  LLOY.L 556.5
08:00  RBS.L  1992
08:00  VOD.L  144.25
08:05  BARC.L 721
08:05  HSBA.L 921
08:05  LLOY.L 556
08:05  RBS.L  1996
08:05  VOD.L  144.5
08:10  BARC.L 721
08:10  HSBA.L 920.5
08:10  LLOY.L 556.5
08:10  RBS.L  1996
08:10  VOD.L  144.75
08:15  BARC.L 723
08:15  HSBA.L 920.5
08:15  LLOY.L 557
08:15  RBS.L  1996
08:15  VOD.L  144.5
..

From the bids table we calculate the returns for each symbol.

q)returns: 0 ! select r: log bid % bid ^ prev bid by sym from bids
q)show returns
sym    r                                                                     ..
-----------------------------------------------------------------------------..
BARC.L 0              0.001387925   0              0.002770085    -0.00415801..
HSBA.L 0              -0.001085187  -0.0005430356  -1.110223e-016 -1.110223e-..
LLOY.L 0              -0.0008988765 0.0008988765   0.0008980692   0.000897263..
RBS.L  -1.110223e-016 0.002006019   -1.110223e-016 -1.110223e-016 0.003500879..
VOD.L  0              0.001731602   0.001728609    -0.001728609   0          ..

By 'filling' the previous bid with bid itself we remove the null return on the first bid: the return becomes zero. As 'select ... by ...' adds keys to the resultant table, we can keep it flat through the '0 !' operation. Note in the resulting returns table that, unlike SQL databases, kdb+ allows a column to contain a list of values.

The covariance matrix

To reduce calculations we will make a sparse covariance matrix, one with only a single entry per unique pair of symbols. The unique pairs are reduced from the simple permutation of all pairs of symbols.

q)pairs: distinct asc each returns.sym cross returns.sym
q)show pairs
BARC.L BARC.L
BARC.L HSBA.L
BARC.L LLOY.L
BARC.L RBS.L
BARC.L VOD.L
HSBA.L HSBA.L
HSBA.L LLOY.L
HSBA.L RBS.L
HSBA.L VOD.L
LLOY.L LLOY.L
LLOY.L RBS.L
LLOY.L VOD.L
RBS.L  RBS.L
RBS.L  VOD.L
VOD.L  VOD.L

The reduction is made through sorting each pair of symbols from the 'cross' function, then selecting only the unique values. In calculating the covariance matrix we will need to repeatedly access the returns for a symbol, so we create a function to do this.

q)r4s: {raze exec r from returns where sym = x}

Then we calculate the sparse covariance matrix for the pairs into a table.

q)matrix: (`sym1`sym2`cv !) each {x, cov [r4s first x; r4s last x]} each pairs
q)show matrix
sym1   sym2   cv
----------------------------
BARC.L BARC.L 1.326453e-006
BARC.L HSBA.L 2.076055e-007
BARC.L LLOY.L 2.626368e-007
BARC.L RBS.L  1.806784e-007
BARC.L VOD.L  7.138501e-008
HSBA.L HSBA.L 5.957067e-007
HSBA.L LLOY.L 2.502168e-007
HSBA.L RBS.L  1.699649e-008
HSBA.L VOD.L  1.199947e-007
LLOY.L LLOY.L 8.537148e-007
LLOY.L RBS.L  9.391369e-008
LLOY.L VOD.L  1.673899e-007
RBS.L  RBS.L  1.14479e-006
RBS.L  VOD.L  -5.121614e-008
VOD.L  VOD.L  1.419477e-006

The minimum variance portfolio

We define a function to extract all the covariances from a sparse matrix for a given symbol; then calculate the minimum variance weightings themselves, as normalised inverse covariance sums, into a table.

q)c4s: {exec cv from matrix where (sym1 = x) or (sym2 = x)}
q)weights: ([] sym: returns.sym; .quant.w {reciprocal sum c4s x} each returns.sym)
q)show weights
sym    w
----------------
BARC.L 0.1504934
HSBA.L 0.2589832
LLOY.L 0.1894035
RBS.L  0.222591
VOD.L  0.1785288

A collection of quantitative functions in q can be downloaded. See also the postscript to this article.

Further reading

1.www.kx.com