Last active
March 16, 2026 18:48
-
-
Save cavedave/614ddd0e92875ec6f4209bfbe0b85995 to your computer and use it in GitHub Desktop.
Simon–Ehrlich wager what years would it have been won and lost https://en.wikipedia.org/wiki/Simon%E2%80%93Ehrlich_wager data from https://www.usgs.gov/centers/national-minerals-information-center/historical-statistics-mineral-commodities-united
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "start_year","end_year","start_value","end_value","change_value","pct_change","winner","winner_label","period","is_original_window" | |
| 1900,1910,1000,1057.58394685222,57.5839468522165,5.75839468522165,"Ehrlich","Ehrlich (prices rose)","1900->1910",FALSE | |
| 1901,1911,1000,1386.4192309077,386.4192309077,38.64192309077,"Ehrlich","Ehrlich (prices rose)","1901->1911",FALSE | |
| 1902,1912,1000,1341.73020560188,341.730205601884,34.1730205601884,"Ehrlich","Ehrlich (prices rose)","1902->1912",FALSE | |
| 1903,1913,1000,1487.37147860107,487.371478601067,48.7371478601067,"Ehrlich","Ehrlich (prices rose)","1903->1913",FALSE | |
| 1904,1914,1000,1135.6068795084,135.606879508398,13.5606879508398,"Ehrlich","Ehrlich (prices rose)","1904->1914",FALSE | |
| 1905,1915,1000,1881.17122655875,881.171226558753,88.1171226558753,"Ehrlich","Ehrlich (prices rose)","1905->1915",FALSE | |
| 1906,1916,1000,2024.47833008782,1024.47833008782,102.447833008782,"Ehrlich","Ehrlich (prices rose)","1906->1916",FALSE | |
| 1907,1917,1000,1527.06554576622,527.06554576622,52.706554576622,"Ehrlich","Ehrlich (prices rose)","1907->1917",FALSE | |
| 1908,1918,1000,2562.82016421843,1562.82016421843,156.282016421843,"Ehrlich","Ehrlich (prices rose)","1908->1918",FALSE | |
| 1909,1919,1000,1855.04046170554,855.040461705544,85.5040461705544,"Ehrlich","Ehrlich (prices rose)","1909->1919",FALSE | |
| 1910,1920,1000,1204.40681030636,204.406810306361,20.4406810306361,"Ehrlich","Ehrlich (prices rose)","1910->1920",FALSE | |
| 1911,1921,1000,984.699874353722,-15.3001256462783,-1.53001256462783,"Simon","Simon (prices fell)","1911->1921",FALSE | |
| 1912,1922,1000,967.239830852856,-32.7601691471441,-3.27601691471441,"Simon","Simon (prices fell)","1912->1922",FALSE | |
| 1913,1923,1000,1016.09345326416,16.0934532641556,1.60934532641556,"Ehrlich","Ehrlich (prices rose)","1913->1923",FALSE | |
| 1914,1924,1000,1078.40513786636,78.405137866356,7.8405137866356,"Ehrlich","Ehrlich (prices rose)","1914->1924",FALSE | |
| 1915,1925,1000,855.155453336315,-144.844546663685,-14.4844546663685,"Simon","Simon (prices fell)","1915->1925",FALSE | |
| 1916,1926,1000,749.439321911723,-250.560678088277,-25.0560678088277,"Simon","Simon (prices fell)","1916->1926",FALSE | |
| 1917,1927,1000,662.248946819576,-337.751053180424,-33.7751053180424,"Simon","Simon (prices fell)","1917->1927",FALSE | |
| 1918,1928,1000,546.173030898749,-453.826969101251,-45.3826969101251,"Simon","Simon (prices fell)","1918->1928",FALSE | |
| 1919,1929,1000,740.154149164675,-259.845850835325,-25.9845850835325,"Simon","Simon (prices fell)","1919->1929",FALSE | |
| 1920,1930,1000,922.798742572699,-77.2012574273009,-7.72012574273009,"Simon","Simon (prices fell)","1920->1930",FALSE | |
| 1921,1931,1000,1086.23982211043,86.2398221104277,8.62398221104277,"Ehrlich","Ehrlich (prices rose)","1921->1931",FALSE | |
| 1922,1932,1000,1009.39192039827,9.39192039827151,0.939192039827151,"Ehrlich","Ehrlich (prices rose)","1922->1932",FALSE | |
| 1923,1933,1000,953.210520691252,-46.7894793087482,-4.67894793087482,"Simon","Simon (prices fell)","1923->1933",FALSE | |
| 1924,1934,1000,1184.2014242306,184.201424230597,18.4201424230597,"Ehrlich","Ehrlich (prices rose)","1924->1934",FALSE | |
| 1925,1935,1000,1109.184927176,109.184927175999,10.9184927175999,"Ehrlich","Ehrlich (prices rose)","1925->1935",FALSE | |
| 1926,1936,1000,1101.72208861532,101.72208861532,10.172208861532,"Ehrlich","Ehrlich (prices rose)","1926->1936",FALSE | |
| 1927,1937,1000,1294.26408450704,294.264084507042,29.4264084507042,"Ehrlich","Ehrlich (prices rose)","1927->1937",FALSE | |
| 1928,1938,1000,1171.35226638515,171.352266385149,17.1352266385149,"Ehrlich","Ehrlich (prices rose)","1928->1938",FALSE | |
| 1929,1939,1000,1108.67986822823,108.679868228226,10.8679868228226,"Ehrlich","Ehrlich (prices rose)","1929->1939",FALSE | |
| 1930,1940,1000,1277.43342913037,277.433429130368,27.7433429130368,"Ehrlich","Ehrlich (prices rose)","1930->1940",FALSE | |
| 1931,1941,1000,1516.8170728273,516.817072827303,51.6817072827303,"Ehrlich","Ehrlich (prices rose)","1931->1941",FALSE | |
| 1932,1942,1000,1805.69004588732,805.690045887325,80.5690045887325,"Ehrlich","Ehrlich (prices rose)","1932->1942",FALSE | |
| 1933,1943,1000,1630.52586282948,630.525862829477,63.0525862829477,"Ehrlich","Ehrlich (prices rose)","1933->1943",FALSE | |
| 1934,1944,1000,1339.30080135073,339.300801350731,33.9300801350731,"Ehrlich","Ehrlich (prices rose)","1934->1944",FALSE | |
| 1935,1945,1000,1317.60552777004,317.605527770042,31.7605527770042,"Ehrlich","Ehrlich (prices rose)","1935->1945",FALSE | |
| 1936,1946,1000,1228.94038890698,228.940388906977,22.8940388906977,"Ehrlich","Ehrlich (prices rose)","1936->1946",FALSE | |
| 1937,1947,1000,1342.89759287029,342.897592870292,34.2897592870292,"Ehrlich","Ehrlich (prices rose)","1937->1947",FALSE | |
| 1938,1948,1000,1768.87912781278,768.879127812782,76.8879127812782,"Ehrlich","Ehrlich (prices rose)","1938->1948",FALSE | |
| 1939,1949,1000,1650.40521023445,650.405210234452,65.0405210234452,"Ehrlich","Ehrlich (prices rose)","1939->1949",FALSE | |
| 1940,1950,1000,1641.68288009528,641.68288009528,64.168288009528,"Ehrlich","Ehrlich (prices rose)","1940->1950",FALSE | |
| 1941,1951,1000,2113.89664513541,1113.89664513541,111.389664513541,"Ehrlich","Ehrlich (prices rose)","1941->1951",FALSE | |
| 1942,1952,1000,2089.88412386752,1089.88412386752,108.988412386752,"Ehrlich","Ehrlich (prices rose)","1942->1952",FALSE | |
| 1943,1953,1000,2060.89928257255,1060.89928257255,106.089928257255,"Ehrlich","Ehrlich (prices rose)","1943->1953",FALSE | |
| 1944,1954,1000,2011.25342163466,1011.25342163466,101.125342163466,"Ehrlich","Ehrlich (prices rose)","1944->1954",FALSE | |
| 1945,1955,1000,2181.06825981401,1181.06825981401,118.106825981401,"Ehrlich","Ehrlich (prices rose)","1945->1955",FALSE | |
| 1946,1956,1000,2283.40351530114,1283.40351530114,128.340351530114,"Ehrlich","Ehrlich (prices rose)","1946->1956",FALSE | |
| 1947,1957,1000,1513.41645499061,513.416454990606,51.3416454990606,"Ehrlich","Ehrlich (prices rose)","1947->1957",FALSE | |
| 1948,1958,1000,1266.5679969718,266.567996971796,26.6567996971796,"Ehrlich","Ehrlich (prices rose)","1948->1958",FALSE | |
| 1949,1959,1000,1403.88985165254,403.889851652541,40.3889851652541,"Ehrlich","Ehrlich (prices rose)","1949->1959",FALSE | |
| 1950,1960,1000,1231.23329160657,231.233291606568,23.1233291606568,"Ehrlich","Ehrlich (prices rose)","1950->1960",FALSE | |
| 1951,1961,1000,960.019130541891,-39.9808694581092,-3.99808694581092,"Simon","Simon (prices fell)","1951->1961",FALSE | |
| 1952,1962,1000,1061.07341132297,61.0734113229714,6.10734113229714,"Ehrlich","Ehrlich (prices rose)","1952->1962",FALSE | |
| 1953,1963,1000,999.478981465322,-0.521018534677864,-0.0521018534677864,"Simon","Simon (prices fell)","1953->1963",FALSE | |
| 1954,1964,1000,1174.91070245675,174.910702456752,17.4910702456752,"Ehrlich","Ehrlich (prices rose)","1954->1964",FALSE | |
| 1955,1965,1000,1193.86688717686,193.866887176855,19.3866887176855,"Ehrlich","Ehrlich (prices rose)","1955->1965",FALSE | |
| 1956,1966,1000,1105.17559908242,105.175599082422,10.5175599082422,"Ehrlich","Ehrlich (prices rose)","1956->1966",FALSE | |
| 1957,1967,1000,1283.62269202916,283.622692029163,28.3622692029163,"Ehrlich","Ehrlich (prices rose)","1957->1967",FALSE | |
| 1958,1968,1000,1533.14001384245,533.140013842449,53.3140013842449,"Ehrlich","Ehrlich (prices rose)","1958->1968",FALSE | |
| 1959,1969,1000,1484.78542244393,484.78542244393,48.478542244393,"Ehrlich","Ehrlich (prices rose)","1959->1969",FALSE | |
| 1960,1970,1000,1710.74506707069,710.745067070688,71.0745067070688,"Ehrlich","Ehrlich (prices rose)","1960->1970",FALSE | |
| 1961,1971,1000,1956.40914786421,956.40914786421,95.640914786421,"Ehrlich","Ehrlich (prices rose)","1961->1971",FALSE | |
| 1962,1972,1000,1660.69539132171,660.695391321709,66.0695391321709,"Ehrlich","Ehrlich (prices rose)","1962->1972",FALSE | |
| 1963,1973,1000,1931.51435575644,931.514355756445,93.1514355756444,"Ehrlich","Ehrlich (prices rose)","1963->1973",FALSE | |
| 1964,1974,1000,2682.95929248828,1682.95929248828,168.295929248828,"Ehrlich","Ehrlich (prices rose)","1964->1974",FALSE | |
| 1965,1975,1000,2785.71327279464,1785.71327279464,178.571327279464,"Ehrlich","Ehrlich (prices rose)","1965->1975",FALSE | |
| 1966,1976,1000,2854.09288851494,1854.09288851494,185.409288851494,"Ehrlich","Ehrlich (prices rose)","1966->1976",FALSE | |
| 1967,1977,1000,3303.60007780077,2303.60007780077,230.360007780077,"Ehrlich","Ehrlich (prices rose)","1967->1977",FALSE | |
| 1968,1978,1000,2998.13797265985,1998.13797265985,199.813797265985,"Ehrlich","Ehrlich (prices rose)","1968->1978",FALSE | |
| 1969,1979,1000,3342.24893731701,2342.24893731701,234.224893731701,"Ehrlich","Ehrlich (prices rose)","1969->1979",FALSE | |
| 1970,1980,1000,3414.03159649386,2414.03159649386,241.403159649386,"Ehrlich","Ehrlich (prices rose)","1970->1980",FALSE | |
| 1971,1981,1000,2902.10436375578,1902.10436375578,190.210436375578,"Ehrlich","Ehrlich (prices rose)","1971->1981",FALSE | |
| 1972,1982,1000,2515.00753666966,1515.00753666966,151.500753666966,"Ehrlich","Ehrlich (prices rose)","1972->1982",FALSE | |
| 1973,1983,1000,2071.28306756229,1071.28306756229,107.128306756229,"Ehrlich","Ehrlich (prices rose)","1973->1983",FALSE | |
| 1974,1984,1000,1405.40134997678,405.401349976784,40.5401349976784,"Ehrlich","Ehrlich (prices rose)","1974->1984",FALSE | |
| 1975,1985,1000,1197.26109121811,197.26109121811,19.726109121811,"Ehrlich","Ehrlich (prices rose)","1975->1985",FALSE | |
| 1976,1986,1000,920.590608712613,-79.409391287387,-7.9409391287387,"Simon","Simon (prices fell)","1976->1986",FALSE | |
| 1977,1987,1000,924.788040826312,-75.211959173688,-7.5211959173688,"Simon","Simon (prices fell)","1977->1987",FALSE | |
| 1978,1988,1000,1659.6245523647,659.624552364702,65.9624552364702,"Ehrlich","Ehrlich (prices rose)","1978->1988",FALSE | |
| 1979,1989,1000,1418.43207307803,418.432073078027,41.8432073078027,"Ehrlich","Ehrlich (prices rose)","1979->1989",FALSE | |
| 1980,1990,1000,989.901998698761,-10.098001301239,-1.0098001301239,"Simon","Simon (prices fell)","1980->1990",TRUE | |
| 1981,1991,1000,997.66843026054,-2.33156973945961,-0.233156973945961,"Simon","Simon (prices fell)","1981->1991",FALSE | |
| 1982,1992,1000,1100.80458068328,100.804580683284,10.0804580683284,"Ehrlich","Ehrlich (prices rose)","1982->1992",FALSE | |
| 1983,1993,1000,916.169552846269,-83.830447153731,-8.3830447153731,"Simon","Simon (prices fell)","1983->1993",FALSE | |
| 1984,1994,1000,1074.8100595323,74.8100595322958,7.48100595322958,"Ehrlich","Ehrlich (prices rose)","1984->1994",FALSE | |
| 1985,1995,1000,1466.08088452755,466.080884527546,46.6080884527547,"Ehrlich","Ehrlich (prices rose)","1985->1995",FALSE | |
| 1986,1996,1000,1499.41972143532,499.419721435319,49.9419721435319,"Ehrlich","Ehrlich (prices rose)","1986->1996",FALSE | |
| 1987,1997,1000,1342.2185119994,342.218511999399,34.2218511999398,"Ehrlich","Ehrlich (prices rose)","1987->1997",FALSE | |
| 1988,1998,1000,760.820350845835,-239.179649154165,-23.9179649154165,"Simon","Simon (prices fell)","1988->1998",FALSE | |
| 1989,1999,1000,594.045765317408,-405.954234682592,-40.5954234682592,"Simon","Simon (prices fell)","1989->1999",FALSE | |
| 1990,2000,1000,895.903258169223,-104.096741830777,-10.4096741830777,"Simon","Simon (prices fell)","1990->2000",FALSE | |
| 1991,2001,1000,902.652880251009,-97.3471197489914,-9.73471197489914,"Simon","Simon (prices fell)","1991->2001",FALSE | |
| 1992,2002,1000,855.736379596182,-144.263620403818,-14.4263620403818,"Simon","Simon (prices fell)","1992->2002",FALSE | |
| 1993,2003,1000,1258.86611509747,258.86611509747,25.886611509747,"Ehrlich","Ehrlich (prices rose)","1993->2003",FALSE | |
| 1994,2004,1000,1616.38250757156,616.382507571558,61.6382507571558,"Ehrlich","Ehrlich (prices rose)","1994->2004",FALSE | |
| 1995,2005,1000,1571.66307802479,571.663078024794,57.1663078024794,"Ehrlich","Ehrlich (prices rose)","1995->2005",FALSE | |
| 1996,2006,1000,2512.15982581622,1512.15982581622,151.215982581622,"Ehrlich","Ehrlich (prices rose)","1996->2006",FALSE | |
| 1997,2007,1000,3294.5618208595,2294.5618208595,229.45618208595,"Ehrlich","Ehrlich (prices rose)","1997->2007",FALSE | |
| 1998,2008,1000,3944.08311749253,2944.08311749253,294.408311749253,"Ehrlich","Ehrlich (prices rose)","1998->2008",FALSE | |
| 1999,2009,1000,2881.12395799521,1881.12395799521,188.112395799521,"Ehrlich","Ehrlich (prices rose)","1999->2009",FALSE | |
| 2000,2010,1000,3313.28869194085,2313.28869194085,231.328869194085,"Ehrlich","Ehrlich (prices rose)","2000->2010",FALSE | |
| 2001,2011,1000,4213.12183871317,3213.12183871317,321.312183871318,"Ehrlich","Ehrlich (prices rose)","2001->2011",FALSE | |
| 2002,2012,1000,4253.01820706126,3253.01820706126,325.301820706126,"Ehrlich","Ehrlich (prices rose)","2002->2012",FALSE | |
| 2003,2013,1000,3316.75723912222,2316.75723912222,231.675723912222,"Ehrlich","Ehrlich (prices rose)","2003->2013",FALSE | |
| 2004,2014,1000,2225.21975039935,1225.21975039935,122.521975039935,"Ehrlich","Ehrlich (prices rose)","2004->2014",FALSE | |
| 2005,2015,1000,1321.53377619824,321.533776198239,32.1533776198239,"Ehrlich","Ehrlich (prices rose)","2005->2015",FALSE |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env Rscript | |
| suppressPackageStartupMessages({ | |
| library(readxl) | |
| library(dplyr) | |
| library(tidyr) | |
| library(ggplot2) | |
| }) | |
| dir.create("output", showWarnings = FALSE, recursive = TRUE) | |
| metal_sources <- list( | |
| chromium = c( | |
| "https://www.usgs.gov/media/files/chromium-historical-statistics-data-series-140", | |
| "https://d9-wret.s3.us-west-2.amazonaws.com/assets/palladium/production/mineral-pubs/historical-statistics/ds140-chrom.xlsx" | |
| ), | |
| copper = c( | |
| "https://www.usgs.gov/media/files/copper-historical-statistics-data-series-140", | |
| "https://d9-wret.s3.us-west-2.amazonaws.com/assets/palladium/production/mineral-pubs/historical-statistics/ds140-coppe.xlsx" | |
| ), | |
| nickel = c( | |
| "https://www.usgs.gov/media/files/nickel-historical-statistics-data-series-140", | |
| "https://d9-wret.s3.us-west-2.amazonaws.com/assets/palladium/production/mineral-pubs/historical-statistics/ds140-nicke.xlsx" | |
| ), | |
| tin = c( | |
| "https://www.usgs.gov/media/files/tin-historical-statistics-data-series-140", | |
| "https://d9-wret.s3.us-west-2.amazonaws.com/assets/palladium/production/mineral-pubs/historical-statistics/ds140-tin.xlsx" | |
| ), | |
| tungsten = c( | |
| "https://www.usgs.gov/media/files/tungsten-historical-statistics-data-series-140", | |
| "https://d9-wret.s3.us-west-2.amazonaws.com/assets/palladium/production/mineral-pubs/historical-statistics/ds140-tungs.xlsx" | |
| ) | |
| ) | |
| download_first_available <- function(urls, target_file) { | |
| for (u in urls) { | |
| ok <- tryCatch({ | |
| utils::download.file(u, target_file, mode = "wb", quiet = TRUE) | |
| if (!isTRUE(file.info(target_file)$size > 0)) { | |
| return(FALSE) | |
| } | |
| # Ensure we actually downloaded an Excel workbook, not an HTML page. | |
| invisible(readxl::excel_sheets(target_file)) | |
| TRUE | |
| }, error = function(e) { | |
| FALSE | |
| }) | |
| if (isTRUE(ok)) { | |
| return(u) | |
| } | |
| } | |
| stop("Failed to download any URL in source list.") | |
| } | |
| standardize_commodity <- function(metal_name, urls) { | |
| tmp_xlsx <- tempfile(fileext = ".xlsx") | |
| used_url <- download_first_available(urls, tmp_xlsx) | |
| raw <- readxl::read_excel(tmp_xlsx, skip = 4, .name_repair = "minimal") | |
| names_clean <- trimws(names(raw)) | |
| names(raw) <- names_clean | |
| year_col <- which(tolower(names_clean) == "year")[1] | |
| value_col <- which(grepl("^Unit value \\(\\$/t\\)$", names_clean, ignore.case = TRUE))[1] | |
| if (is.na(value_col)) { | |
| value_col <- which(grepl("^Unit value", names_clean, ignore.case = TRUE))[1] | |
| } | |
| if (is.na(year_col) || is.na(value_col)) { | |
| stop(paste("Could not detect Year and Unit value columns for", metal_name)) | |
| } | |
| year_name <- names_clean[year_col] | |
| value_name <- names_clean[value_col] | |
| out <- raw %>% | |
| transmute( | |
| Year = suppressWarnings(as.integer(.data[[year_name]])), | |
| value = suppressWarnings(as.numeric(gsub(",", "", as.character(.data[[value_name]])))) | |
| ) %>% | |
| filter(!is.na(Year), !is.na(value), Year >= 1900) %>% | |
| distinct(Year, .keep_all = TRUE) %>% | |
| rename(!!metal_name := value) %>% | |
| arrange(Year) | |
| attr(out, "source_url") <- used_url | |
| out | |
| } | |
| message("Loading and standardizing USGS series...") | |
| metal_data <- lapply(names(metal_sources), function(m) standardize_commodity(m, metal_sources[[m]])) | |
| names(metal_data) <- names(metal_sources) | |
| prices_wide <- Reduce(function(x, y) full_join(x, y, by = "Year"), metal_data) %>% | |
| arrange(Year) | |
| required_metals <- names(metal_sources) | |
| prices_complete <- prices_wide %>% | |
| filter(if_all(all_of(required_metals), ~ !is.na(.x))) | |
| if (nrow(prices_complete) == 0) { | |
| stop("No complete years found across all five metal series.") | |
| } | |
| compute_rolling_basket <- function(prices_tbl, metals, horizon = 10, total_budget = 1000) { | |
| years <- sort(unique(prices_tbl$Year)) | |
| start_years <- years[(years + horizon) %in% years] | |
| if (length(start_years) == 0) { | |
| return(tibble()) | |
| } | |
| rows <- vector("list", length(start_years)) | |
| for (i in seq_along(start_years)) { | |
| sy <- start_years[i] | |
| ey <- sy + horizon | |
| start_row <- prices_tbl[prices_tbl$Year == sy, metals, drop = FALSE] | |
| end_row <- prices_tbl[prices_tbl$Year == ey, metals, drop = FALSE] | |
| if (nrow(start_row) != 1 || nrow(end_row) != 1 || any(is.na(start_row)) || any(is.na(end_row))) { | |
| next | |
| } | |
| per_metal_budget <- total_budget / length(metals) | |
| start_prices <- as.numeric(start_row[1, ]) | |
| end_prices <- as.numeric(end_row[1, ]) | |
| qty <- per_metal_budget / start_prices | |
| end_value <- sum(qty * end_prices) | |
| rows[[i]] <- tibble( | |
| start_year = sy, | |
| end_year = ey, | |
| start_value = total_budget, | |
| end_value = end_value, | |
| change_value = end_value - total_budget, | |
| pct_change = (end_value - total_budget) / total_budget * 100, | |
| winner = ifelse(end_value < total_budget, "Simon", "Ehrlich") | |
| ) | |
| } | |
| bind_rows(rows) %>% arrange(start_year) | |
| } | |
| message("Computing fixed-basket rolling outcomes...") | |
| results <- compute_rolling_basket(prices_complete, required_metals, horizon = 10, total_budget = 1000) | |
| if (nrow(results) == 0) { | |
| stop("No rolling results generated; check year overlap and missing values.") | |
| } | |
| results <- results %>% | |
| mutate( | |
| winner_label = ifelse(winner == "Simon", "Simon (prices fell)", "Ehrlich (prices rose)"), | |
| period = paste0(start_year, "->", end_year), | |
| is_original_window = start_year == 1980 & end_year == 1990 | |
| ) | |
| if (!any(results$is_original_window)) { | |
| warning("1980->1990 window not found in complete data after cleaning.") | |
| } | |
| write.csv(results, "output/simon_wager_basket_results.csv", row.names = FALSE) | |
| palette <- c( | |
| "Simon (prices fell)" = "#009E73", | |
| "Ehrlich (prices rose)" = "#D55E00" | |
| ) | |
| start_break <- floor(min(results$start_year) / 25) * 25 | |
| end_break <- ceiling(max(results$start_year) / 25) * 25 | |
| x_breaks <- sort(unique(c(seq(start_break, end_break, by = 25), 1980, 1990))) | |
| y_max <- max(results$pct_change, na.rm = TRUE) | |
| p <- ggplot(results, aes(x = start_year, y = pct_change, color = winner_label)) + | |
| annotate( | |
| "rect", | |
| xmin = 1980, | |
| xmax = 1990, | |
| ymin = -Inf, | |
| ymax = Inf, | |
| fill = "#B3CDE3", | |
| alpha = 0.22 | |
| ) + | |
| geom_hline(yintercept = 0, linewidth = 0.6, linetype = "dashed", color = "#666666") + | |
| geom_vline(xintercept = 1968, linewidth = 0.5, linetype = "dotted", color = "#666666") + | |
| geom_line(color = "#4C78A8", linewidth = 0.5, alpha = 0.7) + | |
| geom_point(size = 2, alpha = 0.95) + | |
| scale_x_continuous(breaks = x_breaks) + | |
| scale_color_manual(values = palette, name = "10-year winner") + | |
| labs( | |
| title = "Simon-Ehrlich style wager, rolling 10-year starts", | |
| subtitle = "Fixed-quantity basket of chromium, copper, nickel, tin, tungsten (equal-dollar allocation at each start year)", | |
| x = "Start year", | |
| y = "Basket change after 10 years (%)", | |
| caption = "Sources: USGS Data Series 140 commodity unit values" | |
| ) + | |
| theme_minimal(base_size = 11) + | |
| theme( | |
| legend.position = "top", | |
| plot.title = element_text(face = "bold") | |
| ) + | |
| annotate( | |
| "label", | |
| x = 1985, | |
| y = y_max, | |
| label = "Actual Wager\n(1980-1990)", | |
| size = 3.1, | |
| fill = "white", | |
| vjust = 1.2 | |
| ) + | |
| annotate( | |
| "label", | |
| x = 1968, | |
| y = y_max, | |
| label = "The Population Bomb (1968)", | |
| size = 2.8, | |
| fill = "white", | |
| vjust = -0.2, | |
| hjust = 0 | |
| ) | |
| ggsave( | |
| filename = "output/simon_wager_rolling_10y.png", | |
| plot = p, | |
| width = 11, | |
| height = 6.5, | |
| dpi = 180 | |
| ) | |
| summary_line <- results %>% | |
| summarise( | |
| n_windows = n(), | |
| simon_win_rate = mean(winner == "Simon") * 100 | |
| ) | |
| message(sprintf("Saved output/simon_wager_basket_results.csv with %d windows.", summary_line$n_windows)) | |
| message(sprintf("Simon wins %.1f%% of rolling windows.", summary_line$simon_win_rate)) | |
| message("Saved output/simon_wager_rolling_10y.png.") |
Author
cavedave
commented
Mar 16, 2026
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment