rfcipCalibrate provides tools to calibrate yields and simulate revenue outcomes from farm-level Federal Crop Insurance Program (FCIP) experience data. It implements methods from the recent literature (see Citation below) to:
Disclaimer: This product uses data provided by USDA/RMA but is neither endorsed by nor affiliated with USDA or the U.S. Government.
R ≥ 4.1
Upstream FCIP related package dependency:
rfcip Accessing data from the FCIPrfcipCalcPass Calculators and tables used in FCIP Policy Acceptance and Storage System (PASS)rfcipDemand Tools to estimate FCIP demandUSFarmSafetyNetLab Centralized research outputs, analytical tools, and resources dedicated to U.S agricultural safety net programsInternet or local access to the requisite ADM/SOB sources (as configured in rfcipCalcPass controls)
Install the development version from GitHub:
if (!requireNamespace("remotes", quietly = TRUE)) {
install.packages("remotes")
}
remotes::install_github("ftsiboe/rfcipCalibrate")The data collections produced by this package are documented in a sequence of methodological articles, now published as a standalone book, A Field Guide to Federal Crop Insurance Research, at its own site:
https://ftsiboe.github.io/book-fcip-field-guide/
The book walks through the full pipeline: preparing transactions, calibrating sub-county yields, drawing correlated revenue scenarios, reconstructing choice sets, and building synthetic producer panels. Each chapter states the collection name and host repository under its Data availability section; assets are retrievable with piggyback.
Representative producers.
Defined by FCIP Summary of Business by Type, Practice, Unit (SOBTPU) entries for continuously rated plans (YP, APH, RP, RP-HPE). Each SOBTPU aggregates loss experience for producer groups sharing:
This ensures producers within a SOBTPU faced identical policy menus and rating parameters.
Representative insurance agents – coming soon.
Representative AIPs – coming soon.
Representative Government – coming soon.
The workflow for this functionality is drawn from Tsiboe et al. (2025).
For a target year, we pull SOB transactions (coverage type “A”, plans 1/2/3/90) and join matching ADM parameters; missing harvest prices for yield plans are backfilled with the projected price. Revenue policies (plans 2, 3) are converted to yield-equivalent values via adjust_revenue_to_yield_equivalence(), rescaling liability by projected/harvest price, using the higher price in plan-2 guarantees, and recomputing indemnities with a zero floor. From these yield-basis amounts we compute per-acre indemnified yield, an adjusted base premium rate, and the approved yield implied by coverage.
We then invert the rating step with prepare_yield_calibration_data(): DEoptim searches for the rate yield that makes rfcipCalcPass::calc_base_premium_rate() match the observed base rate (rate_yield_optimizer() provides the objective), and we form α and δ from ADM rate components. In the calibration pass, calibrate_yield() aligns the prepared current-year table with the following year’s table and, for each match, selects production-history lengths , (with ) and a nonnegative yield offset to minimize the next year’s base-rate error. This implies an initial calibrated yield: coverage×approved minus indemnified yield if there was a loss, or coverage×approved plus the optimized offset otherwise.
Finally, we benchmark the no-indemnity subset to official historical yields at three scopes (insurance pool, state×commodity×type×practice, and commodity×type×practice), scaling to match group means while enforcing a floor at coverage×approved. We coalesce these adjusted candidates (pool → state → commodity), fall back to the initial value if needed, and aggregate to producer-level contracts with weights and budgets.
# Set up package controls used by all steps below
quick_start_control <- rfcipPackage_controls()
# Download relevant SOB data
sobtpu0 <- get_sob_data_extended(
year = year,
state = "IA",
crop = c(41,21,81,18,11,51),
control = quick_start_control
)
saveRDS(sobtpu0, file.path(dir_project, paste0(calibration_name,"_sobtpu_current.rds")))
sobtpu1 <- get_sob_data_extended(
year = year + 1,
state = "IA",
crop = c(41,21,81,18,11,51),
control = quick_start_control
)
saveRDS(sobtpu1, file.path(dir_project, paste0(calibration_name,"_sobtpu_subsequent.rds")))
# Prepare data for yield calibration
sobtpu0_preped <- prepare_yield_calibration_data(sobtpu = sobtpu0, control = quick_start_control)
saveRDS(sobtpu0_preped, file.path(dir_project, paste0(calibration_name,"_sobtpu_preped_current.rds")))
sobtpu1_preped <- prepare_yield_calibration_data(sobtpu = sobtpu1, control = quick_start_control)
saveRDS(sobtpu1_preped, file.path(dir_project, paste0(calibration_name,"_sobtpu_preped_subsequent.rds")))
# Calibrate yields from observed insurance transactions
cal_yield <- calibrate_yield(
sobtpu_current = sobtpu0_preped,
sobtpu_subsequent= sobtpu1_preped,
control = quick_start_control
)
saveRDS(cal_yield, file.path(dir_project, paste0(calibration_name,"_cal_yield.rds")))We generate 500 joint yield–price scenarios per producer using the RMA M-13 framework and ADM parameters so every menu alternative is evaluated under the same stochastic outcomes. We first create a proxy lookup rate: set rate_yield to the average of the contract’s rate_yield and calibrated_yield, run rfcipCalcPass::fcip_calculator() with indemnities off, and retain the resulting revenue_lookup_rate as rma_draw_lookup_rate.
We then join ADM components: beta_id from A00030_InsuranceOffer, price_volatility_factor and harvest_price from A00810_Price, and combo revenue factors from A01030_ComboRevenueFactor (keyed on lookup_rate, rounded to four decimals). M-13 primitives are computed as AdjMean = approved_yield * mean_quantity / 100, AdjStdDev = approved_yield * standard_deviation_quantity / 100, and LnMean = log(harvest_price) − (price_volatility_factor^2 / 2). From A01020_Beta we retrieve 500-draw vectors for yield and price by beta_id, then form yield draws pmax(0, draw * AdjStdDev + AdjMean) and price draws pmin(2 * harvest_price, exp(draw * price_volatility_factor + LnMean)).
To preserve cross-alternative correlation and provide common anchors, we also compute the pool-average yield path (rma_draw_yield_pool) and the state–commodity–type–practice average price path (rma_draw_price_pool) for each draw. The result is one row per producer with list-columns containing sequence numbers, farm-level yield and price draws, pool/group paths, and the mean lookup rate.
revenue_draw <- rma_500_revenue_draw(
farmdata = cal_yield,
farm_identifiers = c("producer_id"),
control = quick_start_control
)
saveRDS(revenue_draw, file.path(dir_project, paste0(calibration_name,"_revenue_draw.rds")))For each producer, we construct the feasible FCIP menu for the study year/location and simulate revenues for every alternative on the same 500 correlated scenarios from Functionality 2.
construct_menu_option_fcip() tags records with commodity_year, creates producer_id if needed, verifies required fields, and pulls the ADM offerings. It assembles:
(i) none – a no-insurance option (zero premium, full subsidy);
(ii) group/area plans (AY 04, AR 05, AR-HPE 06, MP 16, MP-HPE 17) by averaging area rates, merging index/subsidy parameters, and computing menu_premium_per_liability, menu_subsidy_per_premium, menu_subsidy_percent (capped at 1);
(iii) individual plans (YP 01, RP 02, RP-HPE 03, APH 90) by merging farm yields with ADM eligibility/rate tables and calling rfcipCalcPass::fcip_calculator_individual() per election.
simulate_menu_revenue_fcip() joins the menu to simulated draws, flags the observed and no-insurance choices, attaches ADM projected_price, and for each alternative/draw computes expected and final yields (farm vs. area), guaranteed yield, liability, premium/subsidy, plan-specific harvest liability rules, revenue count, indemnity, and net revenue. It then summarizes moments/risk metrics (calculate_revenue_moments()), orders options within producers (observed → other insured → none), and returns list-columns of indices, attributes, premiums/subsidies, liabilities, and distribution summaries.
Supported plans:
# Merge yield calibration with revenue simulations and rename revealed elections
revenue_draw <- readRDS(file.path(dir_project, paste0(calibration_name,"_revenue_draw.rds")))
cal_yield <- readRDS(file.path(dir_project, paste0(calibration_name,"_cal_yield.rds")))
cal_revenue <- cal_yield[revenue_draw, on = intersect(names(revenue_draw), names(cal_yield)), nomatch = 0]
setnames(cal_revenue, old = FCIP_INSURANCE_ELECTION, new = paste0("revealed_", FCIP_INSURANCE_ELECTION))
saveRDS(cal_revenue, file.path(dir_project, paste0(calibration_name,"_cal_revenue.rds")))
# Construct insurance menu options
menu_option <- construct_menu_option_fcip(
farmdata = cal_revenue,
farm_identifiers = c("producer_id"),
year = year,
control = quick_start_control
)
saveRDS(menu_option, file.path(dir_project, paste0(calibration_name,"_menu_option.rds")))
# Simulate revenues for all available menu options on the same 500 draws
cal_menu <- simulate_menu_revenue_fcip(
farmdata = cal_revenue,
menu_option = menu_option,
farm_identifiers = c("producer_id"),
year = year,
control = quick_start_control
)
saveRDS(cal_menu, file.path(dir_project, paste0(calibration_name,"_cal_menu.rds")))If you use rfcipCalibrate in your research, please cite:
Contributions, issues, and feature requests are welcome. Please see the Code of Conduct.
Questions or collaboration ideas?
Email Francis Tsiboe at ftsiboe@hotmail.com.
If you find this useful, please ⭐ the repo!
🤝 Contributing & license Contributions are welcome — see CONTRIBUTING.md. All contributions require agreement to the project’s Contributor License Agreement: you keep ownership of your work, and the project keeps the flexibility to offer the package under additional license terms in the future. The package is released under GPL-3. Copyright © 2025–2026 TERRA ANALYTICS LLC (Kansas, USA).
💼 Commercial use GPL-3 is a copyleft license: if you distribute a product that incorporates this package, that product must be released under GPL-3 as well. If that does not fit your situation, or you need this work built, extended, or maintained to your schedule rather than to a research calendar, TERRA ANALYTICS LLC licenses it separately and takes on contract work. Write to Francis Tsiboe (ftsiboe@hotmail.com).