An open API service indexing awesome lists of open source software.

https://github.com/amanda-ucc/market-tracker

Automated portfolio creator that generates a portoflio which mimics a bench mark index by minimizing the tracking error.
https://github.com/amanda-ucc/market-tracker

beta covariance numpy pandas scipy sharpe-ratio tracking-error variance yfinance

Last synced: 2 months ago
JSON representation

Automated portfolio creator that generates a portoflio which mimics a bench mark index by minimizing the tracking error.

Awesome Lists containing this project

README

          

# Portfolio creation that tracks an index

`market-tracker` creates a portfolio of 10 to 25 stocks, from a larger pool, that is intended to mimic a benchmark index.

Approach taken is to use the previous years data and run a greedy algorithm that minimize the tracking error with respect to the porfolio weights using SciPy optimize.

The tracking error is measured as follows:

$$
TE = \sqrt{\mathrm{Var}(R_p - R_{\text{index}})}
$$

$$
TE = \sqrt{\frac{1}{T} \sum_{t=1}^{T} (R_{p,t} - R_{\text{index},t})^{2}}
$$

The greedy algorithm functions as follows:

Two are included due to constrainsts so we start with those two and determine the next stock to add by minimizing a 3 stock portfolio with respect to the weights for each of the availble candidate stocks. The stock that makes the 3 stock portfolio have the lowest tracking error is included and then we add a 4th stock and so one which produces the lowest tracking error. The algorithm is greedy in that it assumes the path take to get to an optiminal k will be to determine optimal n in order.

```python

def eval_best_among_candidates(
X_all: pd.DataFrame,
y: np.ndarray,
current_selected: list[str],
candidate_pool: list[str],
K: int,

verbose: bool = False,
):
'''Evalutate the best stock from a candidate pool to add to the current selected list.'''

best_te = np.inf
best_ticker = None
best_weights = None

for ticker in candidate_pool:
tickers_sub = current_selected + [ticker]
X = X_all[tickers_sub].to_numpy()

ok, w_opt, te = minimize_te_best_weights(X, y, K, None, None) # find the optimal weights for

# if optimization failed skip this ticker
if not ok:
if verbose:
print(f" Skipping {ticker}: TE optimizer failed.")
continue

# if it the best tracking error than keep it otherwise do not keep it
if te < best_te:
best_te = te
best_ticker = ticker
best_weights = w_opt

if verbose:
print(f" Tested {ticker}: TE={te:.6f}")

return best_ticker, best_weights, best_te

```

After each of the best 10, 11, 12 ... 25 stock portfolio is determined, it is just a matter of choosing which of those 15 is best.

This approach is determined to be better than calculating a portfolio beta closest to 1 as follows.

$$
\min_{\mathbf{w}}
\left|
\sum_{i=1}^{N} w_i \beta_i - 1
\right|
$$

The reasons which involve diversification, compand and industry risk are outlined in the following academic papers.

Academic References:

https://www.sciencedirect.com/science/article/abs/pii/S1062976914000763

https://link.springer.com/article/10.1007/s10957-022-02116-w