{"id":32206016,"url":"https://github.com/tylerjpike/oos","last_synced_at":"2026-02-23T14:03:38.017Z","repository":{"id":54766604,"uuid":"326015858","full_name":"tylerJPike/OOS","owner":"tylerJPike","description":"Out-Of-Sample Time Series Forecasting: OOS introduces a comprehensive framework for time series forecasting with traditional econometric and modern machine learning techniques.","archived":false,"fork":false,"pushed_at":"2021-03-30T21:01:03.000Z","size":4070,"stargazers_count":10,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-08T13:05:31.481Z","etag":null,"topics":["econometrics","forecast-combination","forecasting","machine-learning"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tylerJPike.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-01-01T16:37:24.000Z","updated_at":"2025-04-09T11:20:01.000Z","dependencies_parsed_at":"2022-08-14T02:10:41.903Z","dependency_job_id":null,"html_url":"https://github.com/tylerJPike/OOS","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/tylerJPike/OOS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerJPike%2FOOS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerJPike%2FOOS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerJPike%2FOOS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerJPike%2FOOS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tylerJPike","download_url":"https://codeload.github.com/tylerJPike/OOS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tylerJPike%2FOOS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29745111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T07:44:07.782Z","status":"ssl_error","status_checked_at":"2026-02-23T07:44:07.432Z","response_time":90,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["econometrics","forecast-combination","forecasting","machine-learning"],"created_at":"2025-10-22T05:02:09.730Z","updated_at":"2026-02-23T14:03:38.007Z","avatar_url":"https://github.com/tylerJPike.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Out-of-sample time series forecasting\n\n\u003c!-- badges: start --\u003e\n[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](http://www.gnu.org/licenses/gpl-3.0)\n[![CRAN status](https://www.r-pkg.org/badges/version/OOS)](https://CRAN.R-project.org/package=OOS)\n[![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html)\n[![codecov](https://codecov.io/gh/tylerJPike/OOS/branch/main/graph/badge.svg?token=AQ4PFWU3KS)](https://codecov.io/gh/tylerJPike/OOS)\n[![Build Status](https://travis-ci.org/tylerJPike/OOS.svg?branch=main)](https://travis-ci.org/tylerJPike/OOS)\n\u003c!-- badges: end --\u003e\n\nOut-of-Sample time series forecasting is a common, important, and subtle task. The OOS package introduces a comprehensive and cohesive API for the out-of-sample forecasting workflow: data preparation, forecasting - including both traditional econometric time series models and modern machine learning techniques - forecast combination, model and error analysis, and forecast visualization. \n\nThe key difference between OOS and the other time series forecasting packages is that it operates out-of-sample by construction. That is, it re-cleans data and re-trains models each forecast.date and is careful not to introduce look-ahead bias into its information set via data cleaning or forecasts via model training. Other packages tend to fit the model once, leaving the user to construct the out-of-sample data cleaning and forecast exercise on their own.\n\nSee the OOS package [website](https://tylerjpike.github.io/OOS/) for examples and documentation.\n\n---\n## Workflow and available Tools\n\n### 1. Prepare Data\n\n| Clean Outliers | Impute Missing Observations (via [imputeTS](https://github.com/SteffenMoritz/imputeTS)) | Dimension Reduction | \n|----------------------|------------------------|-----------------------|\n| Winsorize | Linear Interpolation | Principal Components |\n| Trim | Kalman Filter | |\n|  | Fill-Forward | |\n|  | Average | |\n|  | Moving Average | |\n|  | Seasonal Decomposition | |\n\n\n### 2. Forecast\n\n| Univariate Forecasts (via [forecast](https://github.com/robjhyndman/forecast)) | Multivariate Forecasts (via [caret](https://github.com/topepo/caret)) | Forecast Combinations |\n|----------------------|------------------------|-----------------------|\n| Random Walk | Vector Autoregression | Mean|\n| ARIMA | Linear Regression | Median |\n| ETS | LASSO Regression | Trimmed (Winsorized) Mean |\n| Spline | Ridge Regression | N-Best |\n| Theta Method | Elastic Net | Linear Regression |\n| TBATS | Principal Component Regression | LASSO Regression |\n| STL | Partial Least Squares Regression | Ridge Regression |\n| AR Perceptron | Random Forest | Partial Egalitarian LASSO |\n|  | Tree-Based Gradient Boosting Machine | Principal Component Regression | \n|   |  Single Layered Neural Network  | Partial Least Squares Regression  |\n|  | | Random Forest |\n|  | | Tree-Based Gradient Boosting Machine |\n|  | | Single Layered Neural Network  |\n\n\n### 3. Analyze\n\n| Accuracy | Compare | Visualize |\n|----------------------|------------------------|-----------------------|\n| Mean Square Error (MSE) | Forecast Error Ratios | Forecasts |\n| Root Mean Square Error (RMSE) | Diebold-Mariano Test (for unnested models) | Errors |\n| Mean Absolute Error (MAE) | Clark and West Test (for nested models) |  |\n| Mean Absolute Percentage Error (MAPE) |  | |\n\n---\n\n## Model estimation flexibility and accessibility\n\nUsers may edit any model training routine through accessing a list of function arguments. For machine learning techniques, this entails editing [caret](https://github.com/topepo/caret) arguments including: tuning grid, control grid, method, and accuracy metric. For univariate time series forecasting, this entails passing arguments to [forecast](https://github.com/robjhyndman/forecast) package model functions. For imputing missing variables, this entails passing arguments to [imputeTS](https://github.com/SteffenMoritz/imputeTS) package functions.\n\nA brief example using an `Arima` model to forecast univariate time series:   \n\n\t# 1. create the central list of univariate model training arguments, univariate.forecast.training  \n\tforecast_univariate.control_panel = instantiate.forecast_univariate.control_panel()  \n\n\t# 2. select an item to edit, for example the Arima order to create an ARMA(1,1)   \n\t\t# view default model arguments (there are none)  \n\t\tforecast_univariate.control_panel$arguments[['Arima']] \n\t\t# add our own function arguments  \n\t\tforecast_univariate.control_panel$arguments[['Arima']]$order = c(1,0,1) \n\nA brief example using the `Random Forest` to combine forecasts:   \n\n\t# 1. create the central list of ML training arguments \n\tforecast_combinations.control_panel = instantiate.forecast_combinations.control_panel()  \n\n\t# 2. select an item to edit, for example the random forest tuning grid   \n\t\t# view default tuning grid  \n\t\tforecast_combinations.control_panel$tuning.grids[['RF']]  \n\t\t# edit tuning grid   \n\t\tforecast_combinations.control_panel$tuning.grids[['RF']] = expand.grid(mtry = c(1:6))  \n---\n## Basic workflow\n\t#----------------------------------------\n\t### Forecasting Example\n\t#----------------------------------------\n\t# pull and prepare data from FRED\n\tquantmod::getSymbols.FRED(\n\t\tc('UNRATE','INDPRO','GS10'), \n\t\tenv = globalenv())\n\tData = cbind(UNRATE, INDPRO, GS10)\n\tData = data.frame(Data, date = zoo::index(Data)) %\u003e%\n\t\tdplyr::filter(lubridate::year(date) \u003e= 1990)\n\n\t# run univariate forecasts \n\tforecast.uni = \n\t\tforecast_univariate(\n\t\t\tData = dplyr::select(Data, date, UNRATE),\n\t\t\tforecast.dates = tail(Data$date,15), \n\t\t\tmethod = c('naive','auto.arima', 'ets'),      \n\t\t\thorizon = 1,                         \n\t\t\trecursive = FALSE,\n\n\t\t\t# information set       \n\t\t\trolling.window = NA,    \n\t\t\tfreq = 'month',                   \n\t\t\t\n\t\t\t# outlier cleaning\n\t\t\toutlier.clean = FALSE,\n\t\t\toutlier.variables = NULL,\n\t\t\toutlier.bounds = c(0.05, 0.95),\n\t\t\toutlier.trim = FALSE,\n\t\t\toutlier.cross_section = FALSE,\n\t\t\t\n\t\t\t# impute missing\n\t\t\timpute.missing = FALSE,\n\t\t\timpute.method = 'kalman',\n\t\t\timpute.variables = NULL,\n\t\t\timpute.verbose = FALSE) \n\n\t# create multivariate forecasts\n\tforecast.multi = \n\t\tforecast_multivariate(\n\t\t\tData = Data,           \n\t\t\tforecast.date = tail(Data$date,15),\n\t\t\ttarget = 'UNRATE',\n\t\t\thorizon = 1,\n\t\t\tmethod = c('ols','lasso','ridge','elastic','GBM'),\n\n\t\t\t# information set       \n\t\t\trolling.window = NA,    \n\t\t\tfreq = 'month',                   \n\t\t\t\n\t\t\t# outlier cleaning\n\t\t\toutlier.clean = FALSE,\n\t\t\toutlier.variables = NULL,\n\t\t\toutlier.bounds = c(0.05, 0.95),\n\t\t\toutlier.trim = FALSE,\n\t\t\toutlier.cross_section = FALSE,\n\t\t\t\n\t\t\t# impute missing\n\t\t\timpute.missing = FALSE,\n\t\t\timpute.method = 'kalman',\n\t\t\timpute.variables = NULL,\n\t\t\timpute.verbose = FALSE,\n\t\t\t\n\t\t\t# dimension reduction\n\t\t\treduce.data = FALSE,\n\t\t\treduce.variables = NULL,\n\t\t\treduce.ncomp = NULL,\n\t\t\treduce.standardize = TRUE) \n\n\t# combine forecasts and add in observed values\n\tforecasts = \n\t\tdplyr::bind_rows(\n\t\t\tforecast.uni,\n\t\t\tforecast.multi) %\u003e%\n\t\tdplyr::left_join( \n\t\t\tdplyr::select(Data, date, observed = UNRATE))\n\n\t# forecast combinations \n\tforecast.combo = \n\t\tforecast_combine(\n\t\t\tforecasts, \n\t\t\tmethod = c('uniform','median','trimmed.mean',\n\t\t\t\t\t   'n.best','lasso','peLasso','RF'), \n\t\t\tburn.in = 5, \n\t\t\tn.max = 2)\n\n\t# merge forecast combinations back into forecasts\n\tforecasts = \n\t\tforecasts %\u003e%\n\t\tdplyr::bind_rows(forecast.combo)\n\n\t# calculate forecast errors\n\tforecast.error = forecast_accuracy(forecasts)\n\n\t# view forecast errors from least to greatest \n\t#   (best forecast to worst forecast method)\n\tforecast.error %\u003e% \n\t\tdplyr::mutate_at(vars(-model), round, 3) %\u003e%\n\t\tdplyr::arrange(MSE)\n\n\t# compare forecasts to the baseline (a random walk)\n\tforecast_comparison(\n\t\tforecasts,\n\t\tbaseline.forecast = 'naive',  \n\t\ttest = 'ER',\n\t\tloss = 'MSE') %\u003e% \n\t\tarrange(error.ratio)\n\n\t# chart forecasts\n\tchart = \n\t\tchart_forecast(\n\t\t\tforecasts,              \n\t\t\tTitle = 'US Unemployment Rate',\n\t\t\tYlab = 'Index',\n\t\t\tFreq = 'Monthly')\n\n\tchart\n\n---\n## Contact\nIf you should have questions, concerns, or wish to collaborate, please contact [Tyler J. Pike](https://tylerjpike.github.io/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylerjpike%2Foos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftylerjpike%2Foos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftylerjpike%2Foos/lists"}