Replication Files for “Forward Return Expectations”
1 Overview
This replication package contains the code needed to reproduce the tables and figures in “Forward Return Expectations” (Gandhi et al. 2026), forthcoming in the Review of Financial Studies, together with the input data that we may redistribute and pseudo-data in place of the licensed data. The code runs in four steps on a SLURM cluster and the WRDS Cloud (see Section 4.5) and may take up to two weeks:
- Check the inputs and replace the pseudo-data with the licensed data.
- Extract the OptionMetrics and Compustat inputs on the WRDS Cloud.
- Run the
momentsstage, which constructs the option-implied moments. - Run the
errorsstage, which constructs the forward rates and forecast errors and produces most of the tables and figures. This step also launches thecyclstage, the cyclicality analysis, once the forecast errors have been constructed.
Section 2 describes the data: the input files, their sources, and which of them are included in the package. Section 3 lists the software and the computational requirements. Section 4 describes the code and gives the instructions for running it. Section 5 maps each table and figure to the program that produces it. Section 6 contains the acknowledgements and Section 7 the references.
2 Data
2.1 Data Availability
This paper analyzes external data. Some data cannot be made publicly available due to licensing restrictions.
Statement about rights.
- We certify that the authors of the manuscript have legitimate access to and permission to use the data used in this manuscript.
- We certify that the data contained within this replication package are publicly available.
Summary of availability. The data fall into three groups:
- The licensed data from OptionMetrics, Compustat, CRSP, and the CBOE are not included in the package. Pseudo-data that mirror these files are included in their place.
- The publicly available data files are included in the package.
- The data files obtained from other researchers are included in the package.
Section 2.2 lists every input file with its source and whether it is included in the package or replaced by pseudo-data. The package contains no derived data: the code regenerates every intermediate file and every table and figure. We use the licensed data under our institutional licences and cannot retain them beyond their terms. You can regenerate the WRDS extracts with the SAS programs in moments/wrds/ and obtain the other licensed files from the vendors.
License for data. The data files distributed with the package are third-party data and remain subject to their providers’ terms of use, as stated in LICENSE.txt. The code is licensed under the MIT License (see Section 4.6).
2.2 Input Data Files
The following tables list all input data files by folder. The file names are relative to the folder named in the heading of each table.
moments/data
| File | Description | Source | Downloaded | Provided |
|---|---|---|---|---|
optprc/optprc_USA_108105_1996_2025.txt |
S&P 500 option prices ( Option_Price file, WRDS table opprcd) |
OptionMetrics IvyDB US via WRDS (OptionMetrics 2025b) | 2026-08-25 | pseudo |
vsurf/vsurf_USA_108105.txt |
S&P 500 volatility surface ( Volatility_Surface file, WRDS table vsurfd) |
OptionMetrics IvyDB US via WRDS (OptionMetrics 2025b) | 2026-08-25 | pseudo |
secprc/secprc_USA_108105.txt |
S&P 500 index prices ( Security_Price file, WRDS table secprd) |
OptionMetrics IvyDB US via WRDS (OptionMetrics 2025b) | 2026-08-25 | pseudo |
sample.txt |
index identifiers | authors | – | Yes |
sample_rfs.txt |
sample windows | authors | – | Yes |
moments/raw
| File | Description | Source | Downloaded | Provided |
|---|---|---|---|---|
optionm/usa.zero_curve_1996_2025.txt |
U.S. zero-coupon yield curve ( Zero_Curve file, WRDS table zerocd) |
OptionMetrics IvyDB US via WRDS (OptionMetrics 2025b) | 2026-08-25 | pseudo |
optionm/usa.index_dividend_1996_2025.txt |
S&P 500 dividend yield ( Index_Dividend file, WRDS table idxdvd) |
OptionMetrics IvyDB US via WRDS (OptionMetrics 2025b) | 2026-08-25 | pseudo |
optionm/europe.option_price_YYYY.txt |
European index option prices ( Option_Price file, one file per year) |
OptionMetrics IvyDB Europe (OptionMetrics 2025a) | – | pseudo |
optionm/europe.option.txt |
European option contract identifiers ( Option file) |
OptionMetrics IvyDB Europe (OptionMetrics 2025a) | – | pseudo |
optionm/europe.volatility_surface_YYYY.txt |
European volatility surfaces ( Volatility_Surface file, one file per year) |
OptionMetrics IvyDB Europe (OptionMetrics 2025a) | – | pseudo |
optionm/europe.security_price.txt |
European index prices ( Security_Price file) |
OptionMetrics IvyDB Europe (OptionMetrics 2025a) | – | pseudo |
optionm/europe.index_dividend.txt |
European index dividend yields ( Index_Dividend file) |
OptionMetrics IvyDB Europe (OptionMetrics 2025a) | – | pseudo |
optionm/europe.zero_curve.txt |
European zero-coupon yield curves ( Zero_Curve file) |
OptionMetrics IvyDB Europe (OptionMetrics 2025a) | – | pseudo |
optionm/asia.option_price_YYYY.txt |
Asian index option prices ( Option_Price file, one file per year) |
OptionMetrics IvyDB Asia (OptionMetrics 2023) | – | pseudo |
optionm/asia.option.txt |
Asian option contract identifiers ( Option file) |
OptionMetrics IvyDB Asia (OptionMetrics 2023) | – | pseudo |
optionm/asia.volatility_surface_YYYY.txt |
Asian volatility surfaces ( Volatility_Surface file, one file per year) |
OptionMetrics IvyDB Asia (OptionMetrics 2023) | – | pseudo |
optionm/asia.security_price.txt |
Asian index prices ( Security_Price file) |
OptionMetrics IvyDB Asia (OptionMetrics 2023) | – | pseudo |
optionm/asia.index_dividend.txt |
Asian index dividend yields ( Index_Dividend file) |
OptionMetrics IvyDB Asia (OptionMetrics 2023) | – | pseudo |
optionm/asia.zero_curve.txt |
Asian zero-coupon yield curves ( Zero_Curve file) |
OptionMetrics IvyDB Asia (OptionMetrics 2023) | – | pseudo |
compustat.security_price.txt |
daily index prices (WRDS table g_idx_daily) |
Compustat Global via WRDS (S&P Global Market Intelligence 2025) | 2026-08-25 | pseudo |
crsp.security_price.csv |
daily stock index file (same file as cycl/raw/crsp_d.csv) |
CRSP via WRDS (Center for Research in Security Prices (CRSP) 2025) | 2026-08-25 | pseudo |
mdr/mdr_spx_YYYYMM.csv |
S&P 500 option trades and quotes (one file per month) |
CBOE Market Data Replay (Cboe Global Markets 2025) | – | pseudo |
errors/raw
| File | Description | Source | Downloaded | Provided |
|---|---|---|---|---|
survey_spf_expectations.xlsx |
Livingston Survey | Federal Reserve Bank of Philadelphia’s website (2026) | 2025-09-26 | Yes |
survey_cfo_expectations.xlsx |
CFO Survey | Federal Reserve Bank of Richmond’s website (2026); Graham et al. (2020) | 2026-02-21 | Yes |
survey_ibert_expectations.txt |
CFO Survey, as distributed in the replication package of Dahlquist and Ibert (2024a) | Dahlquist and Ibert’s replication package on Harvard Dataverse (Dahlquist and Ibert 2024b) | 2025-02-18 | Yes |
survey_vanguard_expectations.xlsx |
Vanguard Survey | Vanguard’s website (2025); Giglio et al. (2021a); Giglio et al. (2021b) | 2025-08-27 | Yes |
cycl/raw
| File | Description | Source | Downloaded | Provided |
|---|---|---|---|---|
shiller_m.xls |
excess CAPE yield | Robert Shiller’s website (2026); Shiller et al. (2020) | 2026-02-09 | Yes |
ln_m.xlsx |
real activity factor | Sydney Ludvigson’s website (Ludvigson and Ng 2026); Ludvigson and Ng (2009) | 2026-02-09 | Yes |
vix1m_d.csv |
30-day CBOE Volatility Index (VIX) | Cboe Global Markets (2026) | 2026-02-09 | Yes |
amre_m.txt |
asset manager return expectations | Dahlquist and Ibert’s replication package on Harvard Dataverse (Dahlquist and Ibert 2024b); Dahlquist and Ibert (2024a) | 2026-02-17 | Yes |
gw_m.xlsx |
P/E ratio | Amit Goyal’s website (Welch and Goyal 2026); Welch and Goyal (2008) | 2026-02-09 | Yes |
bex_d.xlsx |
risk aversion index | Nancy Xu’s website (Bekaert et al. 2026); Bekaert et al. (2022) | 2026-02-09 | Yes |
gz_m.csv |
credit spread index | Federal Reserve Board’s website (Favara et al. 2026); Gilchrist and Zakrajšek (2012), updated by Favara et al. (2016) | 2026-02-09 | Yes |
nfci_w.csv |
National Financial Conditions Index (NFCI) and Adjusted NFCI (ANFCI) | Federal Reserve Bank of Chicago’s website (2026) | 2026-02-09 | Yes |
lw_d.xlsx |
zero-coupon yield curve | Cynthia Wu’s website (Liu and Wu 2026); Liu and Wu (2021) | 2026-09-04 | Yes |
apfm_m.xlsx |
repurchase-adjusted price-dividend ratio | Zhengyang Xu’s website (Nagel and Xu 2022b); Nagel and Xu (2022a) | 2026-02-09 | Yes |
crsp_d.csv |
daily stock index file (same file as moments/raw/crsp.security_price.csv) |
CRSP via WRDS (Center for Research in Security Prices (CRSP) 2025) | 2026-08-25 | pseudo |
cycl/data
| File | Description | Source | Downloaded | Provided |
|---|---|---|---|---|
mnemonics.xlsx |
variable labels | authors | – | Yes |
helper/raw
| File | Description | Source | Downloaded | Provided |
|---|---|---|---|---|
fred_<SERIES>.txt |
FRED series downloaded by the code (see the FRED series table below) |
Federal Reserve Bank of St. Louis (2026) | 2026-09-04 and 2026-09-06 | Yes |
Licensed data. The licensed files may not be redistributed.
Included data. All other files are included in the package, with their sources cited in the tables. The FRED series are downloaded at run time (the FRED API key is set in helper/code/libraries.R). Because FRED revises its series, we also include the files that our run downloaded.
FRED series. Each series feeds one variable:
| Series | Program | Variable | Downloaded |
|---|---|---|---|
DTB4WK, DTB6, DGS1, DGS2 |
moments/code/process_mdr.R |
risk-free rates for the CBOE sample | 2026-09-04 |
DTB3 |
moments/code/process_mdr.Rcycl/code/cycl_proxies.R |
risk-free rates for the CBOE sample term spread |
2026-09-06 |
USREC |
cycl/code/cycl_proxies.R |
NBER recession indicator | 2026-09-06 |
INDPRO |
cycl/code/cycl_proxies.R |
industrial production growth | 2026-09-06 |
BAA, AAA |
cycl/code/cycl_proxies.R |
default spread | 2026-09-06 |
CFNAI |
cycl/code/cycl_proxies.R |
Chicago Fed National Activity Index | 2026-09-06 |
STLFSI4 |
cycl/code/cycl_proxies.R |
St. Louis Fed Financial Stress Index | 2026-09-06 |
KCFSI |
cycl/code/cycl_proxies.R |
Kansas City Fed Financial Stress Index, used in the FCI/FSI principal component | 2026-09-06 |
Pseudo-data. The licensed files, marked “pseudo” in the tables, are replaced in the package by pseudo-data files of the same name, location, and layout that contain a few rows of simulated values. The pseudo-data document the file layouts only, that is, the column names and formats the code expects. Running the code on them will not replicate the results, which require the licensed data (see Section 4.5).
3 Computational Requirements
3.1 Software Requirements and Settings
The code runs on Mercury, the computing cluster of the University of Chicago Booth School of Business (link), and on the WRDS Cloud (link), with the software listed below.
Software. The code was last run on 64-bit Linux (x86-64) with R 4.5.3 (environment module R/4.5/4.5.3), StataNow/BE 19.5, revision of April 8, 2025 (stata/19.5), MATLAB R2026a, version 26.1 (matlab/R2026a), Artelys Knitro 14.0.0 (knitro/14.0/14.0.0), a commercial nonlinear optimization solver that optionm_moments_3.m calls through its MATLAB interface for the SVI fits (link), and SAS 9.4 on the WRDS Cloud (qsas). The R figure code (tikzDevice) requires a LaTeX installation, TinyTeX at ~/.TinyTeX/bin/x86_64-linux/ (TeX Live 2026, pdfTeX 1.40.29), and the MATLAB figure code (export_fig) requires Ghostscript (gs) on the path.1 The launchers require SLURM and Environment Modules, bash 4.0 or newer (the run_optionm_*.bash submitters use mapfile), GNU coreutils, sed, and gzip.
R packages. The following packages are attached or called by helper/code/libraries.R and the programs, with the versions installed on Mercury in September 2026: broom 1.0.12, cowplot 1.2.0, data.table 1.18.2.1, DBI 1.3.0, derivmkts 0.2.5.1, dplyr 1.2.0, duckdb 1.5.0, fredr 2.1.0, fst 0.9.8, ggh4x 0.3.1, ggplot2 4.0.2, ggpubr 1.0.0, kableExtra 1.4.1, knitr 1.51, lfe 3.1.1, lubridate 1.9.5, purrrlyr 0.0.10, RcppRoll 0.3.2, readxl 1.4.5, scales 1.4.0, tidyverse 2.0.0, tikzDevice 0.12.6, and zoo 1.8.15. The same file sets the FRED API key with fredr_set_key() (line 51). Replace the placeholder INSERTFREDKEY with your own key. The install commands for the R packages are kept, commented out, at the top of helper/code/libraries.R.
Stata commands. The following commands are included in helper/code/ado/ and added to the ado path automatically by helper/code/functions.do. The fixed-b commands neweyfixedb, testfixedb, and xtsccfixedb are the versions of newey, test, and xtscc with the fixed-b critical values of Kiefer and Vogelsang (2005), written by Do Won Kwak and Timothy Vogelsang and downloaded from Timothy Vogelsang’s website on 07/21/2022 (Kwak and Vogelsang 2011) (link). The commands har and hart are the HAR regression and test commands of Ye and Sun (2018a), downloaded from Yixiao Sun’s website on 07/21/2022 (Ye and Sun 2018b) (link). We modified hart, kernel_t, and kernel_F_all on 08/28/2024 to fix the bandwidth at \(\lceil 1.3\sqrt{T} \rceil / T\) (following Lazarus et al. 2018) in place of the testing-optimal bandwidth. The changed lines are marked hardcode in the three files. The command outreg2 is by Roy Wada, downloaded from SSC (link). The included versions are neweyfixedb 1.5.5 and testfixedb 2.0.1 (fixed-b release of 2011), xtsccfixedb (based on xtscc 1.1.4, fixed-b release of 2010), har and hart (release of April 2018), and outreg2 2.3.2 (August 2014).
The SSC packages the code uses are included in helper/code/ado/ as well, copied from our Stata installation with their help files and compiled Mata libraries: reghdfe 5.7.3, ftools 2.37.0, ivreghdfe 1.0.0, ivreg2 4.1.11, ranktest 2.0.04, and moremata (07/21/2022), whose Mata function mm_root() the fixed-b and HAR commands call. Nothing has to be installed. They are the versions the code was written and tested with, and the code may not run with more recent releases of these packages.
MATLAB toolboxes and add-ons. The export_fig function (link), version 3.02, by Oliver Woodford and Yair Altman, is included in helper/code/functions/exportfig/ under its BSD license, reproduced in the LICENSE file of that folder, and requires Ghostscript. No other third-party MATLAB package is required. The code uses the Parallel Computing, Financial, Financial Instruments, Econometrics, Statistics and Machine Learning, Optimization, and Global Optimization Toolboxes (all version 26.1, R2026a), and the Knitro MATLAB interface.
LaTeX packages. The tikzDevice package calls pdflatex to measure text and requires the LaTeX packages amsfonts, amsmath, amssymb, bm, fontenc, inputenc, nicefrac, preview, and tikz (with the calc library).
Paths. All programs set the project root to ~/forward/. If you place the package at ~/forward, then no paths need to be changed. The following table lists the root and the other settings that may need to change on another system, with the files and lines in which they are set:
| Language | Setting | Files (lines) |
|---|---|---|
| R | path <- "~/forward/" |
helper/code/libraries.R (49) |
| R | fredr_set_key("INSERTFREDKEY") |
helper/code/libraries.R (51) |
| R | source("~/forward/...") |
moments/code/functions.R (3-4)errors/code/functions.R (3-4)cycl/code/functions.R (3-4)moments/code/process_optionm_1.R (1)moments/code/process_optionm_2.R (1)moments/code/process_optionm_3.R (1)moments/code/process_mdr.R (1)errors/code/ggl_errors.R (1)errors/code/ggl_figures.R (1)errors/code/ggl_tables.R (1)cycl/code/cycl_proxies.R (1)cycl/code/cycl_figures.R (1) |
| Stata | global path "~/forward/" |
helper/code/functions.do (1; line 2 sets the ado path from it) |
| Stata | run "~/forward/..." |
errors/code/functions.do (1)cycl/code/functions.do (1)errors/code/ggl_regressions.do (2)cycl/code/cycl_regressions.do (2) |
| MATLAB | path = '~/forward/' |
moments/code/optionm_moments_1.m (5)moments/code/optionm_moments_2.m (5)moments/code/optionm_moments_3.m (5)moments/code/optionm_moments_4.m (5)errors/code/ggl_matlab.m (5)errors/code/ggl_calibration.m (5)errors/code/ggl_simulations.m (5) |
| SAS | %let DATADIR, %let RAWDIR (the output locations on the WRDS Cloud) |
moments/wrds/process_optionm.sas (1-2)moments/wrds/process_compustat.sas (1) |
| bash | cd ~/forward/... |
moments/code/run_optionm_2.bash (10, 15, 32)moments/code/run_optionm_3.bash (10, 15)moments/code/run_optionm_4.bash (10, 15)moments/code/run_optionm_5.bash (10, 15)moments/code/run_optionm_6.bash (10, 16)moments/code/run_optionm_7.bash (10, 16)moments/code/run_optionm_8.bash (3)errors/code/run_ggl_2.bash (3, 12)errors/code/ggl_regressions.bash (15)errors/code/ggl_tables.bash (15)cycl/code/run_cycl_2.bash (3) |
| R | TinyTeX path ~/.TinyTeX/bin/x86_64-linux/pdflatex |
helper/code/functions.R (13-14) |
| bash | export PATH=$HOME/local/bin:$PATH (Ghostscript for export_fig) |
errors/code/ggl_matlab.bash (9)errors/code/ggl_simulations.bash (9) |
| bash | #SBATCH --account=pi-ngormsen, #SBATCH --partition=standard |
every launcher |
Random numbers. Two MATLAB programs use pseudorandom number generation. No R or Stata program draws random numbers. The program errors/code/ggl_calibration.m simulates volatility paths and bootstrap draws for the model calibration. It sets the seed with rng(i) at line 104 before each simulation block, so its results do not depend on the run or on the number of parfor workers. The function moments/code/functions/svi/estimate_svi.m calls the genetic algorithm ga when the fmincon and Knitro fits fail, which happens only in the SVI robustness variant. It sets the seed with rng(0) at line 124 before the ga calls.2
3.2 Memory and Runtime Requirements
The code was last run on Mercury under SLURM, on the standard partition, in August-September 2026. The number of jobs and the cores, memory, and wall-time limit that each script requests in its #SBATCH header are listed with the programs in Sections 4.2 to 4.4. Scripts without a header run on the login node, and the wall-time limits are upper bounds. A complete run may take up to two weeks, most of it in the moments stage, whose per-index jobs are submitted at intervals by run_optionm_2.bash through run_optionm_7.bash (Section 4.2 lists the wall times we request for the submitters). The largest request is 768 GB of memory, for ggl_calibration with 12 workers. A full run needs about 2 TB of disk space, most of it for the raw option data and the intermediate files of the moments stage.
4 Code Description and Instructions
4.1 Directory Structure
The package has the following structure:
forward/
├── moments/ option-implied moments
│ ├── wrds/ SAS programs
│ ├── code/ programs and launchers
│ │ ├── functions/ MATLAB functions
│ │ │ └── svi/
│ │ └── temp/ per-index copies of the programs
│ ├── data/ processed data
│ │ ├── optprc/
│ │ ├── vsurf/
│ │ ├── secprc/
│ │ ├── zeroc/
│ │ ├── divc/
│ │ ├── moments/
│ │ └── workspace/
│ └── raw/ input data
│ ├── optionm/
│ └── mdr/
├── errors/ forward rates and forecast errors
│ ├── code/ programs and launchers
│ │ └── functions/ MATLAB functions
│ ├── data/ processed data
│ │ ├── calibration/
│ │ └── matlab/
│ └── raw/ input data
├── cycl/ cyclicality
│ ├── code/ programs and launchers
│ ├── data/ processed data
│ └── raw/ input data
├── helper/ shared code
│ ├── code/ libraries and scripts
│ │ ├── ado/ Stata commands
│ │ └── functions/ MATLAB functions
│ │ └── exportfig/ export_fig
│ └── raw/ FRED series
├── output/ tables and figures
│ ├── figures/
│ └── tables/
│ ├── errors/
│ └── cycl/
├── README.html this document
└── LICENSE.txt
Each program has a .bash launcher of the same name, which loads the environment module and runs the program under SLURM. Two launchers also post-process their program’s output: ggl_regressions.bash turns the regression tables written by Stata into the nice_*.tex files, relabelling the rows, trimming the table environment, and deleting the intermediate files, and ggl_tables.bash concatenates the _rp and _er fragments of the horizon tables. The numbered run_*.bash scripts submit the launchers in the right order. The tables below list the programs of each stage in run order, with the number of jobs, cores, memory, and wall-time limit requested in the #SBATCH header of each program’s launcher and the files the program writes, after any post-processing. The label “login node” marks the scripts run with bash.
4.2 Moments Code
The moments stage constructs the option-implied moments. Its programs are run for each index by run_optionm_2.bash through run_optionm_8.bash:
| Program | Jobs | Cores | Memory | Wall time | Writes |
|---|---|---|---|---|---|
wrds/process_optionm.sas |
WRDS Cloud | – | – | – | data/optprc/optprc_USA_108105_1996_2025.txtdata/vsurf/vsurf_USA_108105.txtdata/secprc/secprc_USA_108105.txtraw/optionm/usa.zero_curve_1996_2025.txtraw/optionm/usa.index_dividend_1996_2025.txt |
wrds/process_compustat.sas |
WRDS Cloud | – | – | – | raw/compustat.security_price.txt |
code/run_optionm_2.bash |
1 | 1 | 2 GB | 4 h | submits process_optionm_1 and process_mdr |
code/process_optionm_1.R (per index) |
19 | 1 | 64 GB | 4 h | data/optprc/optprc_<ISO>_<SECID>.txtdata/vsurf/vsurf_<ISO>_<SECID>.txtdata/secprc/secprc_<ISO>_<SECID>.txt |
code/process_mdr.R |
1 | 1 | 64 GB | 4 h | data/optprc/optprc_USA_108105.txtraw/optionm/usa.zero_curve.txtraw/optionm/usa.index_dividend.txthelper/raw/fred_<SERIES>.txt |
code/run_optionm_3.bash |
1 | 1 | 2 GB | 4 h | submits process_optionm_2 |
code/process_optionm_2.R (per index) |
20 | 1 | 64 GB | 1 h | data/optprc/optprc_zeroc_<ISO>_<SECID>.txtdata/vsurf/vsurf_zeroc_<ISO>_<SECID>.txtdata/zeroc/zeroc_<ISO>_<SECID>.txtdata/divc/divc_<ISO>_<SECID>.txt |
code/run_optionm_4.bash |
1 | 1 | 2 GB | 4 h | submits optionm_moments_1 |
code/optionm_moments_1.m (per index) |
20 | 1 | 32 GB | 2 d | data/workspace/workspace_<ISO>_<SECID>_optprc_mid.matdata/workspace/workspace_<ISO>_<SECID>_optprc_bid.matdata/workspace/workspace_<ISO>_<SECID>_optprc_ask.matdata/workspace/workspace_<ISO>_<SECID>_vsurf.mat |
code/run_optionm_5.bash |
1 | 1 | 2 GB | 12 h | submits optionm_moments_2 |
code/optionm_moments_2.m (per index) |
20 | 12 | 12 x 32 GB | 3 d | data/moments/<ISO>_<SECID>_nsurf_*_nbid_*_nfilter_*_nbound_*_<moment>.txtdata/workspace/workspace_<ISO>_<SECID>_nsurf_0_nbid_*_nfilter_0_nbound_*.mat |
code/run_optionm_6.bash |
1 | 1 | 2 GB | 12 h | writes data/sample_svi.txt (the SVI indexes)submits optionm_moments_3 |
code/optionm_moments_3.m (per index, SVI) |
2 | 12 | 12 x 18 GB | 3 d | data/moments/<ISO>_<SECID>_nsurf_2_nbid_0_nfilter_1_nbound_0_<moment>.txtdata/workspace/workspace_<ISO>_<SECID>_nsurf_2_nbid_0_nfilter_1_nbound_0.mat |
code/run_optionm_7.bash |
1 | 1 | 2 GB | 12 h | writes data/sample_power.txt (the power-utility indexes)submits optionm_moments_4 |
code/optionm_moments_4.m (per index, power utility) |
10 | 12 | 12 x 18 GB | 18 h | data/moments/<ISO>_<SECID>_nsurf_0_nbid_0_nfilter_0_nbound_9_lvix_*.txtdata/workspace/workspace_<ISO>_<SECID>_nsurf_0_nbid_0_nfilter_0_nbound_9_power.mat |
code/run_optionm_8.bash |
login node | – | – | – | submits process_optionm_3 |
code/process_optionm_3.R |
1 | 1 | 64 GB | 4 h | data/optionm_moments_nsurf_*_nbid_*_nfilter_*_d.txtdata/optionm_moments_nsurf_*_nbid_*_nfilter_*_m.txtdata/optionm_power_moments_m.txt |
4.3 Errors Code
The errors stage constructs the forward rates and forecast errors and produces most of the tables and figures. run_ggl_2.bash submits its programs as SLURM jobs with afterok dependencies that follow the data flow: ggl_errors.R, ggl_matlab.m (which reads only the moments workspaces), and ggl_simulations.m (which reads nothing) start at once. ggl_calibration.m waits for ggl_errors.R and ggl_matlab.m, ggl_regressions.do waits for ggl_errors.R, ggl_figures.R waits for ggl_calibration.m and ggl_regressions.do, and ggl_tables.R waits for ggl_figures.R. The same script submits the three programs of the cycl stage (see Section 4.4) as soon as ggl_errors.R has finished, since they need only its output and the moments daily export:
| Program | Jobs | Cores | Memory | Wall time | Writes |
|---|---|---|---|---|---|
code/run_ggl_2.bash |
login node | – | – | – | submits the programs below with the dependencies above |
code/ggl_errors.R |
1 | 1 | 64 GB | 4 h | data/optionm_log_errors.txtdata/optionm_power_errors.txtdata/survey_spf_errors.txtdata/survey_cfo_errors.txtdata/survey_vanguard_errors.txtcycl/raw/spf_h.txtcycl/raw/cfo_q.txtcycl/raw/vanguard_m.txtdata/cross_spf_errors.txtdata/cross_cfo_errors.txtdata/cross_vanguard_errors.txtdata/calibration/moments_usa.txtdata/calibration/errors_usa.txt |
code/ggl_matlab.m |
1 | 1 | 32 GB | 4 h | data/matlab/observations_<ISO>_<SECID>.txtdata/matlab/openint_<ISO>_<SECID>.txtdata/matlab/observations_0{1..4}_<ISO>_<SECID>.txtdata/matlab/strikes_0{5..7}_<ISO>_<SECID>.txtdata/matlab/sigmalR_USA_108105.txtoutput/figures/triangulation_puts.pdfoutput/figures/triangulation_calls.pdf |
code/ggl_calibration.m |
1 | 12 | 12 x 64 GB | 12 h | data/calibration/thetaE_00.txtdata/calibration/thetaS_00.txtdata/calibration/{b,r2}{Pop,Avg,Lo,Hi}E_00.txtdata/calibration/{b,r2}{Pop,Avg,Lo,Hi}_gridE_00_usa.txtdata/workspace_calibration_00.matoutput/tables/errors/calib_param_00_usa.tex |
code/ggl_regressions.do |
1 | 1 | 32 GB | 4 h | output/tables/errors/nice_mincer_zarnowitz.texoutput/tables/errors/nice_mincer_zarnowitz_iv.texoutput/tables/errors/nice_average_error.texoutput/tables/errors/nice_error_predictability.texoutput/tables/errors/nice_survey_spf.texoutput/tables/errors/nice_survey_cfo.texoutput/tables/errors/nice_survey_vanguard.texoutput/tables/errors/nice_cross_predictability.texoutput/tables/errors/base_*.txt |
code/ggl_figures.R |
1 | 1 | 32 GB | 4 h | output/figures/*.tikz (28 files, see Section 5)output/tables/errors/price_impact.texdata/workspace_tabfig.RData |
code/ggl_tables.R |
1 | 1 | 32 GB | 4 h | output/tables/errors/sample.texoutput/tables/errors/sumstats_option.texoutput/tables/errors/sumstats_survey.texoutput/tables/errors/alternative_bounds.texoutput/tables/errors/alternative_measures.texoutput/tables/errors/split_sample.texoutput/tables/errors/short_horizons.texoutput/tables/errors/alternative_horizons_rp.texoutput/tables/errors/alternative_horizons_er.texoutput/tables/errors/alternative_samples.texoutput/tables/errors/power_utility.texoutput/tables/errors/long_horizons_perror.tex |
code/ggl_simulations.m |
1 | 1 | 32 GB | 4 h | output/figures/bls_truncation.pdfoutput/figures/svj_truncation.pdfoutput/figures/svj_extrapolation.pdfoutput/tables/errors/svj_param.tex |
4.4 Cyclicality Code
The cycl stage runs the cyclicality analysis on the output of the errors stage. Its three programs are submitted, in order, by run_ggl_2.bash once ggl_errors.R has finished. run_cycl_2.bash submits the same three programs on their own, for a rerun of this stage alone:
| Program | Jobs | Cores | Memory | Wall time | Writes |
|---|---|---|---|---|---|
code/run_cycl_2.bash |
login node | – | – | – | submits the programs below in order, for a standalone rerun |
code/cycl_proxies.R |
1 | 1 | 64 GB | 2 h | data/proxies_m.txtdata/proxies_q.txtdata/proxies_h.txtdata/option_m.txtdata/spf_h.txtdata/cfo_q.txtdata/vanguard_m.txthelper/raw/fred_<SERIES>.txt |
code/cycl_regressions.do |
1 | 1 | 16 GB | 4 h | output/tables/cycl/<investor>_<lhs>_<statevar>.texoutput/tables/cycl/<investor>_<lhs>_<statevar>.txt |
code/cycl_figures.R |
1 | 1 | 16 GB | 1 h | output/figures/cyclicality.tikzoutput/figures/cyclicality_forward_rp.tikzoutput/figures/cyclicality_forward_er.tikzoutput/figures/cyclicality_error_rp.tikzoutput/figures/cyclicality_error_er.tikzdata/cyclicality.txt |
4.5 Code Instructions
Prerequisites. You need a WRDS account with access to OptionMetrics IvyDB US, Compustat Global, and CRSP, the OptionMetrics IvyDB Europe and IvyDB Asia files, and the CBOE Market Data Replay files (see Section 2.2). You also need a FRED API key, entered in helper/code/libraries.R in place of the placeholder, internet access from the compute nodes for the FRED downloads, and the software of Section 3.1, including MATLAB with the Artelys Knitro interface, TinyTeX, and Ghostscript on the path. Every Stata command the code uses is included in the package. Scripts with an #SBATCH header are submitted with sbatch, and all other scripts are run with bash. Wait for all SLURM jobs of a step to finish (squeue -u $USER) before starting the next step.
Check the inputs. Place the package at
~/forward. Every input file of Section 2.2 must be in its listed location. Replace the pseudo-data files with the licensed data.Run the WRDS extraction. On the WRDS Cloud, run
moments/wrds/process_compustat.sasandmoments/wrds/process_optionm.saswithqsas, and copy their output files into themoments/data/andmoments/raw/locations listed in Section 2.2.3Run the moments stage. From
~/forward/moments/code/, runsbatch run_optionm_2.bashthroughsbatch run_optionm_7.bashin order, waiting for the jobs of each step to finish, and then runbash run_optionm_8.bash. Each submitter stays in the queue while it spaces out its submissions, so wait untilsqueueshows neither the submitter nor its jobs.4Run the errors and cyclicality stages. From
~/forward/errors/code/, runbash run_ggl_2.bash. It submits the errors programs and, afterggl_errors.R, the cyclicality programs. To rerun the cyclicality stage alone, runbash run_cycl_2.bashfrom~/forward/cycl/code/.5
There is no master script. The four steps run on two systems, the WRDS Cloud and the cluster, and on the cluster each step submits SLURM jobs that can take days and must finish before the next step starts. You therefore start each run_*.bash script by hand once the jobs of the previous step have finished.
We ran these instructions with the code in this package in August-September 2026, the WRDS extraction on the WRDS Cloud and the other steps on Mercury.
4.6 License
The code is licensed under the MIT License (see LICENSE.txt). The third-party code in helper/code/ado/ and helper/code/functions/exportfig/ (see Section 3.1) retains its original licenses. The data files distributed with the package are third-party data and remain subject to their providers’ terms of use (see Section 2.1), as LICENSE.txt also states.
5 List of Tables and Figures
The following tables list each table and figure in the paper and the Internet Appendix with the program that produces it and its output file. The R programs write the figures as .tikz files and the MATLAB programs as PDFs. The code reproduces all tables and figures in the paper and the Internet Appendix except Table 1 and Figure A13, which contain no computed results.
5.1 Main Paper
| Table/Figure | Script | Output file |
|---|---|---|
| Table 1 | – | not generated by code |
| Table 2 | errors/code/ggl_regressions.do |
output/tables/errors/nice_mincer_zarnowitz.tex |
| Table 3 | errors/code/ggl_regressions.do |
output/tables/errors/nice_average_error.tex |
| Table 4 | errors/code/ggl_regressions.do |
output/tables/errors/nice_error_predictability.tex |
| Table 5 | errors/code/ggl_regressions.do |
output/tables/errors/nice_survey_spf.texoutput/tables/errors/nice_survey_cfo.texoutput/tables/errors/nice_survey_vanguard.tex |
| Table 6 | errors/code/ggl_figures.R |
output/tables/errors/price_impact.tex |
| Figure 1 | errors/code/ggl_figures.R |
output/figures/crises_usa.tikz |
| Figure 2 | errors/code/ggl_figures.R |
output/figures/forward_spot_usa.tikz |
| Figure 3 | errors/code/ggl_figures.R |
output/figures/forward_error_usa.tikz |
| Figure 4 | errors/code/ggl_figures.R |
output/figures/forward_survey.tikz |
| Figure 5 | errors/code/ggl_figures.R |
output/figures/cyclicality_survey.tikz |
| Figure 6 | cycl/code/cycl_figures.R |
output/figures/cyclicality.tikz |
| Figure 7 | errors/code/ggl_figures.R |
output/figures/price_impact.tikz |
5.2 Internet Appendix
| Table/Figure | Script | Output file |
|---|---|---|
| Calibrated parameters (Internet Appendix, Section F.2.1) | errors/code/ggl_calibration.m |
output/tables/errors/calib_param_00_usa.tex |
| Table A1 | errors/code/ggl_tables.R |
output/tables/errors/sample.tex |
| Table A2 | errors/code/ggl_tables.R |
output/tables/errors/sumstats_option.texoutput/tables/errors/sumstats_survey.tex |
| Table A3 | errors/code/ggl_regressions.do |
output/tables/errors/nice_mincer_zarnowitz_iv.tex |
| Table A4 | errors/code/ggl_regressions.do |
output/tables/errors/nice_cross_predictability.tex |
| Table A5 | errors/code/ggl_tables.R |
output/tables/errors/alternative_bounds.tex |
| Table A6 | errors/code/ggl_tables.R |
output/tables/errors/alternative_measures.tex |
| Table A7 | errors/code/ggl_tables.R |
output/tables/errors/split_sample.tex |
| Table A8 | errors/code/ggl_tables.R |
output/tables/errors/short_horizons.tex |
| Table A9 | errors/code/ggl_tables.R |
output/tables/errors/alternative_horizons_rp.texoutput/tables/errors/alternative_horizons_er.tex |
| Table A10 | errors/code/ggl_tables.R |
output/tables/errors/alternative_samples.tex |
| Table A11 | errors/code/ggl_tables.R |
output/tables/errors/power_utility.tex |
| Table A12 | errors/code/ggl_tables.R |
output/tables/errors/long_horizons_perror.tex |
| Figure A1 | errors/code/ggl_figures.R |
output/figures/forward_option_survey.tikz |
| Figure A2 | cycl/code/cycl_figures.R |
output/figures/cyclicality_forward_rp.tikzoutput/figures/cyclicality_forward_er.tikz |
| Figure A3 | cycl/code/cycl_figures.R |
output/figures/cyclicality_error_rp.tikzoutput/figures/cyclicality_error_er.tikz |
| Figure A4 | errors/code/ggl_figures.R |
output/figures/price_impact_option.tikz |
| Figure A5 | errors/code/ggl_figures.R |
output/figures/equity_term_structure.tikz |
| Figure A6 | errors/code/ggl_simulations.m |
output/figures/bls_truncation.pdfoutput/figures/svj_truncation.pdfoutput/figures/svj_extrapolation.pdfoutput/tables/errors/svj_param.tex |
| Figure A7 | errors/code/ggl_figures.R |
output/figures/strikes_puts.tikzoutput/figures/strikes_calls.tikz |
| Figure A8 | errors/code/ggl_figures.R |
output/figures/forward_spot_bounds.tikz |
| Figure A9 | errors/code/ggl_figures.R |
output/figures/forward_cfo.tikz |
| Figure A10 | errors/code/ggl_figures.R |
output/figures/forward_perror_usa.tikz |
| Figure A11 | errors/code/ggl_figures.R |
output/figures/sigmalR_usa.tikz |
| Figure A12 | errors/code/ggl_figures.R |
output/figures/calib_main.tikzoutput/figures/calib_appendix.tikz |
| Figure A13 | – | not generated by code |
| Figure A14 | errors/code/ggl_figures.R |
output/figures/bls_weights.tikz |
| Figure A15 | errors/code/ggl_figures.R |
output/figures/observations.tikzoutput/figures/openint.tikz |
| Figure A16 | errors/code/ggl_figures.R |
output/figures/observations_maturity.tikz |
| Figure A17 | errors/code/ggl_figures.R |
output/figures/strikes_06p.tikzoutput/figures/strikes_06c.tikzoutput/figures/strikes_07p.tikzoutput/figures/strikes_07c.tikz |
| Figure A18 | errors/code/ggl_matlab.m |
output/figures/triangulation_puts.pdfoutput/figures/triangulation_calls.pdf |
| Figure A19 | errors/code/ggl_figures.R |
output/figures/current_spot_fs.tikzoutput/figures/realized_spot_fs.tikz |
| Figure A20 | errors/code/ggl_figures.R |
output/figures/power_utility.tikz |
6 Acknowledgements
This document follows the Social Science Data Editors’ template README (link) and the README guidance of the Review of Financial Studies data editors (link). This document and LICENSE.txt were prepared with the assistance of Claude Code (Anthropic, model Claude Fable 5.1).
We ran the code on Mercury, the high-performance computing cluster of the University of Chicago Booth School of Business, and are grateful for the computing resources and the staff support that the cluster provides. Mercury is supported by the Office of the Dean.
7 References
Footnotes
Mercury has no system Ghostscript. We built version 10.07.1 from source under
~/local, and the two launchers that callexport_figadd it to the path (see Paths below).↩︎The
gasearch is also limited to 1,200 seconds of wall-clock time (MaxTime). On a slower machine it may stop after fewer generations, so the results of the SVI robustness variant may not replicate exactly.↩︎In our run,
process_optionm.sastook about 7.5 minutes andprocess_compustat.sasa few seconds.↩︎We do not report a run time for this step. It is by far the most computationally expensive part of the pipeline, and its duration varies widely across indexes, runs, and queue conditions. We ran it in pieces over several weeks, rerunning some indexes, so our run gives no single figure. The wall-time limits in Section 4.2 bound each job.↩︎
In our run, the jobs submitted by
run_ggl_2.bashfinished 2 hours and 36 minutes after submission.ggl_calibration.mtook 1 hour and 46 minutes,ggl_figures.R28 minutes,ggl_errors.R20 minutes, and each of the other errors programs 5 minutes or less. The three cyclicality programs took about 13 minutes together and finished whileggl_calibration.mwas running.↩︎