quanttoolbox.sustainable_finance¶
sustainable_finance.risk¶
Python alternatives
Keep — sector-decomposed quadratic-form risk building blocks (quadratic_form, quadratic_form_risk) and portfolio/sector modified-duration & DTS aggregation (bond_portfolio_metrics), generic to sector-based portfolio risk models. No general-purpose equivalent found; see Library alternatives for the full reasoning.
quanttoolbox.sustainable_finance.risk
¶
Generic quadratic-form risk building blocks used across sector-based
portfolio risk models -- e.g. bond-portfolio modified-duration/DTS risk in
quanttoolbox.bond.pricing, which these functions were factored out of.
Ported from HSF toolbox hsf/{quadratic_form,quadratic_form_risk,
bond_portfolio_metrics}.m.
Translation notes:
quadratic_form_risk.mbuilds a quadratic-form penalty for deviating a sector-level risk measure (e.g. modified duration) from per-sector targets: for each sector j it contributes an outer-product termQ_j = (s_j * risk)(s_j * risk)'(s_jthe sector-j 0/1 indicator), summed across sectors into a single (Q, R, c) triple. Kept as a general-purpose helper rather than folded intobond/pricing.py, since the original file lives inhsf/(sustainable-finance-general), notbond/, and nothing here is bond-specific.
BondPortfolioMetrics(md_portfolio, dts_portfolio, md_by_sector, dts_by_sector, unique_sector)
dataclass
¶
Portfolio- and sector-level modified duration (MD) and duration-times-spread (DTS).
QuadraticFormResult(qf, q, r, c, n, n_sector, unique_sector, q_j, r_j, c_j)
dataclass
¶
Sector-decomposed quadratic-risk form: qf = 0.5 w'Qw - w'R + c,
with q_j/r_j/c_j holding each sector's own contribution to
Q/R/c (summed into q/r/c).
bond_portfolio_metrics(sector, md, dts, w)
¶
Portfolio- and sector-level modified duration and DTS, weighted by portfolio weights w.
Original: hsf/bond_portfolio_metrics.m
Source code in src/quanttoolbox/sustainable_finance/risk.py
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
quadratic_form(x, q, r, c)
¶
Evaluate the quadratic form qf(x) = 0.5 x'Qx - x'R + c.
Original: hsf/quadratic_form.m
Source code in src/quanttoolbox/sustainable_finance/risk.py
27 28 29 30 31 32 33 34 35 | |
quadratic_form_risk(sector, risk, risk_star, w=None)
¶
Build a quadratic-form penalty for a sector-level risk measure (e.g.
modified duration or DTS) deviating from per-sector targets
risk_star, and (if w is given) evaluate it at portfolio weights w.
Original: hsf/quadratic_form_risk.m
Source code in src/quanttoolbox/sustainable_finance/risk.py
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
sustainable_finance.carbon¶
Python alternatives
Keep — closed-form cumulative-emissions ("carbon budget") integrals under linear, compound-decline, piecewise-linear, and GDP-adjusted trajectories. No general-purpose equivalent found; the piecewise closed-form sum and each other formula are cross-checked against scipy.integrate.quad in this module's tests. Two near-duplicate originals (carbon_budget_linear.m/carbon_budget_linear_trend.m) were merged, and one (carbon_budget_linear_reduction.m) was recognized as a strict special case of carbon_budget_Reduction.m and not ported separately — see the module docstring.
quanttoolbox.sustainable_finance.carbon
¶
Cumulative carbon-budget calculations: the total emissions integral of
CE(s) ds over [t0, t] under various assumed emissions trajectories
CE(s) (constant decline rates, GDP-adjusted compound decline, and
piecewise-linear historical/target paths).
Ported from HSF toolbox hsf/{carbon_budget_linear,
carbon_budget_linear_trend,carbon_budget_linear_reduction,
carbon_budget_piecewise,carbon_budget_compound_reduction,
carbon_budget_Reduction}.m.
Translation notes:
carbon_budget_linear.mandcarbon_budget_linear_trend.mare the exact same computation (beta0 * (t - t0) + 0.5 * beta1 * (t^2 - t0^2), the closed-form integral ofbeta0 + beta1 * s) -- the original files differ only in which of their two outputs (closed form vs. ascipy.integrate.quad-equivalent numerical cross-check) comes first. Merged into one function,carbon_budget_linear.carbon_budget_linear_reduction.mis a strict special case ofcarbon_budget_Reduction.m's default ("linear rate") method, under the substitutionr = reduction * ce_t0(verified algebraically and in tests) -- not ported as a separate function; usecarbon_budget(t0, t, ce_t0, r=reduction * ce_t0, method=1)instead.- Every original file returns both a closed-form value and a
integral()-computed numerical cross-check of the same quantity (a self-verification pattern, not two different pieces of information). Only the closed-form value is exposed here; the numerical cross-check is instead used in this module's own test suite (viascipy.integrate.quad), which is a strictly better place for a redundant-by-construction correctness check than a return value every caller pays for. - MATLAB's
integralmaps toscipy.integrate.quadwhere a numerical integral genuinely differs from a closed form (carbon_budget_piecewise's piecewise-linear-interpolated integral, verified in tests against the closed-form sum).
carbon_budget(t0, t, ce_t0, r, method=1)
¶
Cumulative emissions over [t0, t] starting from CE(t0), declining (or
growing) at rate r under one of three conventions:
- method=1 (default, "linear rate"): CE(s) = CE(t0) - r * (s - t0)
- method=2 ("compound rate"): CE(s) = CE(t0) * (1 - r)^(s - t0)
- method=3 ("growth rate"): CE(s) = CE(t0) * exp(-r * (s - t0))
Original: hsf/carbon_budget_Reduction.m
Source code in src/quanttoolbox/sustainable_finance/carbon.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | |
carbon_budget_compound_reduction(t0, t, delta_r, r_minus, ce_t0, g_y=None, discrete=False)
¶
Cumulative emissions over [t0, t], for CE(s) declining at compound
rate delta_r from an initial level CE(t0) * (1 - r_minus),
optionally compounded against a GDP growth rate g_y (CE(s) then
grows/shrinks at the net rate of decarbonization vs. growth).
discrete=False (default, matches the original) treats CE(s) as
continuous and integrates the closed-form geometric series over
[t0, t]. discrete=True instead sums CE(s) at each integer year
s = t0, t0+1, ..., t (t0 and t must be integers) -- added for
callers that budget year-by-year rather than continuously (e.g.
HSF-Notebooks chapter 11g); the two conventions can differ by several
percent on the same inputs, so this is a real modeling choice, not a
numerical-precision detail.
Original: hsf/carbon_budget_compound_reduction.m (discrete=True is
not part of the original, which is continuous-only)
Source code in src/quanttoolbox/sustainable_finance/carbon.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | |
carbon_budget_linear(t0, t, beta0, beta1)
¶
Cumulative emissions over [t0, t] under a linear emissions trend CE(s) = beta0 + beta1 * s.
Original: hsf/carbon_budget_linear.m (identical to hsf/carbon_budget_linear_trend.m -- see module docstring)
Source code in src/quanttoolbox/sustainable_finance/carbon.py
43 44 45 46 47 48 49 50 | |
carbon_budget_piecewise(t0, t, t_k, ce_k)
¶
Cumulative emissions over [t0, t], for a piecewise-linear-interpolated
emissions trajectory given at knots (t_k, ce_k).
Original: hsf/carbon_budget_piecewise.m (this is CB1/CB3, the two
closed-form sums the original computes -- verified algebraically
identical, see this module's tests)
Source code in src/quanttoolbox/sustainable_finance/carbon.py
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
sustainable_finance.esg¶
Python alternatives
Keep — Roncalli's implied-ESG-beta minimum-variance tilt (esg_beta_star, esg_minimum_variance) and Pedersen-Fitzgibbons-Pomorski (2021)'s ESG-efficient-frontier portfolio (pedersen_portfolio). No general-purpose equivalent found. hsf/cdp_filter.m (a CDP-dataset-specific data-loading/filtering script) was not ported — see the module docstring.
quanttoolbox.sustainable_finance.esg
¶
ESG-tilted portfolio construction: the "implied ESG beta" a minimum-variance investor effectively targets (Roncalli's ESG beta-star model), the resulting minimum-variance-plus-ESG-tilt portfolio, Pedersen, Fitzgibbons & Pomorski (2021)'s ESG-efficient-frontier portfolio, ESG score-bucket transition/turnover matrices, and a Monte Carlo power-law-weighted-portfolio-score simulation.
Ported from HSF toolbox hsf/{compute_esg_beta_star,
compute_esg_minimum_variance,compute_pedersen_portfolio}.m.
esg_transition_matrix and mc_weighted_score have no standalone .m
source in hfs-archive -- see their own docstrings -- and are instead
promoted from HSF-Notebooks chapter 16a.
Translation notes:
hsf/cdp_filter.m(CDP -- Carbon Disclosure Project -- data loading and regional/sectoral filtering, plus trend estimation) is not ported: it loads a specificdata/chap9_cdp3.matdataset this package does not ship, and its region/sector categories are hardcoded to that one textbook chapter's data -- a data-loading script tied to one dataset, not a general-purpose library function (same category as the untranslatedtools/display helpers noted in docs/migration_map.md).compute_esg_beta_star.m's locale = ones(n,1)is unrelated tocompute_esg_minimum_variance.m'separameter (a universe-selection mask) despite the shared MATLAB variable name -- kept as an internal local (ones_n) here to avoid the naming collision.- MATLAB's
logical(e)(boolean-mask submatrix selection) isSigma[mask][:, mask]in numpy, wheremask = e.astype(bool).
EsgMinimumVarianceResult(x, sigma, sigma_x, beta_star, beta_esg_star, sigma_tilde_matrix, x_tilde)
dataclass
¶
Minimum-variance-plus-ESG-tilt portfolio weights x, the implied
covariance matrix sigma, its portfolio volatility sigma_x, the
beta-star pair the tilt was built from, and (sigma_tilde_matrix,
x_tilde) the plain (untilted) minimum-variance portfolio restricted
to the selected universe, for comparison.
EsgTransitionMatrixResult(p, cdf, to, to_system)
dataclass
¶
ESG score-bucket transition probabilities p (p[j, k] = the
probability of moving from bucket j to bucket k on remeasurement),
the equilibrium bucket probabilities cdf, the per-bucket turnover
to = 1 - diag(p), and the aggregate (probability-weighted) turnover
to_system.
PedersenPortfolioResult(w, w_r, sigma_bar, s_bar, lambda1, lambda2, pi_w, sigma_w, s_w, sr_w, c_x_y)
dataclass
¶
Pedersen-Fitzgibbons-Pomorski ESG-efficient portfolios: w (shape
(n_assets, n_scenarios)) holds one portfolio per (sigma_bar, s_bar)
scenario, with w_r its residual (cash/risk-free) weight and the rest
the per-scenario risk/return/ESG-score/Sharpe-ratio diagnostics.
esg_beta_star(beta, sigma_m, beta_esg, sigma_esg, sigma_tilde)
¶
The "implied" market beta and ESG beta (beta_star,
beta_esg_star) at which a minimum-variance investor's residual risk
is fully diversified, given per-asset market/ESG factor loadings
(beta, beta_esg), factor volatilities (sigma_m, sigma_esg), and
idiosyncratic volatilities (sigma_tilde).
Original: hsf/compute_esg_beta_star.m
Source code in src/quanttoolbox/sustainable_finance/esg.py
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
esg_minimum_variance(beta, sigma_m, beta_esg, sigma_esg, sigma_tilde, e=None)
¶
The minimum-variance portfolio tilted toward the ESG beta-star of
esg_beta_star, restricted to an optional universe-selection mask e
(default: the full universe).
Original: hsf/compute_esg_minimum_variance.m
Source code in src/quanttoolbox/sustainable_finance/esg.py
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
esg_transition_matrix(s, sigma)
¶
The bucket-to-bucket transition probability matrix and turnover of
an ESG score-bucket scheme with cut points s (K = 1 + len(s)
buckets, delimited by -inf = s_0 < s_1 < ... < s_{K-1} < s_K = +inf),
under a "true" ESG factor g1 ~ N(0, 1) and a noisy remeasurement
g2 = g1 + sigma*eps (eps ~ N(0, 1) independent of g1), so
(g1, g2) is bivariate normal with Cov(g1, g2) = 1 and
Var(g2) = 1 + sigma**2.
p[j, k] = P(g2 in bucket k | g1 in bucket j) is computed via the
two-sided bivariate-normal rectangle probability (_rectangle_prob).
to = 1 - diag(p) is the per-bucket turnover (probability of not
staying in the same bucket); to_system = sum(cdf * to) is the
overall, probability-weighted turnover.
Not ported from a standalone MATLAB HSF toolbox library function --
no hsf/esg_transition_matrix.m file exists in hfs-archive. The
identical algorithm does appear as a local (embedded) function inside
HSF/16. Exercise Solution/chap16_chap2_exercise4.m, of which
HSF-Notebooks chapter 16a is itself a direct Python port; promoted
here from that notebook.
Source code in src/quanttoolbox/sustainable_finance/esg.py
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 | |
mc_weighted_score(alpha_vec, nS, n, rng, g1=None, g2=None)
¶
Monte Carlo simulation of S(x) = sum(x*s), the score of a
power-law-weighted portfolio, for nS draws at once (vectorized over
the draw axis), for each power-law exponent in alpha_vec.
Portfolio weights x are built by drawing n iid uniforms u1,
raising them to the power 1/alpha (a power-law reweighting of an
otherwise-uniform allocation), and normalizing to sum to 1.
g1=None(default):u1and the per-asset scoressare drawn fresh and independent of one another (suncorrelated with the weightsx).g1given:u1 = Phi(g1)(so the weights are tilted from the standard-normal factorg1) ands = g2-- lettingg1/g2be correlated standard normals induces a correlation between the weights and the scores.
Not ported from a standalone MATLAB HSF toolbox library function --
no .m file in hfs-archive implements this as a reusable function.
HSF/16. Exercise Solution/chap16_chap2_exercise4.m performs the same
Monte Carlo computation inline, in per-scenario loops (Questions
2.e/2.g/2.h); HSF-Notebooks chapter 16a factored that inline
computation into this function, and it is promoted here from that
notebook.
Source code in src/quanttoolbox/sustainable_finance/esg.py
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | |
pedersen_portfolio(mu, r, sigma, s, sigma_bar, s_bar)
¶
Pedersen, Fitzgibbons & Pomorski (2021)'s ESG-efficient-frontier
portfolio: mean-variance-optimal subject to a target volatility
sigma_bar and a target portfolio ESG score s_bar, swept over one
portfolio per (sigma_bar, s_bar) pair (broadcast to a common
length).
Original: hsf/compute_pedersen_portfolio.m
Source code in src/quanttoolbox/sustainable_finance/esg.py
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | |
sustainable_finance.climate¶
Python alternatives
Keep — the DICE (Dynamic Integrated Climate-Economy) model's carbon-cycle/temperature state-transition matrices and forward simulation. No general-purpose equivalent found; physical constants are Nordhaus's DICE-2016 calibration, hardcoded as in the original.
quanttoolbox.sustainable_finance.climate
¶
The DICE (Dynamic Integrated Climate-Economy) model's carbon-cycle and temperature submodules: the state-transition matrices linking industrial emissions to atmospheric carbon concentration and global temperature, and a full forward simulation of both given exogenous GDP and mitigation-rate paths.
Ported from HSF toolbox hsf/{dice_temperature_matrix,
dice_temperature_simulation}.m.
Translation notes:
- All physical constants (carbon-cycle transfer coefficients, radiative forcing parameters, initial 2015 conditions) are Nordhaus's DICE-2016 calibration, hardcoded in the original -- kept as-is (not exposed as parameters), matching the original's scope.
dice_temperature_simulation.maccepts aparametersargument that is never read anywhere in the function body (a vestigial/dead parameter in the original) -- dropped here rather than carried forward as a do-nothing kwarg.Y_fn/mu_fn(GDP and mitigation-rate paths, as functions of time) are plain Python callables, matching the original's function-handle arguments exactly.
DiceTemperatureMatrices(phi_cc, b_cc, xi_t, b_t, xi_t_5, b_t_5, xi1, xi2, xi3, xi4, c_at, c_lo, lambda_, beta)
dataclass
¶
The DICE carbon-cycle (phi_cc, b_cc) and temperature (xi_t,
b_t) state-transition matrices for one time step of length
delta_t, plus the intermediate physical constants they were built
from.
dice_temperature_matrix(delta_t, scale=None, method=1)
¶
Build the DICE model's carbon-cycle and temperature state-transition
matrices for a time step of length delta_t.
scale converts delta_t into seconds (default: delta_t is in
years, scale = 365.25 * 24 * 3600). method=2 instead derives xi_t
from the standard 5-year-step calibration matrix via a matrix power
(xi_t_5 ** (delta_t_years / 5)) rather than reconstructing it from
the underlying continuous-time physical constants.
Original: hsf/dice_temperature_matrix.m
Source code in src/quanttoolbox/sustainable_finance/climate.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
dice_temperature_simulation(t0, t_end, delta_t, y_fn, mu_fn, numeric=False)
¶
Forward-simulate the DICE model's industrial emissions, carbon-cycle
concentrations, radiative forcing, and temperature, from t0 to
t_end in steps of delta_t, given a GDP path y_fn(t) and a
mitigation-rate path mu_fn(t).
numeric=True uses the 5-year-calibration temperature matrices
(xi_t_5, b_t_5) directly instead of the continuous-time
reconstruction from dice_temperature_matrix.
Returns an array of shape (n_iters + 1, 10) with columns
[t, CE_t, sigma_t, CC_AT_t, CC_UP_t, CC_LO_t, F_EX_t, F_RAD_t,
T_AT_t, T_LO_t].
Original: hsf/dice_temperature_simulation.m (the unused parameters
argument is dropped -- see module docstring)
Source code in src/quanttoolbox/sustainable_finance/climate.py
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | |
sustainable_finance.ecology¶
Python alternatives
Keep — species-area/endemics-area relationships, species-abundance-distribution histogram binning (including Preston's log2 "octave" classes), and Hurlbert's rarefaction estimator. No general-purpose equivalent found (these are ecology-specific biodiversity measures, not general statistics).
quanttoolbox.sustainable_finance.ecology
¶
Species-area/endemics-area relationships, species-abundance distributions, Hurlbert's rarefaction estimator, and a colonization- extinction equilibrium model's net species-richness growth rate -- classic biodiversity measures from ecology, used in this toolbox's biodiversity-risk chapters.
Ported from HSF toolbox hsf/{species_area_relationship,
endemics_area_relationship,species_abundance_distribution,hurlbert}.m.
fn_delta_t has no standalone .m source in hfs-archive -- see its own
docstring -- and is instead promoted from HSF-Notebooks chapter 16c.
Translation notes:
species_area_relationship/endemics_area_relationshipacceptaas a scalar or array of target sub-areas, and can work either directly from per-species individual countsn_i, or from a pre-binned species-abundance histogram (s_j= number of species with exactlyjindividuals) -- typically the output ofspecies_abundance_distribution. Passs_j=Nonefor the first mode.species_abundance_distribution.m's three-way branch on its second argument (brk) is preserved as three explicit modes rather than MATLAB's type-based dispatch:breaks=None(unique-count histogram),breaks="octave"(Preston's log2 "octave" abundance classes), orbreaks=<array>(custom breakpoints). The"octave"and<array>modes' bucket-assignment rule was corrected to match numpy's ownnp.histogramhalf-open-bin convention exactly (floor(log2(n))for octaves;np.histogram(n_i, bins=[0, *breaks])for custom breakpoints) -- the original bucket-assignment rule here used a different, non-numpy-native inclusive convention, which HSF-Notebooks chapter 05c's independent reimplementation of this same function was found to disagree with on real (Whittaker/BCI) survey data before this fix; seespecies_abundance_distribution's own docstring.hurlbert.m'smethod=2(log-gamma) branch is numerically more stable thanmethod=1's directscipy.special.combratio for large sample sizes (avoids overflow in the individual binomial coefficients); both compute the same quantity and are verified to agree in this module's tests.
endemics_area_relationship(n_i, s_j, area_total, area)
¶
Expected number of species confined entirely within a sub-area
area out of a total surveyed area area_total ("endemics"), given
either per-species individual counts n_i (s_j=None), or a
species-abundance histogram s_j.
Original: hsf/endemics_area_relationship.m
Source code in src/quanttoolbox/sustainable_finance/ecology.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | |
fn_delta_t(S_t, lambda_0, beta1, mu_s, beta2, beta3, beta4, S_s)
¶
Net species-richness growth rate delta(S) = lambda(S) - mu(S) of a
colonization-extinction equilibrium model (the theory of island
biogeography, TIB), where mu(S) = mu^long(S) + mu^short(S):
lambda(S): colonization rate,=lambda_0atS=0, decaying to0at the saturation richnessS=S_s.mu^long(S): long-term extinction rate,=0atS=0, rising tomu_satS=S_s.mu^short(S) = beta3*lambda(S)*exp(-beta4*S): a short-term extinction component proportional to the colonization rate (recently-arrived species are more extinction-prone).
S_t is clipped to S_t = max(0, S_t) before evaluation, so the
ODE/root-finder driving dS/dt = delta(S) never evaluates the model
at a negative richness -- this clip protects only this one function
evaluation, not the ODE trajectory as a whole (an unclipped S(t) can
still run negative between evaluations if delta(S) stays negative
all the way down).
Returns (delta_t, lambda_t, mu_long_t, mu_short_t, mu_t). Used for
equilibrium root-finding (delta_t == 0), ODE trajectory integration
(dS/dt = delta_t), and comparative-statics sweeps over the model
parameters.
Not ported from a standalone MATLAB HSF toolbox library function -- no
hsf/fn_delta_t.m file exists in hfs-archive. The identical model
(fn_lambda_t, fn_mu_long_t, fn_mu_short_t, fn_delta_t) does
appear as local (embedded) functions inside HSF/16. Exercise
Solution/chap16_chap5_exercise2.m, of which HSF-Notebooks chapter 16c
is itself a direct Python port; promoted here from that notebook.
Source code in src/quanttoolbox/sustainable_finance/ecology.py
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | |
hurlbert(n_i, m, method=1)
¶
Hurlbert's rarefaction estimator: expected number of species present
in a random sample of m individuals drawn (without replacement) from
a community with per-species counts n_i.
method=2 uses a log-gamma formulation (via scipy.special.gammaln)
for numerical stability at large sample sizes; method=1 (default)
computes the binomial-coefficient ratio directly.
Original: hsf/hurlbert.m
Source code in src/quanttoolbox/sustainable_finance/ecology.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | |
species_abundance_distribution(n_i, breaks=None)
¶
Bin per-species individual counts n_i into a species-abundance
histogram: s[k] species fall into abundance class j[k].
breaks=None(default): one class per distinct count value inn_i.breaks="octave": Preston's log2 "octave" classes, classk(k=0,1,2,...) covering2**k <= n < 2**(k+1)(sok=0isn=1;k=1isnin{2,3};k=2isnin{4,...,7}; etc.), assigned viak = floor(log2(n)).breaks=<array>: custom upper breakpoints; classes are thenumpy.histogrambins ofn_iover[0, *breaks](all classes half-open[lower, upper)except the last, which is closed at both ends);j[k]is the midpoint of classk's range.
Returns (j, s, breaks) -- breaks is None for the default mode.
Original: hsf/species_abundance_distribution.m
Note: the "octave" and <array> modes' bucket-assignment rule below
was corrected to this numpy-native np.histogram/floor(log2(n))
convention from an earlier, non-numpy-native inclusive rule (each
class taken as (prev_break, this_break], closed at the top and open
at the bottom, with the first class starting from n=1/n=0 rather
than a numpy-style half-open [0, this_break)). On real survey data
with non-integer abundance counts (Whittaker's Siskiyou Mountains tree
survey), the two conventions disagree: HSF-Notebooks chapter 05c's
independent reimplementation of this function -- built and used
without reference to this toolbox version -- was cross-checked against
it and found to classify some individual counts into different
buckets. This toolbox's binning was corrected to match the notebook's
(and numpy's own) convention exactly; see
tests/sustainable_finance/test_ecology.py for the real-data
cross-check.
Source code in src/quanttoolbox/sustainable_finance/ecology.py
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
species_area_relationship(n_i, s_j, area_total, area)
¶
Expected number of species found in a sub-area area out of a total
surveyed area area_total, given either per-species individual counts
n_i (s_j=None), or a species-abundance histogram s_j (number of
species with exactly j = 1, 2, ... individuals).
Original: hsf/species_area_relationship.m
Source code in src/quanttoolbox/sustainable_finance/ecology.py
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
sustainable_finance.entropy¶
Python alternatives
Keep — Shannon entropy/mutual-information decomposition (shannon_entropy, shannon_entropy_markov_chain) and the Israel-Rosenthal-Wei (2001) Markov-generator-matrix repair technique (estimate_markov_generator), used here for rating-migration-generator estimation. No general-purpose equivalent found.
quanttoolbox.sustainable_finance.entropy
¶
Shannon-entropy diversity/dependence measures, and the Israel-Rosenthal-Wei (2001) technique for repairing an estimated Markov generator matrix that fails to satisfy the generator constraints (non-negative off-diagonal entries, zero row sums) because it was estimated from discretely-observed transition data.
Ported from HSF toolbox hsf/{shannon_entropy,
shannon_entropy_markov_chain,estimate_markov_generator}.m.
Translation notes:
- MATLAB's
missrv(x, v)(replace non-finite/flagged entries ofxwithv) is used throughout the originals to implement the0 * log(0) = 0convention; translated asscipy.special.xlogy(p, p), which computesp * log(p)and returns exactly0.0atp == 0without ever evaluatinglog(0)(so, unlikenp.where(p > 0, p * np.log(p), 0.0), it raises no divide-by-zero warning). shannon_entropy_markov_chain.mapproximates the Markov chain's stationary distribution viaexpm(Lambda * 1000)(a long-horizon transition-probability matrix, every row of which has converged to the stationary distribution) -- kept as-is viascipy.linalg.expm.-
estimate_markov_generator.mimplements Israel, Rosenthal & Wei (2001)'s two generator-repair methods for a possibly-invalid estimated generatorLambda(e.g. fromLambda = logm(P) / dton an empirical transition matrixP, which need not itself be a valid generator): -
Lambda1("diagonal adjustment"): zero out negative off-diagonal entries and absorb the removed mass into the diagonal. This exactly preserves each row's original sum (min(x, 0) + max(x, 0) = x), soLambda1's row sums equalLambda's row sums (zero, ifLambdaalready had zero row sums as intended). Lambda2("proportional redistribution"): redistribute each row's negative mass proportionally across that row's positive off-diagonal entries, leaving rows with no positive off-diagonal mass (g[i] == 0) unchanged.
Both are standard generator-matrix regularizations in credit-rating
transition-intensity estimation (Roncalli's hsf toolbox applies this to
rating-migration generators); the row-sum-preservation property of
Lambda1 is verified in this module's tests.
estimate_markov_generator(lam)
¶
Repair a possibly-invalid estimated Markov generator lam (e.g. one
with negative off-diagonal entries) into two valid generators
(non-negative off-diagonal, zero row sums), via Israel, Rosenthal & Wei
(2001)'s two methods.
Returns (Lambda1, Lambda2) -- see the module docstring for the
method descriptions.
Original: hsf/estimate_markov_generator.m
Source code in src/quanttoolbox/sustainable_finance/entropy.py
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
shannon_entropy(p_xy)
¶
Shannon entropy/mutual-information decomposition of a discrete
distribution: p_xy may be a 1D probability vector (single variable,
in which case I_Y = I_XY = 0 and I_X_Y = I_X), or a 2D joint
probability matrix (rows = X, columns = Y).
Returns (I_X, I_Y, I_XY, I_X_Y): the marginal entropy of X, the
marginal entropy of Y, the mutual information between X and Y, and the
joint entropy of (X, Y).
Original: hsf/shannon_entropy.m
Source code in src/quanttoolbox/sustainable_finance/entropy.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | |
shannon_entropy_markov_chain(lambda_, t)
¶
Shannon entropy/mutual-information decomposition of the joint
distribution of a continuous-time Markov chain's state at times 0 and
t, with generator lambda_ and stationary (long-run, t -> inf)
distribution approximated via expm(lambda_ * 1000).
t may be an array of horizons; returns one value per horizon for
each of (I_X, I_Y, I_XY, I_X_Y).
Original: hsf/shannon_entropy_markov_chain.m
Source code in src/quanttoolbox/sustainable_finance/entropy.py
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | |