pyaf/load_forecasting: Nine Load Forecasting Models in One Undergraduate Repository
Forecasting electric power load of Delhi using ARIMA, RNN, LSTM, and GRU models
At a glance
- What is it?
- A notebook collection and three AWS scripts that forecast Delhi's short term electric load with ARIMA, RNN, LSTM, GRU, and four smoothing methods. The comparison value is real; the production story rests on scrapers pointed at two external websites.
- Who is it for?
- Adopt this repository if you want a readable, side by side comparison of classical smoothing, ARIMA, and recurrent networks on a single real load series, or if you are replicating an academic load forecasting project and need the notebook structure.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 174 days ago.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: comparing nine forecasters on one Delhi load series
Short term electric load forecasting asks a narrow question: how much power will a region draw over the next day. The repository is an undergraduate project that answers it for Delhi using data pulled from the State Load Despatch Center. Its contribution is not a new algorithm. It is a side by side implementation of nine methods on the same target series, from Simple Moving Average and Weighted Moving Average through Simple Exponential Smoothing and Holts Winters, then ARIMA, and finally a feed forward network plus RNN, LSTM, and GRU cells. The audience is students and engineers who want to see how a smoothing baseline compares with a sequence model on the same data without assembling nine codebases. The README describes the work as an undergraduate project, and the scope matches that framing: the interesting part is the comparison, not any single model.
Repository layout: notebooks for study, scripts for the daily run
The project splits into three parts. The models folder holds one notebook per algorithm, named after the method: FFNN.ipynb, SMA.ipynb, WMA.ipynb, SES.ipynb, HW.ipynb, ARIMA.ipynb, RNN.ipynb, LSTM.ipynb, GRU.ipynb. The top level holds the operational scripts, all prefixed aws_ and all written as plain Python rather than notebooks. The server folder holds Django code that the README says was built to display the algorithms and compare their performance, with a note that the hosted instance at forecast.energyandsystems.com is now deprecated. A Report folder carries the project write up, and screenshots/website.png shows the comparison page. One consequence of this split is that the notebooks and the scripts are separate code paths. A change to the ARIMA notebook does not propagate to aws_arima.py. Anyone reading the notebooks for method and then running the scripts in production is maintaining two implementations of the same idea.
Two scrapers feed the pipeline, and that is the weak joint
Data collection is handled by load_scrap.py, which the README says scrapes day wise load data for Delhi from the SLDC site and stores it as CSV, and wheather_scrap.py, which scrapes day wise weather data for Delhi from a wunderground history URL and also stores CSV. Both are HTML scrapers against third party pages. That design choice is the main operational risk in the repository. A scraper is coupled to the markup of a page nobody in this project controls, and the wunderground target is a dated history URL of the form /history/airport/VIDP/2017/8/1/DailyHistory.html. If either site changes its table structure, blocks automated requests, or moves the data behind a different endpoint, the daily forecast has no input. There is no fallback source, no API client, and no schema validation described in the README. Weather enters the pipeline only through this scraper, so a silent scraping failure degrades the feature set rather than raising an obvious error.
The daily job: three scripts, one scheduler, different training windows
The operational design is a rolling refit rather than a trained and frozen model. aws_arima.py fits ARIMA on the last one month of data and forecasts load for each day. aws_rnn.py fits RNN, LSTM, and GRU on the last two months of data and forecasts each day. aws_smoothing.py fits SES, SMA, and WMA on the last one month and forecasts each day. aws.py is described as a scheduler that runs all three scripts every day at 00:30 IST. The training windows differ by model family, which is a deliberate looking choice: the recurrent models get twice the history of the statistical ones. The README does not explain why, and the notebooks would be the place to check whether two months was chosen for accuracy or for compute time. Refitting daily on a one or two month window means the model tracks recent regime changes but never learns seasonal structure that spans a year, since no window in the pipeline is long enough to see a full annual cycle. pdq_search.py exists to grid search ARIMA hyperparameters on the last month of data, which suggests the order is meant to be re-derived rather than fixed, though the README does not state whether aws_arima.py calls it or uses a hardcoded order.
What you actually run, and what the repository does not give you
The README lists the scripts and their roles but does not provide a requirements file, an install command, a Dockerfile, or a configuration example. There are no releases, so there is no version tag to pin and no changelog to read before upgrading. The last push date is 2026-03-25, which means the project is not archived, but the absence of releases means every consumer tracks the master branch. To run anything you install the dependencies the notebooks and scripts import, then invoke the scripts directly: python load_scrap.py and python wheather_scrap.py to populate the CSVs, python pdq_search.py to search ARIMA orders, and python aws.py to start the daily scheduler. The scheduler hardcodes 00:30 IST in its description, so running outside India means either accepting that offset or editing the schedule. The Django server in the server folder has no documented setup path in the README beyond its existence, and the live deployment is marked deprecated, so treat the web layer as a reference implementation of the comparison view rather than a service to deploy.
Where this is the wrong tool
The pipeline forecasts one city's aggregate load from one historical series plus scraped weather. It has no notion of temperature forecasts, holiday calendars, or special events, and the README does not claim otherwise. For a control room that needs probabilistic forecasts with calibrated intervals, or a feeder level forecast, this repository offers point forecasts from a single series and no uncertainty quantification. The daily refit also means the model has no memory beyond its training window: a one month ARIMA fit cannot represent the previous summer's peak, and a two month recurrent fit has seen only part of a season. If your load series has strong annual seasonality and you cannot supply exogenous calendar features, the simpler smoothing notebooks will likely be the honest baseline, and the recurrent notebooks will need more history than the scripts provide. Finally, the scraping dependency makes this a poor fit for any environment where an unannounced upstream markup change would be treated as an incident.
Alternatives and the difference in approach
The obvious alternative is a general purpose time series library such as statsmodels for the ARIMA and exponential smoothing side, or a deep learning framework's sequence model API for the neural side. The difference is not accuracy, it is what the code owns. A library gives you a maintained estimator, documented parameters, and a test suite; you supply the data pipeline. This repository gives you the opposite: nine worked examples and a scraper based pipeline, with the estimators imported from libraries anyway. The second alternative is a managed load forecasting service, which removes the scraping and scheduling work entirely but also removes the ability to read the model. The reason to pick this repository over either is the comparison itself. Nine notebooks sharing one target series is a useful artifact for teaching and for sanity checking a new method against simple baselines. The reason not to pick it is that the production path, three scripts plus two scrapers plus a scheduler, is the least documented and least portable part of the project.
Licence, maintenance, and what to check before depending on it
The repository is MIT licensed, which permits commercial use, modification, and redistribution provided the copyright notice and permission notice are retained. That covers the code in this repository. It does not cover the data: the README states the load data comes from the State Load Despatch Center, Delhi, and the weather data from wunderground, and neither source's terms are addressed in the README. Scraping those pages and redistributing the resulting CSVs is a question for whoever operates the deployment, not something the MIT licence settles. On maintenance, the project has no releases and no versioning, so upgrades mean diffing master. The notebooks and the aws_ scripts duplicate logic, so a fix applied in one place can leave the other stale. Before depending on it, verify three things: that load_scrap.py and wheather_scrap.py still parse their target pages, that the ARIMA order used by aws_arima.py is either re-searched or documented, and that 00:30 IST matches your forecast delivery deadline.
Editorial conclusion
Adopt this repository if you want a readable, side by side comparison of classical smoothing, ARIMA, and recurrent networks on a single real load series, or if you are replicating an academic load forecasting project and need the notebook structure. Do not adopt it as the forecasting layer of a live grid operation: the daily pipeline depends on scraping delhisldc.org and a wunderground history URL, the Django front end is marked deprecated, and the repository ships no released version to pin. Before committing, open load_scrap.py and wheather_scrap.py and confirm the target pages still return the tables they parse, then run pdq_search.py against a recent month of your own data to see how stable the chosen ARIMA order is.
Community notes