1"""Build paper/references.bib ONLY from bibliographic records verified against a public registry.23Each candidate is (bibkey, identifier, expected title fragment). The identifier is a Crossref DOI, an4``arXiv:<id>`` or an ``openalex:<Wid>``; alternatives can be chained with `` || `` (tried in order). A record5is written to the .bib only when the fetched title contains the expected fragment (case-insensitive). Items6without any registry record (books, technical documents, pre-DOI working papers) may be included through the7MANUAL list, but only with a URL that was actually fetched and confirmed on the recorded date. Everything else8goes to results/metrics/references_unverified.json and is never cited.910Outputs11 paper/references.bib12 results/metrics/references_verification.json (per bibkey: identifier, fetched title, status, date, source)13 results/metrics/references_unverified.json1415Run: .venv/bin/python scripts/build_references.py16Rate: ~2 requests/s against api.crossref.org (polite pool, mailto in User-Agent), export.arxiv.org, api.openalex.org.17Literature cutoff: 2026-11-09.18"""19from __future__ import annotations2021import datetime as dt22import json23import re24import sys25import time26import urllib.parse27import urllib.request28import xml.etree.ElementTree as ET29from pathlib import Path3031ROOT = Path(__file__).resolve().parents[1]32MAILTO = "simon-pierre.boucher@uqo.ca"33UA = {"User-Agent": f"wp46-garch-benchmark/0.1 (mailto:{MAILTO})"}34SLEEP = 0.5 # seconds between requests (~2 req/s)35TODAY = dt.date.today().isoformat()3637# --------------------------------------------------------------------------------------------------------------38# Candidates: (bibkey, identifier, expected title fragment). Bibkey = firstauthorYEARfirstword (lowercase); the39# year is the print-volume year. Grouped by literature-matrix block (see docs/literature_matrix.md).40# --------------------------------------------------------------------------------------------------------------41CANDIDATES: list[tuple[str, str | None, str | None]] = [42 # --- genealogy additions (verified via Crossref on 2026-11-09, results/metrics/references_candidates_genealogy.json)43 ("hentschel1995all", "10.1016/0304-405X(94)00821-H", "nesting symmetric and asymmetric"),44 ("duan1997augmented", "10.1016/S0304-4076(97)00009-2", "augmented garch (p,q) process and its di"),45 ("maheu2004news", "10.1111/j.1540-6261.2004.00648.x", "news arrival, jump dynamics, and volatil"),46 ("bollerslev1996periodic", "10.1080/07350015.1996.10524640", "periodic autoregressive conditional hete"),47 ("engle2012dynamic", "10.1080/07350015.2011.652048", "dynamic equicorrelation"),48 ("engle1990asset", "10.1016/0304-4076(90)90099-F", "asset pricing with a factor-arch covaria"),49 ("bollerslev1988capital", "10.1086/261527", "a capital asset pricing model with time-"),50 ("engle1990discussion", "10.1093/rfs/3.1.103", "discussion"),51 ("geweke1986comment", "10.1080/07474938608800097", "commet"),52 ("pantula1986comment", "10.1080/07474938608800099", "comment"),53 ("rabemananjara1993threshold", "10.1002/jae.3950080104", "threshold arch models and asymmetries in"),54 ("engle1998autoregressive", "10.2307/2999632", "autoregressive conditional duration: a n"),55 ("li1996double", "10.1002/(SICI)1099-1255(199605)11:3<253::AID-JAE393>3.0.CO;2-8", "on a double-threshold autoregressive het"),56 # ---- (a) univariate ARCH/GARCH architectures -------------------------------------------------------------57 ("engle1982autoregressive", "10.2307/1912773", "autoregressive conditional heteroscedasticity"),58 ("bollerslev1986generalized", "10.1016/0304-4076(86)90063-1", "generalized autoregressive conditional heteroskedasticity"),59 ("engle1986modelling", "10.1080/07474938608800095", "modelling the persistence of conditional variances"),60 ("engle1987estimating", "10.2307/1913242", "arch-m"),61 ("nelson1991conditional", "10.2307/2938260", "conditional heteroskedasticity in asset returns"),62 ("glosten1993relation", "10.1111/j.1540-6261.1993.tb05128.x", "volatility of the nominal excess return"),63 ("zakoian1994threshold", "10.1016/0165-1889(94)90039-6", "threshold heteroskedastic models"),64 ("ding1993long", "10.1016/0927-5398(93)90006-D", "long memory property of stock market returns"),65 ("schwert1989why", "10.1111/j.1540-6261.1989.tb02647.x", "why does stock market volatility change over time"),66 ("engle1993measuring", "10.1111/j.1540-6261.1993.tb05127.x", "impact of news on volatility"),67 ("higgins1992class", "10.2307/2526988", "class of nonlinear arch models"),68 ("sentana1995quadratic", "10.2307/2298081", "quadratic arch models"),69 ("baillie1996fractionally", "10.1016/S0304-4076(95)01749-6", "fractionally integrated generalized autoregressive"),70 ("bollerslev1996modeling", "10.1016/0304-4076(95)01736-4", "long memory in stock market volatility"),71 ("tse1998conditional", "10.1002/(SICI)1099-1255(199801/02)13:1<49::AID-JAE459>3.0.CO;2-O", "yen-dollar exchange rate"),72 ("davidson2004moment", "10.1198/073500103288619359", "moment and memory properties"),73 ("engle1999long", "10.1093/oso/9780198296836.003.0020", "component model of stock return volatility"),74 ("hamilton1994autoregressive", "10.1016/0304-4076(94)90067-1", "changes in regime"),75 ("cai1994markov", "10.1080/07350015.1994.10524546", "switching-regime arch"),76 ("gray1996modeling", "10.1016/0304-405X(96)00875-6", "regime-switching process"),77 ("klaassen2002improving", "10.1007/s001810100100", "regime-switching garch"),78 ("haas2004new", "10.1093/jjfinec/nbh020", "markov-switching garch"),79 ("bauwens2010theory", "10.1111/j.1368-423X.2009.00307.x", "markov switching garch"),80 ("augustyniak2014maximum", "10.1016/j.csda.2013.01.026", "markov-switching garch"),81 ("ardia2019markov", "10.18637/jss.v091.i04", "msgarch"),82 ("hamilton1989new", "10.2307/1912559", "nonstationary time series and the business cycle"),83 ("gonzalezrivera1998smooth", "10.2202/1558-3708.1041", "smooth-transition garch"),84 ("hagerud1997smooth", None, None), # SSE/EFI WP 162 (no DOI) -> MANUAL85 ("engle2013stock", "10.1162/REST_a_00300", "macroeconomic fundamentals"),86 ("ghysels2006predicting", "10.1016/j.jeconom.2005.01.004", "sampled at different frequencies"),87 ("ghysels2007midas", "10.1080/07474930600972467", "midas regressions"),88 ("engle2008spline", "10.1093/rfs/hhn004", "spline-garch"),89 ("engle2011forecasting", "10.1093/jjfinec/nbr005", "multiplicative component garch"),90 ("jpmorgan1996riskmetrics", None, None), # technical document (no DOI) -> MANUAL91 ("zumbach2009riskmetrics", "10.2139/ssrn.1420185", "riskmetrics 2006"),92 ("creal2013generalized", "10.1002/jae.1279", "generalized autoregressive score models"),93 ("harvey2013dynamic", "10.1017/CBO9781139540933", "dynamic models for volatility and heavy tails"),94 ("harvey2014egarch", "10.1016/j.csda.2013.09.022", "egarch models with fat tails"),95 ("harvey2008beta", None, None), # Cambridge WP 0840 (no DOI) -> MANUAL96 ("blasques2015information", "10.1093/biomet/asu076", "observation-driven time series models"),97 ("ardia2019generalized", "10.18637/jss.v088.i06", "gas package"),98 ("taylor2008modelling", "10.1142/6578", "modelling financial time series"),99 ("taylor1994modeling", "10.1111/j.1467-9965.1994.tb00057.x", "modeling stochastic volatility"),100 ("kim1998stochastic", "10.1111/1467-937X.00050", "stochastic volatility: likelihood inference"),101 ("jacquier1994bayesian", "10.1080/07350015.1994.10524553", "bayesian analysis of stochastic volatility"),102 ("harvey1994multivariate", "10.2307/2297980", "multivariate stochastic variance"),103 ("pagan1990alternative", "10.1016/0304-4076(90)90101-X", "alternative models for conditional stock volatility"),104 ("ding1996modeling", "10.1016/0304-4076(95)01737-2", "volatility persistence of speculative returns"),105 # innovation distributions106 ("bollerslev1987conditionally", "10.2307/1925546", "conditionally heteroskedastic time series model"),107 ("hansen1994autoregressive", "10.2307/2527081", "autoregressive conditional density estimation"),108 ("fernandez1998bayesian", "10.1080/01621459.1998.10474117", "fat tails and skewness"),109 # QMLE theory, stationarity, moments, constraints110 ("bollerslev1992quasi", "10.1080/07474939208800229", "quasi-maximum likelihood estimation and inference"),111 ("lee1994asymptotic", "10.1017/S0266466600008215", "garch(1,1) quasi-maximum likelihood"),112 ("lumsdaine1996consistency", "10.2307/2171862", "igarch(1,1)"),113 ("jensen2004asymptotic", "10.1111/j.1468-0262.2004.00504.x", "qmle estimator of arch"),114 ("francq2004maximum", "10.3150/bj/1093265632", "pure garch and arma-garch"),115 ("straumann2006quasi", "10.1214/009053606000000803", "stochastic recurrence equations approach"),116 ("nelson1990stationarity", "10.1017/S0266466600005296", "stationarity and persistence"),117 ("bougerol1992stationarity", "10.1016/0304-4076(92)90067-2", "stationarity of garch processes"),118 ("he1999properties", "10.1016/S0304-4076(98)00089-X", "properties of moments"),119 ("ling2002stationarity", "10.1016/S0304-4076(01)00090-2", "existence of moments"),120 ("ling2002necessary", "10.1017/S0266466602183071", "necessary and sufficient moment conditions"),121 ("conrad2006inequality", "10.1093/jjfinec/nbj015", "fractionally integrated garch"),122 ("chung1999estimating", None, None), # NTU working paper: no registry record found -> unverified123 ("nelson1992inequality", "10.1080/07350015.1992.10509902", "inequality constraints in the univariate garch"),124 ("lamoureux1990persistence", "10.1080/07350015.1990.10509794", "persistence in variance"),125 ("mikosch2004nonstationarities", "10.1162/003465304323023886", "igarch effects"),126 ("hillebrand2005neglecting", "10.1016/j.jeconom.2004.09.005", "neglecting parameter changes"),127 ("lundbergh2002evaluating", "10.1016/S0304-4076(02)00096-9", "evaluating garch models"),128 # surveys, textbooks, handbooks129 ("engle2001garch", "10.1257/jep.15.4.157", "garch 101"),130 ("bollerslev1992arch", "10.1016/0304-4076(92)90064-X", "arch modeling in finance"),131 ("bollerslev1994arch", "10.1016/S1573-4412(05)80018-2", "arch models"),132 ("terasvirta2009introduction", "10.1007/978-3-540-71297-8_1", "univariate garch models"),133 ("engle2004risk", "10.1257/0002828041464597", "risk and volatility"),134 ("bollerslev2010glossary", "10.1093/acprof:oso/9780199549498.003.0008", "glossary to arch"),135 ("engle2001what", "10.1088/1469-7688/1/2/305", "what good is a volatility model"),136 ("francq2019garch", "10.1002/9781119313472", "garch models"),137 ("bauwens2012handbook", "10.1002/9781118272039", "handbook of volatility models"),138 # ---- (b) realized measures and realized-measure models ------------------------------------------------------139 ("andersen1998answering", "10.2307/2527343", "answering the skeptics"),140 ("andersen2001distribution", "10.1198/016214501750332965", "realized exchange rate volatility"),141 ("andersen2001distributionstock", "10.1016/S0304-405X(01)00055-1", "realized stock return volatility"),142 ("andersen2003modeling", "10.1111/1468-0262.00418", "modeling and forecasting realized volatility"),143 ("barndorff2002econometric", "10.1111/1467-9868.00336", "econometric analysis of realized volatility"),144 ("barndorff2004power", "10.1093/jjfinec/nbh001", "power and bipower variation"),145 ("barndorff2008designing", "10.3982/ECTA6495", "designing realized kernels"),146 ("barndorff2009realized", "10.1111/j.1368-423X.2008.00275.x", "realized kernels in practice"),147 ("barndorff2010measuring", "10.1093/acprof:oso/9780199549498.003.0007", "realized semivariance"),148 ("hansen2006realized", "10.1198/073500106000000071", "market microstructure noise"),149 ("hansen2005realized", "10.1093/jjfinec/nbi028", "realized variance for the whole day"),150 ("hansen2006consistent", "10.1016/j.jeconom.2005.01.005", "consistent ranking of volatility models"),151 ("zhang2005tale", "10.1198/016214505000000169", "tale of two time scales"),152 ("aitsahalia2005how", "10.1093/rfs/hhi016", "how often to sample"),153 ("jacod2009microstructure", "10.1016/j.spa.2008.11.004", "pre-averaging approach"),154 ("liu2015does", "10.1016/j.jeconom.2015.02.008", "does anything beat 5-minute rv"),155 ("corsi2009simple", "10.1093/jjfinec/nbp001", "simple approximate long-memory model"),156 ("andersen2007roughing", "10.1162/rest.89.4.701", "roughing it up"),157 ("patton2015good", "10.1162/REST_a_00503", "good volatility, bad volatility"),158 ("bollerslev2016exploiting", "10.1016/j.jeconom.2015.10.007", "exploiting the errors"),159 ("engle2002new", "10.1002/jae.683", "new frontiers for arch models"),160 ("engle2006multiple", "10.1016/j.jeconom.2005.01.018", "multiple indicators model for volatility"),161 ("shephard2010realising", "10.1002/jae.1158", "heavy"),162 ("hansen2012realized", "10.1002/jae.1234", "realized garch"),163 ("hansen2016exponential", "10.1080/07350015.2015.1038543", "exponential garch modeling with realized measures"),164 ("noureldin2012multivariate", "10.1002/jae.1260", "heavy"),165 ("andersen2005correcting", "10.1111/j.1468-0262.2005.00572.x", "correcting the errors"),166 ("andersen2011realized", "10.1016/j.jeconom.2010.03.032", "realized volatility forecasting and market microstructure noise"),167 ("patton2009optimal", "10.1016/j.ijforecast.2009.01.011", "optimal combinations of realised volatility estimators"),168 ("andersen2010parametric", "10.1016/B978-0-444-50897-3.50005-5", "parametric and nonparametric volatility measurement"),169 ("andersen1999forecasting", "10.1016/S0927-5398(99)00013-4", "sample frequency"),170 ("fleming2003economic", "10.1016/S0304-405X(02)00259-3", "economic value of volatility timing"),171 ("hansen2014realized", "10.1002/jae.2389", "realized beta garch"),172 ("archakov2026multivariate", "10.1016/j.jeconom.2025.106040", "multivariate realized garch"),173 ("bollerslev2018modeling", "10.1016/j.jeconom.2018.05.004", "realized covariances"),174 # ---- (c) multivariate ----------------------------------------------------------------------------------------175 ("bollerslev1990modelling", "10.2307/2109358", "multivariate generalized arch"),176 ("engle1995multivariate", "10.1017/S0266466600009063", "multivariate simultaneous generalized arch"),177 ("engle2002dynamic", "10.1198/073500102288618487", "dynamic conditional correlation"),178 ("engle2001theoretical", "10.3386/w8554", "dynamic conditional correlation"),179 ("tse2002multivariate", "10.1198/073500102288618496", "time-varying correlations"),180 ("cappiello2006asymmetric", "10.1093/jjfinec/nbl005", "asymmetric dynamics in the correlations"),181 ("vanderweide2002gogarch", "10.1002/jae.688", "generalized orthogonal garch"),182 ("aielli2013dynamic", "10.1080/07350015.2013.771027", "dynamic conditional correlation: on properties"),183 ("bauwens2006multivariate", "10.1002/jae.842", "multivariate garch models: a survey"),184 ("silvennoinen2009multivariate", "10.1007/978-3-540-71297-8_9", "multivariate garch models"),185 ("engle2019large", "10.1080/07350015.2017.1345683", "large dynamic covariance matrices"),186 ("pakel2021fitting", "10.1080/07350015.2020.1713795", "vast dimensional"),187 ("laurent2012forecasting", "10.1002/jae.1248", "forecasting accuracy of multivariate garch"),188 ("laurent2013loss", "10.1016/j.jeconom.2012.08.004", "loss functions and ranking"),189 ("patton2009evaluating", "10.1007/978-3-540-71297-8_36", "evaluating volatility and correlation forecasts"),190 ("engle2006testing", "10.1198/073500106000000017", "dynamic correlations for asset allocation"),191 ("caporin2014robust", "10.1016/j.csda.2012.05.012", "robust ranking of multivariate garch"),192 ("creal2011dynamic", "10.1198/jbes.2011.10070", "dynamic multivariate heavy-tailed model"),193 # ---- (d) forecast evaluation and inference -------------------------------------------------------------------194 ("patton2011volatility", "10.1016/j.jeconom.2010.03.034", "imperfect volatility proxies"),195 ("hansen2005forecast", "10.1002/jae.800", "does anything beat a garch(1,1)"),196 ("hansen2003choosing", "10.1046/j.0305-9049.2003.00086.x", "model confidence set approach"),197 ("diebold1995comparing", "10.1080/07350015.1995.10524599", "comparing predictive accuracy"),198 ("diebold2015comparing", "10.1080/07350015.2014.983236", "twenty years later"),199 ("harvey1997testing", "10.1016/S0169-2070(96)00719-4", "prediction mean squared errors"),200 ("west1996asymptotic", "10.2307/2171956", "asymptotic inference about predictive ability"),201 ("giacomini2006tests", "10.1111/j.1468-0262.2006.00718.x", "conditional predictive ability"),202 ("clark2007approximately", "10.1016/j.jeconom.2006.05.023", "nested models"),203 ("white2000reality", "10.1111/1468-0262.00152", "reality check"),204 ("hansen2005test", "10.1198/073500105000000063", "superior predictive ability"),205 ("hansen2011model", "10.3982/ECTA5771", "model confidence set"),206 ("romano2005stepwise", "10.1111/j.1468-0262.2005.00615.x", "stepwise multiple testing"),207 ("holm1979simple", "10.2307/4615733 || openalex:W2121044470", "sequentially rejective"),208 ("politis1994stationary", "10.1080/01621459.1994.10476870", "stationary bootstrap"),209 ("politis2004automatic", "10.1081/ETC-120028836", "automatic block-length selection"),210 ("newey1987simple", "10.2307/1913610", "heteroskedasticity and autocorrelation consistent"),211 ("newey1994automatic", "10.2307/2297912", "automatic lag selection"),212 ("mincer1969evaluation", None, None), # NBER chapter (no DOI) -> MANUAL213 ("poon2003forecasting", "10.1257/jel.41.2.478", "forecasting volatility in financial markets"),214 ("awartani2005predicting", "10.1016/j.ijforecast.2004.08.003", "role of asymmetries"),215 ("brownlees2011practical", "10.21314/JOR.2012.237", "calm and storm"),216 ("bollerslev2018risk", "10.1093/rfs/hhy041", "risk everywhere"),217 ("patton2020comparing", "10.1080/07350015.2019.1585256", "comparing possibly misspecified forecasts"),218 ("gneiting2011making", "10.1198/jasa.2011.r10138", "making and evaluating point forecasts"),219 ("gneiting2007strictly", "10.1198/016214506000001437", "strictly proper scoring rules"),220 ("amisano2007comparing", "10.1198/073500106000000332", "weighted likelihood ratio tests"),221 ("diks2011likelihood", "10.1016/j.jeconom.2011.04.001", "density forecasts in tails"),222 ("lopez2001evaluating", "10.1002/1099-131X(200103)20:2<87::AID-FOR782>3.0.CO;2-7", "predictive accuracy of volatility models"),223 ("hansen2015equivalence", "10.3982/ECTA10581", "wald statistics"),224 ("christoffersen2000how", "10.1162/003465300558597", "how relevant is volatility forecasting"),225 ("kourtis2016international", "10.1002/fut.21792", "implied, realized, and garch volatility forecasts"),226 # ---- (e) tail risk -------------------------------------------------------------------------------------------227 ("kupiec1995techniques", "10.3905/jod.1995.407942", "risk measurement models"),228 ("christoffersen1998evaluating", "10.2307/2527341", "evaluating interval forecasts"),229 ("christoffersen2004backtesting", "10.1093/jjfinec/nbh004", "duration-based approach"),230 ("engle2004caviar", "10.1198/073500104000000370", "caviar"),231 ("berkowitz2011evaluating", "10.1287/mnsc.1080.0964", "desk-level data"),232 ("fissler2016higher", "10.1214/16-AOS1439", "higher order elicitability"),233 ("fissler2015expected", "arXiv:1507.00244", "jointly elicitable"), # arXiv v1 2015; Risk magazine version 2016234 ("patton2019dynamic", "10.1016/j.jeconom.2018.10.008", "dynamic semiparametric models for expected shortfall"),235 ("acerbi2014backtesting", "openalex:W2292483766", "backtesting expected shortfall"),236 ("nolde2017elicitability", "10.1214/17-AOAS1041", "elicitability and backtesting"),237 ("mcneil2000estimation", "10.1016/S0927-5398(00)00012-8", "extreme value approach"),238 ("bayer2022regression", "10.1093/jjfinec/nbaa013", "regression-based expected shortfall backtesting"),239 ("dimitriadis2019joint", "10.1214/19-EJS1560", "joint quantile and expected shortfall regression"),240 ("taylor2019forecasting", "10.1080/07350015.2017.1281815", "asymmetric laplace"),241 ("ziegel2016coherence", "10.1111/mafi.12080", "coherence and elicitability"),242 ("kuester2006value", "10.1093/jjfinec/nbj002", "value-at-risk prediction"),243 ("giot2003value", "10.1002/jae.710", "long and short trading positions"),244 # ---- (f) large-scale benchmarks, ML extensions, software ---------------------------------------------------245 ("marcucci2005forecasting", "10.2202/1558-3708.1145", "regime-switching garch models"),246 ("andersen2006volatility", "10.1016/S1574-0706(05)01015-3", "volatility and correlation forecasting"),247 ("ardia2018forecasting", "10.1016/j.ijforecast.2018.05.004", "large-scale performance study"),248 ("christensen2023machine", "10.1093/jjfinec/nbac020", "machine learning approach to volatility forecasting"),249 ("bucci2020realized", "10.1093/jjfinec/nbaa008", "neural networks"),250 ("zhang2024volatility", "10.1093/jjfinec/nbad005", "intraday commonality"),251 ("rahimikia2024machine", "10.2139/ssrn.4857569", "machine learning for realised volatility forecasting"),252 ("rahimikia2021realised", "arXiv:2108.00480", "financial word embedding"),253 ("lyocsa2021stock", "10.1016/j.ijforecast.2020.12.001", "do we need high-frequency data"),254 ("clements2021practical", "10.1016/j.jbankfin.2021.106285", "har volatility model"),255 ("gunnarsson2024prediction", "10.1016/j.irfa.2024.103221", "ai and machine learning: a review"),256 ("branco2024forecasting", "10.1016/j.jempfin.2024.101524", "does anything beat linear models"),257 ("kim2018forecasting", "10.1016/j.eswa.2018.03.002", "lstm with multiple garch-type"),258 ("reisenhofer2022harnet", "arXiv:2205.07719", "harnet"),259 ("brini2026forecasting", "arXiv:2607.05291", "time series foundation models"),260 ("brini2024comparison", "arXiv:2404.04962", "cryptocurrency volatility"),261 ("catania2019forecasting", "10.1016/j.ijforecast.2018.09.005", "forecasting cryptocurrencies"),262 ("ardia2019regime", "10.1016/j.frl.2018.08.009", "bitcoin garch volatility dynamics"),263 ("trucios2019forecasting", "10.1016/j.ijforecast.2019.01.003", "bitcoin risk measures"),264 # software (CRAN DOIs are Crossref-registered; the arch package is on Zenodo/DataCite -> MANUAL)265 ("sheppard2025arch", None, None),266 ("galanos2011rugarch", "10.32614/CRAN.package.rugarch", "rugarch"),267 ("galanos2013rmgarch", "10.32614/CRAN.package.rmgarch", "rmgarch"),268 ("boudt2012highfrequency", "10.32614/CRAN.package.highfrequency", "highfrequency"),269 ("ardia2016msgarch", "10.32614/CRAN.package.MSGARCH", "msgarch"),270 ("catania2014mcs", "10.32614/CRAN.package.MCS", "model confidence set"),271 ("bayer2020esback", "10.32614/CRAN.package.esback", "esback"),272]273274# Records whose Crossref author list is truncated or empty (checked 2026-11-09 against the journal/OpenAlex275# record); the DOI and title were verified by the fetch, only the author field is completed here.276AUTHOR_FIX = {277 "barndorff2004power": "Barndorff-Nielsen, Ole E. and Shephard, Neil",278 "barndorff2008designing": "Barndorff-Nielsen, Ole E. and Hansen, Peter Reinhard and Lunde, Asger and Shephard, Neil",279 "hansen2005realized": "Hansen, Peter Reinhard and Lunde, Asger",280 "hansen2011model": "Hansen, Peter R. and Lunde, Asger and Nason, James M.",281 "haas2004new": "Haas, Markus and Mittnik, Stefan and Paolella, Marc S.",282 "kuester2006value": "Kuester, Keith and Mittnik, Stefan and Paolella, Marc S.",283 "christoffersen2004backtesting": "Christoffersen, Peter and Pelletier, Denis",284 "conrad2006inequality": "Conrad, Christian and Haag, Berthold R.",285 "andersen2001distributionstock": "Andersen, Torben G. and Bollerslev, Tim and Diebold, Francis X. and Ebens, Heiko",286 "bollerslev2010glossary": "Bollerslev, Tim",287 "jpmorgan1996riskmetrics": "{J.P. Morgan/Reuters}",288}289EDITOR_FIX = {"bauwens2012handbook": "Bauwens, Luc and Hafner, Christian M. and Laurent, S{\\'e}bastien"}290# Crossref metadata typos corrected from the publisher page fetched 2026-11-09291# (https://academic.oup.com/book/52280/chapter/421087965: authors Robert F. Engle and Gary G. J. Lee, editors R. F. Engle and292# H. White, Oxford, 1999, pp. 475-497).293FIELD_FIX = {"geweke1986comment": {"title": "Comment"},294 "engle1999long": {"author": "Engle, Robert F. and Lee, Gary G. J.", "editor": "Engle, Robert F. and White, Halbert",295 "booktitle": "Cointegration, Causality, and Forecasting: A Festschrift in Honour of Clive W. J. Granger",296 "publisher": "Oxford University Press", "address": "Oxford"}}297298# Print-volume year when Crossref's 'issued' date is the online-first date (volume/issue checked 2026-11-09).299YEAR_FIX = {300 "corsi2009simple": 2009, "creal2013generalized": 2013, "laurent2012forecasting": 2012, "noureldin2012multivariate": 2012,301 "hansen2012realized": 2012, "engle2019large": 2019, "christensen2023machine": 2023, "zhang2024volatility": 2024,302 "bayer2022regression": 2022, "taylor2019forecasting": 2019, "patton2020comparing": 2020, "pakel2021fitting": 2021,303 "kuester2006value": 2006, "ziegel2016coherence": 2016, "taylor2008modelling": 2008, "brownlees2011practical": 2011,304 "engle2011forecasting": 2011, "hansen2016exponential": 2016, "archakov2026multivariate": 2026,305}306307# Items with no registry record. Each URL was fetched on the recorded date and the bibliographic data below was read308# from the fetched page/PDF (nothing is taken from memory).309MANUAL = {310 "hagerud1997smooth": {311 "url": "https://econpapers.repec.org/paper/hhshastef/0162.htm", "checked": "2026-11-09",312 "evidence": "EconPapers record: Hagerud, G. E., 'A Smooth Transition ARCH Model for Asset Returns', SSE/EFI Working Paper Series in Economics and Finance No. 162, March 1997.",313 "bib": "@techreport{hagerud1997smooth,\n author = {Hagerud, Gustaf E.},\n title = {A Smooth Transition {ARCH} Model for Asset Returns},\n institution = {Stockholm School of Economics},\n type = {SSE/EFI Working Paper Series in Economics and Finance},\n number = {162},\n year = {1997},\n url = {https://econpapers.repec.org/paper/hhshastef/0162.htm}\n}",314 },315 "harvey2008beta": {316 "url": "https://econpapers.repec.org/paper/camcamdae/0840.htm", "checked": "2026-11-09",317 "evidence": "EconPapers record: Harvey, A. and Chakravarty, T., 'Beta-t-(E)GARCH', Cambridge Working Papers in Economics 0840, September 2008.",318 "bib": "@techreport{harvey2008beta,\n author = {Harvey, Andrew and Chakravarty, Tirthankar},\n title = {Beta-t-({E}){GARCH}},\n institution = {University of Cambridge, Faculty of Economics},\n type = {Cambridge Working Papers in Economics},\n number = {0840},\n year = {2008},\n url = {https://econpapers.repec.org/paper/camcamdae/0840.htm}\n}",319 },320 "mincer1969evaluation": {321 "url": "https://www.nber.org/books-and-chapters/economic-forecasts-and-expectations-analysis-forecasting-behavior-and-performance/evaluation-economic-forecasts",322 "checked": "2026-11-09",323 "evidence": "NBER chapter page: Mincer, J. A. and Zarnowitz, V., 'The Evaluation of Economic Forecasts', chapter 1 in J. A. Mincer (ed.), Economic Forecasts and Expectations: Analysis of Forecasting Behavior and Performance, NBER, 1969 (page range not shown on the page, so omitted).",324 "bib": "@incollection{mincer1969evaluation,\n author = {Mincer, Jacob A. and Zarnowitz, Victor},\n title = {The Evaluation of Economic Forecasts},\n booktitle = {Economic Forecasts and Expectations: Analysis of Forecasting Behavior and Performance},\n editor = {Mincer, Jacob A.},\n publisher = {National Bureau of Economic Research},\n address = {New York},\n year = {1969},\n url = {https://www.nber.org/books-and-chapters/economic-forecasts-and-expectations-analysis-forecasting-behavior-and-performance/evaluation-economic-forecasts}\n}",325 },326 "jpmorgan1996riskmetrics": {327 "url": "https://www.msci.com/documents/10199/5915b101-4206-4ba0-aee2-3449d5c7e95a", "checked": "2026-11-09",328 "evidence": "PDF fetched from MSCI (HTTP 200, application/pdf); cover page reads 'J.P.Morgan/Reuters, RiskMetrics -- Technical Document, Fourth Edition, 1996, New York, December 17, 1996, Morgan Guaranty Trust Company, Risk Management Advisory'.",329 "bib": "@techreport{jpmorgan1996riskmetrics,\n author = {{J.P. Morgan/Reuters}},\n title = {{RiskMetrics}---Technical Document},\n edition = {Fourth},\n institution = {Morgan Guaranty Trust Company, Risk Management Advisory},\n address = {New York},\n year = {1996},\n note = {17 December 1996},\n url = {https://www.msci.com/documents/10199/5915b101-4206-4ba0-aee2-3449d5c7e95a}\n}",330 },331 "sheppard2025arch": {332 "url": "https://zenodo.org/api/records/17404619", "checked": "2026-11-09",333 "evidence": "Zenodo API record 17404619: 'bashtage/arch: Release v8.0.0', version v8.0.0, publication_date 2025-10-21, DOI 10.5281/zenodo.17404619 (concept DOI 10.5281/zenodo.593254), creators Kevin Sheppard, Stanislav Khrapov, Gabor Liptak, et al. DataCite DOI (not Crossref), hence manual.",334 "bib": "@misc{sheppard2025arch,\n author = {Sheppard, Kevin and Khrapov, Stanislav and Lipt{\\'a}k, G{\\'a}bor and others},\n title = {bashtage/arch: Release v8.0.0},\n howpublished = {Zenodo (software)},\n year = {2025},\n month = oct,\n version = {8.0.0},\n doi = {10.5281/zenodo.17404619},\n url = {https://doi.org/10.5281/zenodo.17404619},\n note = {Concept DOI 10.5281/zenodo.593254}\n}",335 },336}337338# Venue completion for OpenAlex-only records (not stored in the OpenAlex record; read from the fetched page listed).339OPENALEX_NOTE = {340 "acerbi2014backtesting": ("Risk (Risk.net technical paper)", "https://www.risk.net/risk-magazine/technical-paper/2381658/back-testing-expected-shortfall"),341}342343344# --------------------------------------------------------------------------------------------------------------345def tex(s: str) -> str:346 return (s.replace("\\", "\\textbackslash{}").replace("&", "\\&").replace("%", "\\%").replace("_", "\\_")347 .replace("#", "\\#").replace("$", "\\$"))348349350def clean_title(t: str) -> str:351 return " ".join(re.sub(r"<[^>]+>", "", t).replace("‐", "-").replace("‑", "-").split())352353354def get(url: str, retries: int = 2) -> bytes | None:355 for i in range(retries + 1):356 try:357 with urllib.request.urlopen(urllib.request.Request(url, headers=UA), timeout=40) as r:358 return r.read()359 except Exception as exc: # noqa: BLE001360 last = str(exc)[:120]361 time.sleep(1.5 * (i + 1))362 return None if last is None else (b"__ERR__" + last.encode())363364365def crossref(doi: str) -> dict:366 raw = get(f"https://api.crossref.org/works/{urllib.parse.quote(doi, safe='/')}")367 if raw is None or raw.startswith(b"__ERR__"):368 return {"_error": (raw or b"no response")[7:].decode(errors="replace")}369 return json.loads(raw)["message"]370371372def arxiv(aid: str) -> dict:373 raw = get(f"https://export.arxiv.org/api/query?id_list={aid}")374 if raw is None or raw.startswith(b"__ERR__") or not raw.strip():375 return {"_error": "arXiv request failed"}376 root = ET.fromstring(raw)377 ns = {"a": "http://www.w3.org/2005/Atom"}378 e = root.find("a:entry", ns)379 if e is None or not e.findtext("a:title", "", ns).strip():380 return {"_error": "no entry"}381 return {"title": clean_title(e.findtext("a:title", "", ns)),382 "authors": [x.findtext("a:name", "", ns) for x in e.findall("a:author", ns)],383 "year": e.findtext("a:published", "", ns)[:4], "id": aid}384385386def openalex(wid: str) -> dict:387 raw = get(f"https://api.openalex.org/works/{wid}?mailto={MAILTO}")388 if raw is None or raw.startswith(b"__ERR__"):389 return {"_error": "OpenAlex request failed"}390 w = json.loads(raw)391 src = (w.get("primary_location") or {}).get("source") or {}392 return {"title": clean_title(w.get("display_name") or ""), "authors": [a["author"]["display_name"] for a in w.get("authorships", [])],393 "year": w.get("publication_year"), "venue": src.get("display_name"), "biblio": w.get("biblio") or {},394 "doi": (w.get("doi") or "").replace("https://doi.org/", ""), "id": wid}395396397# --------------------------------------------------------------------------------------------------------------398def bib_from_crossref(key: str, m: dict) -> str:399 authors = AUTHOR_FIX.get(key) or " and ".join(400 f"{a.get('family', '')}, {a.get('given', '')}".strip(", ") for a in m.get("author", []) if a.get("family"))401 editors = EDITOR_FIX.get(key) or " and ".join(402 f"{a.get('family', '')}, {a.get('given', '')}".strip(", ") for a in m.get("editor", []) if a.get("family"))403 title = tex(clean_title(m["title"][0]))404 year = YEAR_FIX.get(key) or (m.get("published-print", {}).get("date-parts") or [[None]])[0][0] \405 or (m.get("issued", {}).get("date-parts") or [[None]])[0][0]406 container = tex(clean_title((m.get("container-title") or [""])[0]))407 ctype = m.get("type")408 typ = {"journal-article": "article", "book-chapter": "incollection", "monograph": "book", "book": "book",409 "edited-book": "book", "report": "techreport", "posted-content": "misc"}.get(ctype, "misc")410 fields = []411 if authors:412 fields.append(f" author = {{{authors}}}")413 if editors and not authors:414 fields.append(f" editor = {{{editors}}}")415 fields += [f" title = {{{title}}}", f" year = {{{year}}}"]416 if typ == "article" and container:417 fields.append(f" journal = {{{container}}}")418 elif typ == "incollection" and container:419 fields.append(f" booktitle = {{{container}}}")420 if m.get("publisher"):421 fields.append(f" publisher = {{{tex(m['publisher'])}}}")422 elif typ == "book":423 if m.get("publisher"):424 fields.append(f" publisher = {{{tex(m['publisher'])}}}")425 elif typ == "techreport":426 fields.append(f" institution = {{{tex(m.get('publisher', ''))}}}")427 if m["DOI"].lower().startswith("10.3386/"):428 fields.append(f" type = {{NBER Working Paper}}")429 fields.append(f" number = {{{m['DOI'].split('/')[-1][1:]}}}")430 else:431 if m["DOI"].lower().startswith("10.2139/ssrn"):432 fields.append(" howpublished = {SSRN working paper}")433 elif m["DOI"].lower().startswith("10.32614/cran"):434 fields.append(" howpublished = {CRAN: Contributed Packages (R package)}")435 elif container:436 fields.append(f" howpublished = {{{container}}}")437 if typ in ("article", "incollection"):438 if m.get("volume"):439 fields.append(f" volume = {{{m['volume']}}}")440 if m.get("issue"):441 fields.append(f" number = {{{m['issue']}}}")442 if m.get("page"):443 fields.append(f" pages = {{{tex(str(m['page'])).replace('-', '--')}}}")444 for name, value in FIELD_FIX.get(key, {}).items():445 fields = [f for f in fields if not f.strip().startswith(f"{name} = ")] + [f" {name} = {{{value}}}"]446 fields.append(f" doi = {{{m['DOI']}}}")447 fields.append(f" url = {{https://doi.org/{m['DOI']}}}")448 return f"@{typ}{{{key},\n" + ",\n".join(fields) + "\n}"449450451def bib_from_arxiv(key: str, m: dict) -> str:452 return (f"@misc{{{key},\n author = {{{' and '.join(m['authors'])}}},\n title = {{{tex(m['title'])}}},\n year = {{{m['year']}}},\n"453 f" howpublished = {{arXiv preprint arXiv:{m['id']}}},\n eprint = {{{m['id']}}},\n archiveprefix = {{arXiv}},\n"454 f" url = {{https://arxiv.org/abs/{m['id']}}}\n}}")455456457def bib_from_openalex(key: str, m: dict) -> str:458 venue, url = OPENALEX_NOTE.get(key, (m.get("venue"), None))459 fields = [f" author = {{{' and '.join(m['authors'])}}}", f" title = {{{tex(m['title'].title() if m['title'].isupper() else m['title'])}}}",460 f" year = {{{m['year']}}}"]461 typ = "article" if m.get("venue") else "misc"462 if typ == "article":463 fields.append(f" journal = {{{tex(venue)}}}")464 b = m["biblio"]465 if b.get("volume"):466 fields.append(f" volume = {{{b['volume']}}}")467 if b.get("issue"):468 fields.append(f" number = {{{b['issue']}}}")469 if b.get("first_page") and b.get("last_page"):470 fields.append(f" pages = {{{b['first_page']}--{b['last_page']}}}")471 elif venue:472 fields.append(f" howpublished = {{{tex(venue)}}}")473 if m.get("doi"):474 fields.append(f" doi = {{{m['doi']}}}")475 fields.append(f" url = {{{url or ('https://doi.org/' + m['doi'] if m.get('doi') else 'https://openalex.org/' + m['id'])}}}")476 fields.append(f" note = {{Bibliographic record from OpenAlex {m['id']}}}")477 return f"@{typ}{{{key},\n" + ",\n".join(fields) + "\n}"478479480# --------------------------------------------------------------------------------------------------------------481def resolve(key: str, ident: str, frag: str) -> tuple[str | None, dict]:482 """Try each alternative identifier; return (bib entry or None, log record)."""483 attempts = []484 for alt in [a.strip() for a in ident.split("||")]:485 if alt.startswith("arXiv:"):486 m = arxiv(alt[6:]); src = "arXiv"487 elif alt.startswith("openalex:"):488 m = openalex(alt[9:]); src = "OpenAlex"489 else:490 m = crossref(alt); src = "Crossref"491 time.sleep(SLEEP)492 if "_error" in m:493 attempts.append({"identifier": alt, "source": src, "error": m["_error"]}); continue494 title = m["title"] if src != "Crossref" else (clean_title(m["title"][0]) if m.get("title") else "")495 ok = bool(title) and frag.lower() in title.lower()496 attempts.append({"identifier": alt, "source": src, "fetched_title": title, "title_match": ok})497 if ok:498 bib = {"arXiv": bib_from_arxiv, "OpenAlex": bib_from_openalex, "Crossref": bib_from_crossref}[src](key, m)499 return bib, {"status": f"verified {src}", "identifier": alt, "source": src, "fetched_title": title,500 "expected_fragment": frag, "date": TODAY, "attempts": attempts}501 return None, {"status": "UNVERIFIED", "identifier": ident, "expected_fragment": frag, "date": TODAY, "attempts": attempts}502503504def main() -> None:505 entries, unverified, log = [], [], {}506 keys = [k for k, _, _ in CANDIDATES]507 assert len(keys) == len(set(keys)), "duplicate bibkeys"508 for key, ident, frag in CANDIDATES:509 if ident is None:510 if key in MANUAL:511 man = MANUAL[key]512 entries.append(man["bib"])513 log[key] = {"status": "manual (URL fetched)", "identifier": man["url"], "source": "manual", "date": man["checked"],514 "fetched_title": None, "evidence": man["evidence"]}515 else:516 unverified.append(key)517 log[key] = {"status": "UNVERIFIED", "identifier": None, "source": None, "date": TODAY,518 "fetched_title": None, "evidence": "no registry record found (Crossref bibliographic search, OpenAlex, EconPapers)"}519 continue520 bib, rec = resolve(key, ident, frag)521 log[key] = rec522 if bib:523 entries.append(bib)524 else:525 unverified.append(key)526 print(f"{rec['status']:22s} {key}", file=sys.stderr)527 (ROOT / "paper").mkdir(exist_ok=True)528 (ROOT / "results" / "metrics").mkdir(parents=True, exist_ok=True)529 header = ("% Generated by scripts/build_references.py from Crossref / arXiv / OpenAlex records whose titles were verified\n"530 f"% against the expected fragment (run {TODAY}; literature cutoff 2026-11-09). Manual entries carry a URL that was\n"531 "% fetched on the recorded date. Do not edit by hand -- edit CANDIDATES/MANUAL in the script and re-run.\n\n")532 (ROOT / "paper" / "references.bib").write_text(header + "\n\n".join(entries) + "\n", encoding="utf-8")533 n_manual = sum(1 for v in log.values() if v["status"].startswith("manual"))534 summary = {"generated": TODAY, "literature_cutoff": "2026-11-09", "n_candidates": len(CANDIDATES), "n_written": len(entries),535 "n_verified_registry": len(entries) - n_manual, "n_manual_url": n_manual, "n_unverified": len(unverified),536 "unverified": unverified, "records": log}537 (ROOT / "results" / "metrics" / "references_verification.json").write_text(json.dumps(summary, indent=1, ensure_ascii=False), encoding="utf-8")538 (ROOT / "results" / "metrics" / "references_unverified.json").write_text(json.dumps(539 {"generated": TODAY, "unverified": [{"bibkey": k, **{kk: vv for kk, vv in log[k].items() if kk != "status"}} for k in unverified]},540 indent=1, ensure_ascii=False), encoding="utf-8")541 print(f"written {len(entries)} entries ({len(entries) - n_manual} registry-verified + {n_manual} manual/URL); unverified: {unverified}")542543544if __name__ == "__main__":545 main()546