Model or dataset
pyaf/load_forecasting avatar
pyaf/load_forecasting

load_forecasting: nine Delhi load models with unequal training windows

Forecasting electric power load of Delhi using ARIMA, RNN, LSTM, and GRU models

648 stars166 forksJupyter NotebookMIT

At a glance

What is it?
pyaf/load_forecasting is an undergraduate project fitting nine models to daily Delhi electricity load, from simple moving average through ARIMA to LSTM and GRU. The interesting detail is that the models are not trained on equal footing: the linear and smoothing families get one month of history and the recurrent models get two. Only ARIMA gets a hyperparameter search, and the Django comparison server is marked deprecated.
Who is it for?
Use this if you want a readable set of nine forecasting implementations over a public load series, with the notebooks worth more than the service. Skip it if you need to run it, because there is no requirements file, no test and no version to install, and the comparison site it was built around is deprecated.
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?
Activity is slowing. The repository last received commits 6 months 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 October 10, 2026, and from our analysis. They are not legal advice.

Editorial analysis

ARIMA trains on one month of history and the recurrent models train on two

The fitting scripts are split by model family, and each family gets a different amount of history. aws_arima.py fits an ARIMA model on the last one month of data and forecasts the load for each day. aws_rnn.py fits RNN, LSTM and GRU on the last two months of data and forecasts the load for each day. aws_smoothing.py fits SES, SMA and WMA on the last one month.

So the nine models are not being compared on equal footing. The linear time series models and the recurrent models are trained on windows of different lengths, and a month versus two months is a large difference when the target is a daily load series.

The grouping is otherwise sensible. Exponential smoothing and moving averages need almost no history to be meaningful, ARIMA needs enough points to identify its own order, and a recurrent network needs enough sequences to have anything to learn. Two months is still a short window for a network, which tells you the choice was made for what was available rather than for what was ideal.

None of the scripts is documented beyond that one line, so the train and test split, the forecast horizon and the error metric are not stated anywhere in the repository.

Two scrapers feed csv files and a 00:30 IST job runs three scripts

The data side is two scripts. load_scrap.py scrapes day-wise load data for Delhi from the State Load Despatch Center site and stores it in csv format. wheather_scrap.py, misspelled in the filename as well as in the description, scrapes day-wise weather data for Delhi from wunderground, using the daily history page for the VIDP station, and stores that in csv too.

Weather is in the pipeline as a covariate, which is what makes this more than a univariate load exercise. The load series comes from the system operator and the weather series from an external observation station, and the two are joined downstream by the fitting scripts.

The scheduling is a single file. aws.py is described as a scheduler that runs all three fitting scripts every day at 00:30 IST, and the repository root holds celery.sh alongside it, so the schedule is a Celery beat configuration rather than a crontab entry.

Running at half past midnight local time is not incidental. The scrapers need the previous day's figures to be published by the load despatch centre before the fit runs, so the trigger is set after the upstream data lands rather than on a round hour.

Hyperparameter search exists for ARIMA and for nothing else

One script in the list is a grid search: pdq_search.py, which searches the hyperparameters of the ARIMA model on the last one month's data. The order, p, q and d, is the standard ARIMA parameterisation.

Nothing equivalent exists for the other eight. There is no search over the moving average window, none over the exponential smoothing parameters, and none over the recurrent architectures, their layer counts or their sequence lengths.

That asymmetry is the main methodological gap in the repository, and it is visible precisely because the search script is named in the same list as the fit scripts. If the comparison is the point of the project, the linear models got tuned and the neural ones got a fixed configuration.

It is also worth noting what the search is scoped to. It runs on one month of data, which is the same window aws_arima.py fits on, so the search and the final fit see the same history and a hyperparameter chosen there may be tuned to that particular month.

Nine notebooks hold the models and only three scripts operationalise them

The models folder is the substance of the project and it is nine Jupyter notebooks, one per algorithm. Feed forward neural network, simple moving average, weighted moving average, simple exponential smoothing, Holts Winters, ARIMA, RNN, LSTM and GRU, each in its own .ipynb file.

That ordering runs from the simplest possible estimator to the most parameterised one, which makes the folder read as a progression rather than a menu. A moving average needs no fitting, Holts Winters needs two smoothing parameters, ARIMA needs an order, and the recurrent models need an architecture.

The primary language recorded for the repository is Jupyter Notebook rather than Python, which is a fair summary of how the work was done. The scripts are a later layer: five Python files that take the same models and run them unattended on a schedule, with the notebooks remaining the place where the models were developed.

There is a screenshots folder at the root, which suggests results were captured as images rather than as a numeric table, and there is no results file, no benchmark CSV and no committed metric to compare against.

The Django comparison server is in the tree and its domain is dead

The server folder holds Django webserver code, written to show the implemented algorithms and compare their performance. Every implemented algorithm was used to forecast the current Delhi electricity load at forecast.energyandsystems.com, and the README marks that link as now deprecated.

So the comparison interface was a real deliverable rather than a notebook aside, and it is no longer reachable. The code is still in the repository, which means the piece that would let you reproduce a side by side comparison is available while the thing that produced one is not.

The design implied by the README is a polling page that asks each model for today's forecast. That is a different and harder thing than scoring models on a fixed historical window, because it assumes the models are already fitted and being kept current, which is what the 00:30 IST job does.

There is also a Report folder holding the project report, which is where the numbers behind the comparison would be if they are written down anywhere.

Eight top-level entries, and no requirements file among them

The whole repository is .gitignore, LICENSE, README.md and five directories: Report, models, screenshots and server, plus celery.sh. That is the entire tree.

There is no requirements.txt, no environment.yml, no pyproject.toml and no setup.py. A notebook that imports TensorFlow, a Django server and a Celery scheduler cannot be reconstructed from what is committed here, because nothing records which versions of anything were used.

There are no tests either, and no CI configuration. For a project whose entire claim is a comparison between nine models, there is no artefact in the repository that would fail if a model regressed.

What the repository does commit is unusually good on one axis: the model implementations are all present as readable notebooks rather than as a compiled artefact, so the nine algorithms can be read and understood without running anything.

A student project last pushed on 2026-03-25, with no releases and a master branch

This is an undergraduate project and the README says so in the first sentence, listing four team members. That framing matters for reading everything else, because a course project sets a different bar from a maintained library.

The recorded state reflects that. The repository is not archived, but the last recorded push is 2026-03-25, which is over six months before the current date. There are no GitHub releases at all, and there is no version to pin.

The default branch is master rather than main, the primary language is recorded as Jupyter Notebook, the licence is MIT, and no homepage is recorded. The recorded counts are 648 stars, 166 forks and 12 open issues.

The forks are worth reading against the stars. A fork count of 166 on a project with a dead demonstration site suggests the code was reused rather than the service depended on, which is the outcome a dataset and a set of notebooks can plausibly have.

Editorial conclusion

Use this if you want a readable set of nine forecasting implementations over a public load series, with the notebooks worth more than the service. Skip it if you need to run it, because there is no requirements file, no test and no version to install, and the comparison site it was built around is deprecated. Before you draw conclusions from the models, check the training windows, since the recurrent ones see twice the history the ARIMA and smoothing ones do, and note that only ARIMA was tuned.

Frequently asked questions

what is short term load forecasting

In this repository it means forecasting Delhi daily electricity load for each day ahead, from data taken from the State Load Despatch Center in Delhi. Nine models are implemented, from simple moving average and exponential smoothing through ARIMA to recurrent, LSTM and GRU networks.

what is load forecasting

Here it is treated as a model comparison problem rather than a single forecast. The same Delhi load data is fitted with nine different algorithms, and a Django webserver was built to show the implemented algorithms side by side and compare their performance.

What data does load_forecasting use?

Two scrapers feed it. load_scrap.py pulls day-wise load data for Delhi from the State Load Despatch Center site and stores it in csv, and wheather_scrap.py pulls day-wise weather data from wunderground for the VIDP station, also as csv. Weather is what makes this more than a univariate load exercise.

How are the load_forecasting models run?

aws.py is a scheduler that runs the three fitting scripts every day at 00:30 IST, using the celery.sh file at the repository root. aws_arima.py fits ARIMA on the last month of data, aws_rnn.py fits RNN, LSTM and GRU on the last two months, and aws_smoothing.py fits SES, SMA and WMA on the last month.

Is the load_forecasting website still online?

No. The README links to a site that showed every implemented algorithm forecasting the current Delhi load and marks it as now deprecated. The Django code in the server folder is still in the repository, along with a Report folder holding the project report.

Official sources

  1. Issues
  2. License: MIT
  3. pyaf/load_forecasting on GitHub
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pyaf-load-forecasting.svg)](https://hysenlabs.com/projects/pyaf-load-forecasting)