Source code for tensorcircuit.applications.finance.portfolio
"""
Supplementary functions for portfolio optimization
"""
from typing import Any
import numpy as np
Array = Any
Tensor = Any
[docs]def QUBO_from_portfolio(cov: Array, mean: Array, q: float, B: int, t: float) -> Tensor:
"""
convert portfolio parameters to a Q matrix
:param cov: n-by-n covariance numpy array
:param mean: numpy array of means
:param q: the risk preference of investor
:param B: budget
:param t: penalty factor
:return Q: n-by-n symmetric Q matrix
"""
n = cov.shape[0]
R = np.diag(mean)
S = np.ones((n, n)) - 2 * B * np.diag(np.ones(n))
Q = q * cov - R + t * S
return Q
[docs]class StockData:
"""
A class for converting real-world stock data to an annualized covariance matrix and annualized return.
Attributes:
- data: A list of continuous stock data in the same time span.
- n_stocks: The number of stocks in the data.
- n_days: The number of trading days in the data.
Methods:
- __init__(self, data): Initializes the StockData object.
- get_return(self, decimals=5): Calculates the annualized return.
- get_covariance(self, decimals=5): Calculates the annualized covariance matrix.
"""
[docs] def __init__(self, data: Tensor):
"""
Initializes the StockData object.
:param data: A list of continuous stock data in the same time span.
"""
self.data = data
self.n_stocks = len(data)
# Check the number of days
n_days = [len(i) for i in data]
if max(n_days) != (sum(n_days) / len(n_days)):
raise Exception("Timespan of stocks should be the same")
self.n_days = len(data[1])
# Calculate the daily percentage price change
self.daily_change = [
np.diff(data[i][:]) / data[i][:-1] for i in range(self.n_stocks)
]
[docs] def get_return(self, decimals: int = 5) -> Any:
"""
Calculates the annualized return (mu).
:param decimals: Number of decimal places to round the result to (default: 5).
:return: The annualized return as an array rounded to the specified number of decimals.
"""
change = [[j + 1 for j in i] for i in self.daily_change]
ret = np.prod(change, axis=1) ** (252 / self.n_days)
return ret.round(decimals)
[docs] def get_covariance(self, decimals: int = 5) -> Tensor:
"""
Calculates the annualized covariance matrix (sigma).
:param decimals: Number of decimal places to round the result to (default: 5).
:return: The annualized covariance matrix rounded to the specified number of decimals.
"""
mean = np.mean(self.daily_change, axis=1)
relative_change = [
[j - mean[i] for j in self.daily_change[i]] for i in range(6)
]
cov = 252 / self.n_days * np.dot(relative_change, np.transpose(relative_change))
return cov.round(decimals)