Source code for spd_trading.utils.density

import numpy as np
from sklearn.neighbors import KernelDensity

from ..utils.smoothing import bspline


[docs]def density_estimation(sample, X, h, kernel="epanechnikov"): """Kernel Density Estimation over the sample in domain X. Routine for `sklearn.neighbors.KernelDensity`. Args: sample (np.array): Sample of observations. shape: (n_samples, n_features) List of n_features-dimensional data points. Each row corresponds to a single data point. X (np.array): Domain in which the density is estimated. An array of points to query. Last dimension should match dimension of training data. shape: (n_estimates, n_features) h (float): Bandwidth of the kernel. Needs to be chosen wisely or estimated. Sensitive parameter. kernel (str, optional): The kernel to use for the estimation, so far only the Epanechnikov kernel is implemented. Defaults to "epanechnikov". Returns: [np.array]: The array of log(density) evaluations. These are normalized to be probability densities, so values will be low for high-dimensional data. shape: (n_estimates,) """ kde = KernelDensity(kernel=kernel, bandwidth=h).fit(sample.reshape(-1, 1)) log_dens = kde.score_samples(X.reshape(-1, 1)) density = np.exp(log_dens) return density
[docs]def pointwise_density_trafo_K2M(K, q_K, S_vals, M_vals): """Pointwise density transformation from K (Strike Price) to M (Moneyness) domain. M = S/K First, a spline has to be fitted to q_K, so that it is possible to extract the q_K-value at every point of interest, not just at the known points K. Then, it is iterated through the (M, S)-tuples and the density q_K is transformed to q_M. Args: K (np.array): Strike Price values for which the density q_K is know. q_K (np.array): Density values in Strike Price domain. S_vals (array-like): Prices of underlying for the density points. M_vals (array-like): Moneyness values for the density point. Returns: [np.array]: Density values in Moneyness domain. """ _, q_K, _ = bspline(K, q_K, 15) # fit spline to q_K num = len(M_vals) q_pointsM = np.zeros(num) # loop through (M, S)-tuples and calculate the q_M value at this point for i, m, s in zip(range(num), M_vals, S_vals): q_pointsM[i] = s / (m ** 2) * q_K(s / m) return q_pointsM
[docs]def density_trafo_K2M(K, q_K, S): """Density transformation from K (Strike Price) to M (Moneyness) domain. M = S/K First, a spline has to be fitted to q_K, so that it is possible to extract the q_K-value at every point of interest, not just at the known points K. Then, it is iterated through the (M, S)-tuples and the density q_K is transformed to q_M. Args: K (np.array): Strike Price values for which the density q_K is know. q_K (np.array): Density values in Strike Price domain. S (array-like): Prices of underlying for the density points. Returns: [np.array]: Density values in Moneyness domain. """ _, q_K, _ = bspline(K, q_K, 30) num = len(K) M = np.linspace(0.5, 1.5, num) q_M = np.zeros(num) for i, m in enumerate(M): q_M[i] = S / (m ** 2) * q_K(S / m) return M, q_M