Devils and details

The devil is in the detail they say. And one detail that has been nagging me extra lately is the issue mentioned in A few simple rows – Restated that I’m still not sure if my model successfully can ensure positive asset weight only. A feature which I believe is essential for having an investment strategy accessible to anyone, and not only hedge funds. As you will see in this post, this issue is an easy fix. Although, the solution was not what I expected. 

I will demonstrate two different models for obtaining dynamic and optimal values of theta, followed by two different methods for translating these thetas into asset weight within my portfolio. In total, this will result in four different model+method combinations for which each combination’s portfolio performance is presented in the end. Are you ready?

Model A

The first model is the one currently used for obtaining the values of theta within my investment strategy up to date. Since I have already shown you all details behind this model (please see A few simple rows – Restated), I will try to keep it short. In sum, the model uses a combination of the parametric portfolio policy, together with the asset characteristics past trading volume / dolvol and momentum, and a generalized autoregressive score (GAS) model to decide which stocks within the OMX Stockholm 30 Index to invest in each month.
 
With this said, the full python code for model A is presented below.
I would like to point your attention to the line 
w = list(map(lambda i: np.exp(np.log((1/N1[i])*(1+np.dot(x1[i].T,tets[i,:])))),range(len(inin1)))),
and specifically to the np.exp(np.log part. This is where I within my optimization try to tell the model that negative weights are not allowed.  

Model B

Moving on, the code for model B follows suit.
Have you noticed any difference? Again, take a look at the line 
w = list(map(lambda i: (1/N1[i])*(1+np.dot(x1[i].T,tets[i,:])),range(len(inin1))))
In the model B optimization, I skip the part of trying to ensure positive assets weights only and let it optimize more freely instead. The main idea with Model B is that I allow my model to use hypothetically negative asset weights for finding the optimal values of theta. And, as you will see soon in the method part of this post, I wait with restricting the weights until after the optimization. 

Thetas

Before moving on to the methods of how to translate thetas into actual asset weight, this is how I obtain the thetas of each model out of sample.
This part has also been explained in full previously in A few simple rows – Restated but I think it’s worth mentioning that the out of sample thetas are obtained using the same mechanics for both model A and model B. Meaning, any differences in the output will be driven solely by the estimated parameters (omega, alpha, and beta) of the two models. 

In essence, this is how the dynamic and optimal values of theta look like for model A and model B, for which the dashed line separates the in sample and out of sample data. Followed by each model’s estimated parameters (omega, alpha, and beta). 

The value of theta obtained with model B is clearly more volatile and generally higher with respect to the momentum characteristic. This pattern is probably connected to the absence of weight restrictions within the model B optimization.  

Method I

Like model A, method I is also the one that I currently use for translating the thetas into actual asset weight within my investment strategy today. The method I code for getting asset weights using the thetas of both model A and B looks as follow.
Here I also use the np.exp(np.log to ensure positive weights which I believe is the right thing to do. Looking back, however, the fact that I have needed to use np.exp(np.log both here and within the optimization might be proof enough that the restrictions in model A were not working ideally.

One remaining issue though, that method I do not cover but that I try to cope with in method II, is that the sum of all weights each month does not sum to one, resulting in a portfolio exposure that risks being larger than 100%. By the laws of nature, this is not a feasible scenario. Not even for hedge funds (I think?). Soon, you will also see why this becomes a problem when taking an investment budget into account. But first, let’s look at a potential solution. 

Method II

In method II, I use the same weights gotten from method I standardized by their sum.

In math, it will look like this. 



And in python code, for each of model A and B, like this.
The expressions 
/np.nan_to_num(np.exp(np.log((1/N2[i])*(1+np.dot(x2[i].T,teta_a[i]))))).sum() 
and 
/np.nan_to_num(np.exp(np.log((1/N2[i])*(1+np.dot(x2[i].T,teta_b[i]))))).sum() 
represent the part where each asset weight becomes standardized (or divided) by the sum of all weights each month. 

Performance

Looking at the performance of the four different model+method combinations, I start by deriving the actual asset allocations and corresponding portfolio returns of each month when accounting for a monthly investment budget of 5000 SEK using the following lines. 

But I also want to show you the actual size or price of each monthly investment that should be close (but seldom exactly equal) to the budget. One reason why the investment size tends to deviate from the budget is that stocks need to be bought in pieces (hence the np.round expression) and naturally, this alters the allocation. But it can also be due to my investment strategy having a portfolio exposure larger than 100%. Anyhow, I calculate the investment size for each month as below. Followed by an illustration of the size for each combination. 



It’s easy to see that model B + method I (meaning the non-restricted optimization with non-standardized weights) is going crazy. Following this combination, I would need to nearly double my expected budget on several occasions to “keep my strategy happy”. Meanwhile, the combinations using method II seem to stay quite close to the budget throughout time.  

And to a more return-oriented performance analysis, here follows an illustration of the cumulative and abnormal returns (measured using the Fama and French five-factor model) for each combination.
 

The combinations involving model B seem to do quite well, albeit the terrible crash at the beginning of 2022. Specifically, I believe the combination of model B and method II (the non-restricted optimization with standardized weights) to be a very promising candidate moving forward to future investments. Both with respect to returns and by staying within budget.     
 
   

Comments