Source code for finsim.portfolio.optimize.native.pymetrics


from typing import Literal, Annotated

import numpy as np
from numpy.typing import NDArray
import numba as nb


[docs] @nb.njit def python_sharpe_ratio( weights: Annotated[NDArray[np.float64], Literal["1D array"]], r: Annotated[NDArray[np.float64], Literal["1D array"]], cov: Annotated[NDArray[np.float64], Literal["2D array"]], rf: float ) -> float: """Calculate the Sharpe ratio for a portfolio using Python/Numba. Args: weights: Array of portfolio weights r: Array of expected returns cov: Covariance matrix rf: Risk-free rate Returns: float: Sharpe ratio value """ yieldrate = np.sum(weights * r) sqweights = np.expand_dims(weights, axis=1) @ np.expand_dims(weights, axis=0) volatility = np.sqrt(np.sum(sqweights * cov)) return (yieldrate - rf) / volatility
[docs] @nb.njit def python_mpt_costfunction( weights: Annotated[NDArray[np.float64], Literal["1D array"]], r: Annotated[NDArray[np.float64], Literal["1D array"]], cov: Annotated[NDArray[np.float64], Literal["2D array"]], rf: float, lamb: float, V0: float=10. ) -> float: """Calculate the MPT cost function for a portfolio using Python/Numba. Args: weights: Array of portfolio weights r: Array of expected returns cov: Covariance matrix rf: Risk-free rate lamb: Lambda parameter for the cost function V0: Initial portfolio value (default: 10.0) Returns: float: MPT cost function value """ weightmat = np.expand_dims(weights[:-1], axis=0) c = lamb * V0 return weights[-1]*rf + np.dot(weights[:-1], r) - 0.5*c/V0*(weightmat @ cov @ weightmat.T)[0, 0]
[docs] @nb.njit def python_mpt_entropy_costfunction( weights: Annotated[NDArray[np.float64], Literal["1D array"]], r: Annotated[NDArray[np.float64], Literal["1D array"]], cov: Annotated[NDArray[np.float64], Literal["2D array"]], rf: float, lamb0: float, lamb1: float, V: float=10. ) -> float: """Calculate the MPT entropy cost function for a portfolio using Python/Numba. Args: weights: Array of portfolio weights r: Array of expected returns cov: Covariance matrix rf: Risk-free rate lamb0: Lambda 0 parameter for the entropy cost function lamb1: Lambda 1 parameter for the entropy cost function V: Portfolio value parameter (default: 10.0) Returns: float: MPT entropy cost function value """ weightmat = np.expand_dims(weights[:-1], axis=0) c0 = lamb0 * V c1 = lamb1 * V yield_val = weights[-1]*rf + np.dot(weights[:-1], r) cov_val = - 0.5 * c0 / V * (weightmat @ cov @ weightmat.T)[0, 0] sumweights = np.sum(weights[:-1]) entropy_val = - 0.5 * c1 / V * np.sum(weights[:-1] * (np.log(weights[:-1]) - np.log(sumweights))) / sumweights return yield_val + cov_val + entropy_val