Skip to content
RomainFillonPublic

About

Replication package for "The Price of Caution near a Collapsing Threshold"

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Replication package

"The Price of Caution near a Collapsing Threshold" Romain Fillon

What the paper does. It prices the risk of crossing a climate tipping threshold. Inside a window the paper delimits, more climate noise lowers that price rather than raising it, inverting the standard reading of uncertainty. And the price diverges or stays bounded according to how fast the safety margin closes — as the square root of the remaining carbon budget, or in proportion to it — so two elements at identical proximity can carry prices that differ without limit.


1. What this package produces, and how to run it

One command, from this directory:

bash run_all.sh

It recomputes every number, table and figure the manuscript displays, writes them where manuscript/paper.tex reads them, verifies that each exhibit the paper displays was produced by that run, and compiles manuscript/paper.pdf.

The run produces:

  • the figures into 02_output/figures/, copied to manuscript/figures/;
  • the table file, manuscript/tables/crra_hjb_slopes.tex;
  • manuscript/values.tex, every inline number the paper quotes, each carrying the script and the inputs it came from;
  • 02_output/values/VALUES_DIFF.md, a per-macro comparison of the regenerated values against the manuscript's previous state;
  • manuscript/paper.pdf.

The last thing it prints is one line per exhibit. The run exits non-zero if any step fails or if any exhibit the paper displays was not produced, and names what is missing. The authority for that list is paper.tex itself, harvested at run time — not a list kept by hand in this file.

What that check does and does not establish. Step 4/5 asserts that every file paper.tex includes or inputs exists and is newer than the start of the run — so a committed leftover whose generator has been removed is reported, not passed. It does not compare figure contents between runs: every PDF carries a creation timestamp in its metadata, so two runs of the same seeded script differ byte for byte. What stands behind the figures instead is that they are built from the same seeded runs as the numbers, and that no script anywhere in 01_code/ prints a date into a figure.


2. Requirements

Python 3.14.3 (developed and tested; 3.11+ expected to work)
Packages numpy==2.4.4, scipy==1.17.1, matplotlib==3.10.8, pandas==3.0.1
Install python -m pip install -r 01_code/requirements.txt. On Windows, run under Git Bash; if python resolves to the Microsoft Store alias the run stops and tells you to pass PYTHON=/c/path/to/python.exe, that alias not being an interpreter. On Linux and macOS bash run_all.sh needs nothing said about it.
LaTeX latexmk with a full TeX distribution, for step 5/5 only
Network Required once, for one series (§3)
Disk About 10 MB for the package; under 50 MB after a run
Runtime Half an hour to an hour on a current laptop, dominated by a few Monte-Carlo and BVP sweeps. Read that as an order of magnitude, not a budget: across cold runs of the same machine the wall clock has varied by more than half while the values came back byte-identical — one run was faster on every single script — so the spread is machine load and says nothing about the work. The per-script RUNTIME headers give an observed range for the same reason.

All Monte Carlo is seeded, so reruns are deterministic: calibration_ci.py, eps_inf_ci.py, ews_calibration.py and fig_forest_tc.py use np.random.seed(42). The solvers draw no random numbers at all. Two cold runs separated in time return every computed macro identical to the last digit printed and the CRRA slope table byte for byte, which is what makes 02_output/values/VALUES_DIFF.md worth reading: a rerun that disagrees with manuscript/values.tex is reporting a real difference in the environment, not sampling noise.


3. Data availability statement

Every input is either one public time series, fetched at run time, or a literature constant cited in the manuscript. The package bundles no data files.

Input Provider / citation Status In this package Used by
AMOC SST fingerprint (subpolar-gyre index, HadISST, 1871–2016) Caesar et al. (2018), Nature 556, 191–196 — PIK Host page publishes no licence, copyright notice or conditions of use No — fetched at run time ews_calibration.py
HadISST (the underlying SST record) Met Office Hadley Centre Distributed by the Met Office under its own terms No — reached only through the index above —
Tipping thresholds and timescales Armstrong McKay et al. (2022), Science 377, eabn7950 Published constants Yes — 01_code/inputs_literature.py, with citation calibration
Present warming, TCRE IPCC AR6 Published constants Yes — 01_code/inputs_literature.py, with citation calibration

Three NOAA PSL series (AMO, Niño 3.4, Tropical Southern Atlantic) shipped with the package until 2026-09 as regional placebos for a third-moment diagnostic. That argument is no longer in the manuscript; the diagnostic and the three files are in 99_archive/, with their provenance and checksums, and nothing in the package reads them.

The one series fetched at run time

ews_calibration.py downloads, at every run, from

https://www.pik-potsdam.de/~caesar/AMOC_slowdown/sg_index_hadisst.txt

a plain-text file of 1 638 bytes, 146 annual values covering 1871–2016, carrying a one-line header with the years and the unit: the subpolar-gyre sea surface temperature index of Caesar et al. (2018), derived by those authors from the HadISST record. The package reads it into memory and does not write a copy to disk.

The host page publishes no licence, no copyright notice and no conditions of use, and this package does not redistribute the file. A replicator therefore needs network access once, for this one series. This is the package's only external dependency at run time and its only availability risk.

This is also the only network call the package makes, and it is made in one place. A second script used to fetch the same series independently, from outside the guard described below; it is archived, and with it that second call.

If the URL stops resolving. The index is a documented transformation of a public record: it can be reconstructed from HadISST using the subpolar-gyre region definition given in Caesar et al. (2018). That reconstruction has not been carried out here, and nothing in this package performs it — a replicator taking that route would be rebuilding the input rather than rerunning it, and should verify the rebuilt series against the summary statistics ews_calibration.py prints (146 values, detrended variance 0.0683 K², AR(1) restoring rate 0.4933 yr⁻¹).

What does not reproduce without it. The fetch is the first link in a chain: it estimates the restoring rate λ̂ and the detrended variance, and three later scripts — reduced_form_scc.py, crosspartial_contrast.py and noise_reversal_frontier.py — read those two numbers back out of its captured output.

35 of the 60 computed macros in manuscript/values.tex carry [requires network], alongside 11 sourced literature constants (71 macros in the file).

Those macros are unobtainable without the series — not only λ̂ and Var themselves, but everything downstream of them: the reduced-form price level, the cross-partial contrast ratios, the noise-reversal frontier, the additivity errors, the dynamic scale ε_dyn and the discount-range price ratios. run_all.sh does not run those three dependent scripts at all when the fetch fails, rather than let any of them continue on a recorded constant, and it names the step that failed.

What does reproduce without it. Every figure the paper shows; the CRRA slope table; the Monte-Carlo budgets and deadlines; and every computed macro not marked [requires network], together with the sourced literature constants — the counts above give both. The contrast and frontier solvers are not in that list, although their mathematics needs no data: both read λ̂ out of the fetch and exit without it, so every macro they emit is marked, on the availability the marker states rather than on what the equations consume. The manuscript will not compile to its published numbers, because the missing macros include ones the body quotes.


4. What produces what

Everything between the markers below is written by make_inventory.py at every run, from what the run actually produced; a hand edit there is overwritten by the next run.

Exhibits (4)

The paper's other tables are written inline in paper.tex; their cells are macros from values.tex or analytic constants, so they carry no separate file.

Exhibit in the paper Produced by Data consumed Status
fig_bifurcation_intro.pdf 01_code/03_figures/fig_bifurcation_intro.py none (self-contained) up-to-date
fig_cross_partial.pdf 01_code/02_solvers/paper3_cross_partial_figures.py none (self-contained) up-to-date
fig_forest_tc.pdf 01_code/03_figures/fig_forest_tc.py none (self-contained) up-to-date
crra_hjb_slopes.tex 01_code/04_tables_values/make_tables_values.py (from crra_hjb_scc.py) none (self-contained) up-to-date

Inline numbers (71 macros in values.tex, 35 needing the network)

Every number the paper quotes inline is a macro in manuscript/values.tex, and every macro carries, as a comment on its own line, the script and the inputs it came from. Grouped here by producing script. The Macros column counts the macros marked [requires network], and those counts add up down the column to the figure §3 gives. The Data column answers a different question — what the script needs in order to run. Here the two agree: every script that reads the fetched series emits macros marked by it, because none of them runs without it.

Produced by Macros Data
01_code/01_calibration/calibration_ci.py 6 (0 network) none (self-contained)
01_code/01_calibration/eps_inf_ci.py 3 (0 network) none (self-contained)
01_code/01_calibration/ews_calibration.py 3 (3 network) PIK SST record (network)
01_code/01_calibration/reduced_form_scc.py 8 (8 network) PIK SST record, via the EWS estimates
01_code/02_solvers/crosspartial_contrast.py 9 (9 network) PIK SST record, via the EWS estimates
01_code/02_solvers/noise_reversal_frontier.py 3 (3 network) PIK SST record, via the EWS estimates
01_code/02_solvers/paper3_cross_partial_figures.py 2 (0 network) none (self-contained)
01_code/03_figures/fig_forest_tc.py 6 (0 network) none (self-contained)
01_code/04_tables_values/collect_computed.py 20 (12 network) closed forms and sourced constants
01_code/inputs_literature.py 11 (0 network) literature constants

Scripts that produce no exhibit (3)

These ship although the paper displays nothing they make and they emit no macro. Each is the numerical evidence behind one sentence, which is a third category next to "produces a figure" and "produces a macro" -- and the one no import graph reveals.

Script The sentence it supports In the default run?
01_code/02_solvers/paper2_all_bifurcations.py the class column of the universality table, stated analytically and checked numerically here yes -- it is also imported by paper3_cross_partial_figures.py
01_code/02_solvers/paper1_ez_amplitude.py *"monotonicity is numerical, over four decades bracketing the calibrated values and for βL
01_code/02_solvers/paper1_crra_reversal.py "the price falls strictly with the noise at every γ ∈ {0.5,…,6}" (CRRA appendix) no -- run python 01_code/02_solvers/paper1_crra_reversal.py, about 13 min

5. Directory layout

Path Contents
run_all.sh The single entry point. Runs everything, checks coverage, compiles.
01_code/01_calibration/ Calibration: the EWS estimates, the Monte-Carlo budgets, deadlines and the reduced-form level.
01_code/02_solvers/ The first-passage, amplitude, cross-partial and noise-reversal numerics.
01_code/03_figures/ Two scripts written around a figure: fig_bifurcation_intro.py produces only that, fig_forest_tc.py also emits six macros.
01_code/04_tables_values/ Collects the printed results, writes values.tex and the table file, and regenerates §4 above.
01_code/check_exhibits.py The coverage control: every exhibit paper.tex displays was produced by this run.
01_code/inputs_literature.py The sourced constants, each with its citation.
02_output/ Everything the run writes: figures, tables, computed.json, captured script output.
manuscript/ paper.tex (authoritative), the generated values.tex, the table and figure files it reads.
99_archive/ Withdrawn scripts and their outputs, each under its original path, with a dry inventory: what, from where, why withdrawn, and the commit to restore it from. Nothing here is needed to reproduce the paper. The authoring tooling and the record of how the package reached its present shape are kept in the project repository, outside this package.

6. Licence

The code in 01_code/ and run_all.sh is released under the MIT licence; see LICENSE. Use it, adapt it, cite the paper if it helps you.

The manuscript (manuscript/paper.tex, its figures and its text) is not covered by that licence and remains the author's, as does the paper itself.

The data are covered by neither, because the package redistributes none: the one series it uses is fetched from its publisher at run time and is discussed in §3.

About

Replication package for "The Price of Caution near a Collapsing Threshold"

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages