Live demo -> <PASTE_VERCEL_URL> · runs entirely in your browser, no backend needed.
PredictX takes a CSV of historical sales, benchmarks four time-series models with a rolling-origin backtest, picks the best one on out-of-sample error, and projects the next 1–365 days with an approximate 95% prediction band. The four models are implemented from scratch in TypeScript (src/lib/ml.ts, no ML libraries) and covered by unit tests.
Stack: React 18 · Vite · Recharts · Radix UI · Vitest · Django REST Framework (optional backend)
- Overview
- System Architecture
- Key Features
- Machine Learning Methodologies
- Model Evaluation and Backtesting
- Sample Datasets
- Project Structure
- Installation and Setup
- Data Ingestion Specifications
- Export and Reporting
- What I Built and What I Learned
- Limitations and Design Notes
- Credits
- Author and License
Accurate demand forecasting is a common operational requirement in retail, inventory management, and resource planning. PredictX provides an accessible interface to evaluate and project sales trends:
- Runs directly in the browser with client-side computation.
- Benchmarks multiple time-series algorithms using a rolling-origin backtest instead of a single split.
- Computes an approximate prediction band to communicate forecast uncertainty.
- Breaks down category sales shares and generates exportable CSV and PNG summaries.
flowchart TD
A[Historical Sales CSV or Preloaded Demo] --> B[Data Ingestion and Validation Engine]
B --> C[Date Aggregation and Chronological Sort]
C --> D[Rolling-Origin Backtest: Expanding Window, 10% Horizon]
D --> E[Multi-Model Benchmarking Engine]
E --> E1[Linear Regression]
E --> E2[Holt's Exponential Smoothing]
E --> E3[Moving Average with Momentum]
E --> E4[Polynomial Regression]
E1 & E2 & E3 & E4 --> F[Leaderboard: Pooled Out-of-Sample MAE, RMSE, MAPE, R2]
F --> G[Select Best Model and Refit on Full Series]
G --> H[Approximate 95% Prediction Band Computation]
H --> I[Interactive Recharts Trajectory Visualization]
I --> J[CSV / PNG Export and Brand Analytics]
- Multi-Model Benchmark: Trains and scores 4 forecasting algorithms using an expanding-window rolling-origin backtest.
- Model Selection: Selects the best-performing model based on minimal out-of-sample Mean Absolute Error (MAE), or allows manual selection.
- Approximate 95% Prediction Band: Visualizes an uncertainty band based on backtest RMSE that widens as the forecast horizon extends.
- Preloaded Demo Datasets: Instant 1-click access to automotive, consumer electronics, and SaaS subscription demo data.
- Configurable Horizon: Project between 1 and 365 days into the future with dynamic recalculation.
- Brand Market Share Analytics: Segment-level breakdowns, donut charts, and volume rankings on
/dashboard. - Export Tools: Download projected points and uncertainty bounds as CSV, or capture visual dashboard panels as PNG.
- Optional Django REST Backend: Provides atomic multi-row CSV upload, SQLite storage, and REST API endpoints.
PredictX incorporates four distinct time-trend forecasting algorithms written from scratch:
Fits a linear trend line through historical observations by minimizing the residual sum of squares: $$\hat{y}t = \beta_0 + \beta_1 t$$ Where: $$\beta_1 = \frac{\sum{i=1}^n (t_i - \bar{t})(y_i - \bar{y})}{\sum_{i=1}^n (t_i - \bar{t})^2}, \quad \beta_0 = \bar{y} - \beta_1 \bar{t}$$
Adapts to trends using recursive level and slope smoothing parameters (
Computes a rolling average baseline across a window
Solves a
The uncertainty standard deviation
Evaluating small time series (30–45 points) on a single 80/20 train/test split is noisy because the test set contains only 6–9 points.
PredictX uses an expanding-window rolling-origin backtest:
- Starts training on a minimum window (60% of the series).
- Predicts the next out-of-sample block with a horizon
$h \approx \max(1, \lfloor 0.10 \cdot n \rfloor)$ . - Expands the origin by
$h$ points and repeats until the end of the series. - Pools all out-of-sample forecast errors across all folds to calculate benchmark metrics:
| Metric | Formula | Description |
|---|---|---|
| MAE | Mean Absolute Error. Primary benchmark criterion for model selection. | |
| RMSE | Root Mean Square Error; penalizes large prediction outliers. | |
| MAPE | Mean Absolute Percentage Error; scale-independent error rate. | |
| R² Score | Coefficient of determination; measures variance explained by the model. |
Sample datasets are located in the sample_data/ directory and can also be loaded directly with 1 click in the user interface:
sample_data/car_sales_demo.csv: 45-day automotive sales records across Toyota, Honda, Tesla, BMW, and Ford.sample_data/retail_electronics_demo.csv: 31-day consumer electronics retail data across Apple, Samsung, Sony, and Dell.
predictx/
├── .github/
│ └── workflows/
│ └── ci.yml # GitHub Actions CI workflow (frontend + backend)
├── docs/
│ └── screenshots/ # Application screenshots
│ ├── dashboard.png # Populated dashboard view
│ ├── forecast-chart.png # Forecast chart with actuals and predictions
│ ├── model-results.png # Model benchmark leaderboard
│ └── brand-analytics.png # Brand market share donut chart
├── backend/ # Optional Django REST API backend
│ ├── api/
│ │ ├── migrations/ # Database migrations
│ │ ├── models.py # CarSalesData model
│ │ ├── serializers.py # DRF serializers
│ │ ├── urls.py # API routes (/test, /upload-car-data, /car-data)
│ │ ├── views.py # Atomic upload & list endpoints
│ │ └── tests.py # Django test suite (7 tests)
│ ├── server/ # Django project settings and URLs
│ ├── manage.py # Django CLI entrypoint
│ ├── requirements.txt # Python dependencies
│ └── .env.example # Template for environment variables
├── sample_data/ # Ready-to-test CSV files
│ ├── car_sales_demo.csv
│ └── retail_electronics_demo.csv
├── src/ # Frontend React Application
│ ├── components/
│ │ ├── ui/ # Radix UI primitives
│ │ └── CarDataTable.tsx # Backend database viewer modal
│ ├── lib/
│ │ ├── __tests__/ # Unit test suites (19 tests)
│ │ │ ├── ml.test.ts # ML engine & backtest tests
│ │ │ └── csvParser.test.ts # CSV parser & aggregation tests
│ │ ├── ml.ts # Forecasting algorithms & rolling-origin backtest
│ │ ├── sampleDatasets.ts # Preloaded demo datasets
│ │ ├── csvParser.ts # CSV parser & date aggregation helper
│ │ └── exportUtils.ts # CSV and PNG report export helpers
│ ├── pages/
│ │ └── CarDashboard.tsx # Brand distribution & market share analytics
│ ├── App.tsx # Main forecasting dashboard
│ ├── main.tsx # React DOM entry point
│ └── index.css # Global styles and pre-compiled Tailwind CSS
├── package.json # Node dependencies and scripts
├── vite.config.ts # Vite configuration (port 3000)
├── vercel.json # Vercel deployment and routing configuration
├── LICENSE # MIT License
└── README.md # Project documentation
- Node.js (v18.0 or higher)
- npm (v9.0 or higher)
- Python (v3.9 or higher, optional for backend)
Clone the repository:
git clone https://github.com/diyuworks/predictx.git
cd predictxInstall dependencies:
npm installRun unit tests:
npm testStart the local development server:
npm run devOpen the application at http://localhost:3000.
To create an optimized production build:
npm run buildIn a separate terminal:
cd backend
python -m venv venv
# On Windows:
venv\Scripts\activate
# On macOS/Linux:
source venv/bin/activate
pip install -r requirements.txt
python manage.py migrate
python manage.py test
python manage.py runserverThe Django REST API runs at http://127.0.0.1:8000/.
PredictX accepts CSV files with comma delimiters. The file must contain a header row with at least date and sales columns:
date,sales,brand
2024-01-01,142,Toyota
2024-01-02,156,Toyota
2024-01-03,138,Hondadate: Valid date string parsed viaDate.parse().sales: Non-negative numeric sales volume or revenue figure. Rows with invalid or negative values are automatically filtered out.brand(optional): Category label used for segment market share breakdowns on/dashboard. Defaults to"General"if omitted.- Date Aggregation: Multiple rows sharing the same date are summed into a single daily total before forecasting to ensure an uncorrupted chronological time index.
- Forecast CSV Export: Downloads a CSV containing date, actual sales, predicted values, and approximate 95% lower/upper bounds.
- High-Resolution PNG Capture: Captures dashboard charts and analytics panels as PNG images using
html2canvas. - Brand Analytics CSV: Exports market share breakdowns and volume rankings.
- Built the time-series forecasting algorithms (linear regression, Holt's linear exponential smoothing with damped trend, moving average, and quadratic polynomial fit via Gaussian elimination) from scratch in TypeScript with zero third-party ML dependencies.
- Replaced a standard single 80/20 train/test split with an expanding-window rolling-origin backtest after finding that evaluating small time-series (30–45 points) on a tiny holdout set caused high variance and noisy model selection.
- Structured an end-to-end data validation and date-aggregation pipeline to handle edge cases like duplicated dates, quoted CSV fields, missing columns, and non-numeric values before feeding the models.
- Built automated Vitest test suites (19 unit tests) and GitHub Actions CI to verify both the mathematical correctness of the models and the robustness of data parsing on every commit.
Written down on purpose, so nobody has to guess what this project does and doesn't claim.
- Prediction band is approximate. It is
1.96 × RMSE × sqrt(1 + 0.04·h), where RMSE comes from out-of-sample backtest errors and the horizon-widening factor is a heuristic. It is not a closed-form statistical prediction interval and its coverage has not been empirically validated. - Model selection uses a rolling-origin backtest (expanding window, horizon ≈ 10% of the series). With 30–45 daily points, differences between models can be within noise; treat "best model" as "best on this backtest".
- Models are simple trend models. No weekly/annual seasonality, holidays or external regressors. Holt damping uses a fixed φ = 0.98 and the forecast is
L + h·b·φ^h(a simplified damped trend), not the textbook cumulative-sum form. - One series per upload. Rows sharing a date are summed into one daily total before forecasting; the
brandcolumn is used only for the Brand Analytics page. - Demo datasets are synthetic, generated for demonstration.
- Backend is optional and not used by the hosted demo; it stores uploaded rows in SQLite and exposes
/api/upload-car-data/and/api/car-data/.
- UI components and design tokens adapted from shadcn/ui (MIT License), built on Radix UI and Tailwind CSS.
Developed by Diya Malviya.
GitHub: https://github.com/diyuworks
This project is licensed under the MIT License. See the LICENSE file for details.
