Turn emissions and profit figures into carbon costs and stranded-asset flags under NGFS carbon-price scenarios — three benchmark prices, four vectorized scoring functions, zero setup.
import pandas as pd
from ngfs_toolkit import list_scenarios, stranding_score, is_stranded
firms = pd.DataFrame({
"firm": ["Alpha Cement", "Beta Agri", "Gamma Logistics"],
"profit_musd": [12.0, 3.5, 1.2], # annual profit, M USD
"emissions_mtco2e": [0.05, 0.08, 0.02], # annual emissions, MtCO2e
})
for scenario in list_scenarios():
firms[f"score | {scenario}"] = stranding_score(
firms["profit_musd"], firms["emissions_mtco2e"], scenario
)
firms[f"stranded | {scenario}"] = is_stranded(
firms["profit_musd"], firms["emissions_mtco2e"], scenario
)Output (positive score = carbon cost exceeds profit = stranded under that scenario):
firm score | Delayed Transition stranded | Delayed Transition score | Net Zero(NZ) 2050 stranded | Net Zero(NZ) 2050 score | Divergent Net Zero stranded | Divergent Net Zero
Alpha Cement -11.5 False -6.5 False 3.0 True
Beta Agri -2.7 False 5.3 True 20.5 True
Gamma Logistics -1.0 False 1.0 True 4.8 True
Nobody is stranded at 10 USD/t, everybody is at 300 USD/t — the interesting information is who flips in between.
-
Packages the NGFS Phase 3 benchmark carbon prices (REMIND model, USD 2010 per tCO2e) as a plain dict with a lookup helper that gives useful errors:
>>> from ngfs_toolkit import SCENARIOS, get_price >>> SCENARIOS {'Delayed Transition': 10.0, 'Net Zero(NZ) 2050': 110.0, 'Divergent Net Zero': 300.0} >>> get_price("Net Zero 2050") KeyError: "Unknown scenario 'Net Zero 2050'. Did you mean 'Net Zero(NZ) 2050' or 'Divergent Net Zero'?"
-
Scores carbon exposure with four vectorized primitives —
carbon_cost,adjusted_profit,stranding_score,is_stranded— that accept scalars, lists, numpy arrays or pandas Series and return the same kind of object. -
Provides drop-in DataFrame wrappers (
add_carbon_cost_index,add_adjusted_profit,add_carbon_risk_score) with the exact signatures and column-naming behaviour of the original research pipeline. Parity is enforced by tests against verbatim copies of the original code (tests/reference/), bit-for-bit on a 50-row synthetic frame across all three scenarios. -
Computes a physical climate-stress composite (
climate_stress):0.4*drought + 0.4*flood + 0.2*z(temperature).
Extracted and generalized from a climate-finance research pipeline on agricultural credit risk.
git clone https://github.com/0scarito/ngfs-toolkit
cd ngfs-toolkit
pip install -e .Requires Python >= 3.10, numpy >= 1.24, pandas >= 2.0. No network access, no API keys, no configuration.
from ngfs_toolkit import carbon_cost, adjusted_profit, stranding_score
carbon_cost(0.5, "Divergent Net Zero") # 0.5 t * 300 USD/t = 150.0
carbon_cost(0.5, 87.0) # explicit price also works
adjusted_profit(100.0, 0.5, "Net Zero(NZ) 2050") # 100 - 55 = 45.0
stranding_score(45.0, 0.5, "Divergent Net Zero") # 150 - 45 = 105.0 -> strandedUnits are up to you, but keep them consistent: prices are per tCO2e, so tCO2e emissions give USD costs and MtCO2e give M USD.
from ngfs_toolkit import (
SCENARIOS, add_carbon_cost_index, add_adjusted_profit, add_carbon_risk_score,
)
df = add_carbon_cost_index(df, SCENARIOS, proxy_col="Emission_Proxy")
df = add_adjusted_profit(df, SCENARIOS, profit_col="Net_Profit")
df = add_carbon_risk_score(df, SCENARIOS, profit_col="Net_Profit")
# adds Carbon_Cost_<scenario>, Adj_Profit_<scenario>, Carbon_Risk_Score_<scenario>Pass scenarios=None to use the packaged NGFS benchmarks. Note the cost index shifts each cost column so its minimum is 0 (the emission proxy is typically z-scored, so raw products can be negative) — it is a relative index within your sample, not an absolute cost.
from ngfs_toolkit import climate_stress
climate_stress(drought=[0.5, 0.5], flood=[0.25, 0.25], temperature=[10.0, 20.0])
# array([0.15857864, 0.44142136])The scoring model is deliberately simple:
carbon_cost = emissions x price, with prices from the NGFS Phase 3 scenario set (REMIND-MAgPIE outputs, USD 2010 per tCO2e): 10 (Delayed Transition), 110 (Net Zero 2050), 300 (Divergent Net Zero).adjusted_profit = profit - carbon_cost— what is left if the firm had to pay for its emissions at the scenario price.stranding_score = carbon_cost - profit— positive means the scenario carbon bill exceeds current profit, i.e. the asset's economics do not survive that carbon price. This is a first-order transition-risk screen in the spirit of stranded-asset analyses (Caldecott, 2017).climate_stress = 0.4*drought + 0.4*flood + 0.2*z(temperature), wherezis the sample z-score with a1e-9floor on the standard deviation. Weights come from the original research pipeline, not from an estimation procedure.
Honest list:
- Three benchmark price points, not full NGFS trajectories. The NGFS scenarios are multi-decade price paths varying by region and model; this package ships one representative point per scenario. Loading full trajectories from the NGFS Scenario Explorer is roadmap, not implemented.
- Static, first-order screen. No discounting, no demand response, no pass-through, no abatement — a firm that can cut emissions or raise prices is treated the same as one that cannot.
- Prices are in USD 2010 real terms. Comparing them against nominal current-year profits mixes price bases; rebase your financials or accept the approximation.
- The cost index is sample-relative.
add_carbon_cost_indexmin-shifts each column, so values depend on which rows are in your frame; only the vectorizedcarbon_costis an absolute figure. climate_stressz-scores within the sample. The same row scored inside two different samples gives two different results, and the 0.4/0.4/0.2 weights are a research-pipeline convention, not calibrated coefficients.- Emission proxies are your problem. The original pipeline used a z-scored proxy, not measured emissions; garbage proxies give garbage scores.
- NGFS (2022). NGFS Climate Scenarios for central banks and supervisors, Phase 3. https://www.ngfs.net/ngfs-scenarios-portal/
- Luderer, G. et al. REMIND-MAgPIE integrated assessment model (Potsdam Institute for Climate Impact Research), one of the models behind the NGFS scenario set.
- Caldecott, B. (2017). Introduction to special issue: stranded assets and the environment. Journal of Sustainable Finance & Investment, 7(1), 1-13.
Extracted from a group research project by Oscar, Daniil, Oulaya, Ulysse and Yuhan (CentraleSupelec / ESSEC coursework): https://github.com/0scarito/Research-project. The tests/reference/ directory keeps verbatim copies of the original modules so parity with the research code stays enforced by CI.
MIT