Histogram: private API
PortfolioOptimisers.Int_Bin — Type
const Int_Bin = Union{<:AbstractBins, <:Integer}Alias for a histogram binning algorithm or an integer number of bins.
Matches either an AbstractBins algorithm (auto-selecting bin counts) or a plain Integer (fixed number of bins). Used in histogram-based mutual information and variation of information calculations.
Related
PortfolioOptimisers.calc_hist_data — Function
calc_hist_data(xj::VecNum, xi::VecNum, bins::Integer)Compute histogram-based marginal and joint distributions for two variables.
This function computes the normalised histograms (probability mass functions) for two variables xj and xi using the specified number of bins, as well as their joint histogram. It returns the marginal entropies and the joint histogram, which are used in mutual information and variation of information calculations.
A bin is closed on the left, so the lower edge is the minimum itself and needs no widening. The upper edge is exclusive, so it is nextfloat of the maximum, one unit in the last place above it at every magnitude. The largest observation therefore falls strictly inside the last bin whatever the magnitude of the data, and a constant column gives an entropy of zero rather than NaN.
Algorithm
- Add one to
bins, givingbp1, the number of bin edges. - Build the edge range of
xjfromminimum(xj)tonextfloat(maximum(xj)), withbp1points. Repeat forxi. - Bin
xjover its own edges, giving the countshx, and dividehxby its own sum to make it a probability mass function. - Repeat step 3 for
xi, givinghy. - Take the Shannon entropy of
hxintoex, and ofhyintoey. - Bin the pair over both edge ranges, giving the joint counts
hxy. It is left unnormalised, becauseintrinsic_mutual_infonormalises it itself.
Arguments
xj: Data vector for variablej.xi: Data vector for variablei.bins: Number of bins to use for the histograms.
Returns
ex::Number: Shannon entropy of the marginal probability mass function ofxj, in nats.ey::Number: Shannon entropy of the marginal probability mass function ofxi, in nats.hxy::Matrix{<:Number}: Joint histogram (counts, not normalised to probability).
Related
PortfolioOptimisers.intrinsic_mutual_info — Function
intrinsic_mutual_info(X::MatNum)Compute the intrinsic mutual information from a joint histogram.
This function computes the mutual information between two variables given their joint histogram matrix X. It is used as a core step in information-theoretic measures such as mutual information and variation of information.
Intrinsic names the estimate itself: the quantity the joint histogram carries, before mutual_info divides it by a marginal entropy and before either matrix-valued measure clamps it. It is therefore in nats, it is not bounded above by one, and it is the value that mutual_info returns when normalise is false. It is not the intrinsic conditional information of secret-key agreement, which is a different quantity under the same word.
Mathematical definition
Given the joint histogram $\mathbf{X}$ (unnormalised counts), with marginals $p_i = \sum_j X_{ij} / n$ and $p_j = \sum_i X_{ij} / n$:
\[\begin{align} \hat{I}(X; Y) &= \sum_{i,j:\, X_{ij} > 0} \frac{X_{ij}}{n} \log\!\left(\frac{X_{ij} / n}{p_i \, p_j}\right)\,. \end{align}\]
Where:
- $\hat{I}(X; Y)$: Estimated mutual information between $X$ and $Y$.
- $X_{ij}$: Joint histogram count at bin $(i, j)$.
- $n = \sum_{i,j} X_{ij}$: Total count.
- $p_i = \sum_j X_{ij} / n$, $p_j = \sum_i X_{ij} / n$: Marginal probabilities.
A bin the pair never visits contributes nothing, because $p \log p$ tends to zero as $p$ does. The sum therefore runs over the non-empty bins alone. When either axis has a single bin the two variables are indistinguishable under the binning, and the estimate is zero.
Algorithm
- Sum
Xover its columns intop_i, and over its rows intop_j. Both are unnormalised marginal counts. - When either marginal has length one, return zero.
- Find the indices of the non-zero entries of
Xintomask, and read those entries into the vectornz. - Sum
nzintonz_sum, the total count, and dividenzby it, giving the joint probabilitiesnz_nm. - Take the outer product of the two marginal counts at the masked indices into
outer, and turn it into the logarithm of the product of the marginal probabilities,log_outer, by subtracting the logarithm of each marginal total. - Form the per-bin contributions
mifromnz_nmand the two logarithms, and set to zero every contribution whose magnitude is below the machine epsilon. - Return the sum of
mi.
Arguments
X: Joint histogram matrix.
Returns
mi::Number: The intrinsic mutual information between the two variables, in nats.
Related
References
- [24] C. E. Shannon. A mathematical theory of communication. The Bell System Technical Journal 27, 379–423 (1948).
PortfolioOptimisers.variation_info — Function
variation_info(X::MatNum, bins::Int_Bin = HacineGharbiRavier(),
normalise::Bool = true)Compute the variation of information (VI) matrix for a set of variables.
This function computes the pairwise variation of information between all columns of the data matrix X, using histogram-based entropy and mutual information estimates. VI quantifies the amount of information lost and gained when moving from one variable to another, and is a true metric on the space of discrete distributions: it is non-negative, it is zero exactly when the two variables agree, it is symmetric, and it satisfies the triangle inequality. mutual_info is the complementary measure and is not a metric — it grows with agreement rather than with disagreement, and its diagonal is the entropy rather than zero.
Mathematical definition
Let $H(X)$, $H(Y)$ denote the marginal Shannon entropies and $I(X;Y)$ the mutual information. The variation of information is:
\[\begin{align} \mathrm{VI}(X, Y) &= H(X) + H(Y) - 2\,I(X;Y)\,. \end{align}\]
Where:
- $\mathrm{VI}(X, Y)$: Variation of information between $X$ and $Y$.
- $H(X)$, $H(Y)$: Marginal Shannon entropies.
- $I(X;Y)$: Mutual information.
When normalise = true, it is divided by the joint entropy $H(X,Y) = H(X) + H(Y) - I(X;Y)$:
\[\begin{align} \widetilde{\mathrm{VI}}(X, Y) &= \frac{H(X) + H(Y) - 2\,I(X;Y)}{H(X) + H(Y) - I(X;Y)}\,. \end{align}\]
Where:
- $\widetilde{\mathrm{VI}}(X, Y)$: Normalised variation of information.
- $H(X,Y) = H(X) + H(Y) - I(X;Y)$: Joint entropy.
The divisor is the joint entropy, which keeps the normalised form a metric on $[0, 1]$. Equation 6.25 of the source divides by $\max(H(X), H(Y))$ instead, which is bounded by the same interval but is not a metric.
Algorithm
- Read the shape of
XintoT, the number of observations, andN, the number of variables. - Allocate the
N × Nresultvar_mtx. - For each variable
j, write an exact zero atvar_mtx[j, j]. $\mathrm{VI}(X, X)$ is zero by definition, and the histogram estimate of $I(X; X)$ does not reproduce the estimate of $H(X)$ bit for bit, so estimating the self pair leaves roughly1e-16on the diagonal. That is enough to stop the result being a distance matrix, and skipping the self pair also savesNhistogram computations. - For each pair
(j, i)below the diagonal, take the bin count fromcalc_num_bins, givingnbins. - Take the two marginal entropies
exandeyand the joint histogramhxyfromcalc_hist_data. - Take the mutual information of
hxyfromintrinsic_mutual_info, givingmut_ixy, and apply the definition above, givingvar_ixy. - When
normaliseis true, dividevar_ixyby the joint entropyvxy. - Clamp
var_ixybelow at zero, and write it into bothvar_mtx[j, i]andvar_mtx[i, j].
Arguments
X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.bins: Binning algorithm or fixed number of bins.normalise: Whether to normalise the mutual and/or variation of information calculation.
Returns
var_mtx::Matrix{<:Number}: Symmetric matrix of pairwise variation of information values, with an exactly zero diagonal. In nats whennormaliseisfalse, and dimensionless on[0, 1]when it istrue.
Related
References
PortfolioOptimisers.mutual_info — Function
mutual_info(X::MatNum, bins::Int_Bin = HacineGharbiRavier(),
normalise::Bool = true)Compute the mutual information (MI) matrix for a set of variables.
This function computes the pairwise mutual information between all columns of the data matrix X, using histogram-based entropy and mutual information estimates. MI quantifies the amount of shared information between pairs of variables, and is widely used in information-theoretic analysis of dependencies.
Mutual information is a measure of agreement and is not a metric: it grows with dependence rather than with distance, and its diagonal carries the marginal entropy rather than zero. variation_info is the metric of the pair. The diagonal is estimated here, not pinned, so it is the marginal entropy in nats when normalise is false and one when it is true.
Mathematical definition
Mutual information between assets $i$ and $j$:
\[\begin{align} I(X_i; X_j) &= H(X_i) + H(X_j) - H(X_i, X_j) = \sum_{x,y} p(x,y) \log\frac{p(x,y)}{p(x)\,p(y)}\,. \end{align}\]
Where:
- $I(X_i; X_j)$: Mutual information between assets $i$ and $j$.
- $H(X_i)$, $H(X_j)$: Marginal Shannon entropies.
- $H(X_i, X_j)$: Joint entropy.
- $p(x,y)$: Joint probability mass function.
When normalise = true, the MI is normalised by the minimum marginal entropy:
\[\begin{align} \tilde{I}(X_i; X_j) &= \frac{I(X_i; X_j)}{\min\bigl(H(X_i),\, H(X_j)\bigr)}\,. \end{align}\]
Where:
- $\tilde{I}(X_i; X_j)$: Normalised mutual information.
The smaller marginal entropy is the largest value the mutual information of the pair can take, so the normalised form is bounded by $[0, 1]$ and reaches one exactly when one variable determines the other.
Algorithm
- Read the shape of
XintoT, the number of observations, andN, the number of variables. - Allocate the
N × Nresultmut_mtx. - For each pair
(j, i)on or below the diagonal, take the bin count fromcalc_num_bins, givingnbins. - Take the two marginal entropies
exandeyand the joint histogramhxyfromcalc_hist_data. - Take the mutual information of
hxyfromintrinsic_mutual_info, givingmut_ixy. - When
normaliseis true, dividemut_ixyby the smaller ofexandey. - Clamp
mut_ixybelow at zero, and write it into bothmut_mtx[j, i]andmut_mtx[i, j].
Arguments
X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.bins: Binning algorithm or fixed number of bins.normalise: Whether to normalise the mutual and/or variation of information calculation.
Returns
mut_mtx::Matrix{<:Number}: Symmetric matrix of pairwise mutual information values. In nats whennormaliseisfalse, and dimensionless on[0, 1]when it istrue.
Related
variation_infomutual_variation_infocalc_hist_datacalc_num_binsintrinsic_mutual_infoInt_BinMutualInfoCovariance
References
PortfolioOptimisers.mutual_variation_info — Function
mutual_variation_info(X::MatNum, bins::Int_Bin = Knuth(), normalise::Bool = true)Compute the pairwise mutual information and variation of information matrices from a data matrix.
Both matrices come from one pass over the pairs, so the two share a bin count and a joint histogram per pair. The result is what mutual_info and variation_info return, and the two normalisers differ: mutual information is divided by the smaller marginal entropy, variation of information by the joint entropy. The default bins is Knuth here and HacineGharbiRavier in the other two, so the three agree only when bins is given.
Mathematical definition
\[\begin{align} I(X_i; X_j) &= H(X_i) + H(X_j) - H(X_i, X_j)\,, \\ \mathrm{VI}(X_i, X_j) &= H(X_i) + H(X_j) - 2\,I(X_i; X_j)\,. \end{align}\]
When normalise = true, each is divided by its own normaliser:
\[\begin{align} \tilde{I}(X_i; X_j) &= \frac{I(X_i; X_j)}{\min\bigl(H(X_i),\, H(X_j)\bigr)}\,, \\ \widetilde{\mathrm{VI}}(X_i, X_j) &= \frac{\mathrm{VI}(X_i, X_j)}{H(X_i) + H(X_j) - I(X_i; X_j)}\,. \end{align}\]
Where:
- $I(X_i; X_j)$: Mutual information between assets $i$ and $j$.
- $\mathrm{VI}(X_i, X_j)$: Variation of information between assets $i$ and $j$.
- $H(X_i)$, $H(X_j)$: Marginal Shannon entropies.
- $H(X_i, X_j) = H(X_i) + H(X_j) - I(X_i; X_j)$: Joint entropy.
- $\tilde{I}(X_i; X_j)$: Normalised mutual information.
- $\widetilde{\mathrm{VI}}(X_i, X_j)$: Normalised variation of information.
Algorithm
- Read the shape of
XintoT, the number of observations, andN, the number of variables. - Allocate the two
N × Nresultsmut_mtxandvar_mtx. - For each pair
(j, i)on or below the diagonal, take the bin count fromcalc_num_bins, givingnbins. - Take the two marginal entropies
exandeyand the joint histogramhxyfromcalc_hist_data. - Take the mutual information of
hxyfromintrinsic_mutual_info, givingmut_ixy, and formvar_ixyfrom it and the two entropies. - When
normaliseis true, dividevar_ixyby the joint entropyvxyandmut_ixyby the smaller ofexandey. - Clamp both below at zero, and write each into both of its symmetric positions.
- After the inner loop, write an exact zero at
var_mtx[j, j], for the reasonvariation_infogives.mut_mtx[j, j]keeps its estimate, because $I(X; X) = H(X)$ is a real value there rather than a zero.
Arguments
X: Data matrixobservations × assetsif thedimskeyword does not exist ordims = 1,assets × observationswhendims = 2.bins: Binning algorithm or fixed number of bins.normalise: Whether to normalise the mutual and/or variation of information calculation.
Returns
mut_mtx::Matrix{<:Number}: Symmetric matrix of pairwise mutual information values, whose diagonal is the marginal entropy whennormaliseisfalseand one when it istrue.var_mtx::Matrix{<:Number}: Symmetric matrix of pairwise variation of information values, with an exactly zero diagonal.
Related
References
References
- [5]
- D. Cajas. Advanced Portfolio Optimization: A Cutting-edge Quantitative Approach (Springer Nature Switzerland, 2025).
- [24]
- C. E. Shannon. A mathematical theory of communication. The Bell System Technical Journal 27, 379–423 (1948).