A reinforcement learning system that trains a PPO agent to dynamically price products in a simulated competitive retail market, calibrated on 26,342 real retail transactions, tested across 5 shock scenarios and 5 competitor archetypes.
Can an AI learn to make smarter pricing decisions than a human expert and adapt those decisions in real time as market conditions change?
This project builds a complete answer to that question. Using real transaction data from a UK online retailer, we constructed a digital market simulator, trained a reinforcement learning agent to compete in that market, and measured exactly how much better the AI performs compared to expert-designed pricing rules across five market conditions and five competitor types.
Course: IS557 Applied Machine Learning β University of Illinois Urbana-Champaign
Timeline: January 2026 β May 2026
| Metric | Value |
|---|---|
| Training Steps | 600,000 (across 5 independent random seeds) |
| Market Scenarios Won | 5 / 5 |
| Profit Lift vs. Expert Benchmark | +8% to +79% |
| Average Revenue Pool Captured | 46.8% (vs. 33.3% equal-share benchmark) |
| Competitor Archetypes Beaten | 4 / 5 |
| Demand Model RΒ² | 0.516 (OLS, calibrated on real retail data) |
| Retail Transactions Processed | 26,342 |
| Validation Figures Produced | 13 publication-ready plots |
| Price Volatility Reduction (Stability Penalty) | β90.8% with +2.1% profit gain |
The project is organized into modular, reproducible components:
market_sim/
βββ demand_engine/ # OLS demand model calibrated on 26,342 real transactions
βββ shock_engine/ # Composable market shock simulator (5 shock types)
βββ competitor_agents/ # 5 rule-based competitor archetypes + SmartHeuristic benchmark
βββ gym_environment/ # Custom OpenAI Gymnasium environment (52-week episodes)
βββ training/
β βββ train_rl_agent.py # PPO training via Stable-Baselines3 (QUICK / hero run)
βββ evaluation/ # Scenario benchmarking, multi-seed study, lambda ablation
βββ scripts/
β βββ output/ # 13 publication-ready figures + CSV summaries
β βββ cross_validate_demand.py
βββ data/ # Cleaned retail transaction dataset (26,342 records, 56 SKUs)
βββ validate_simulator.py # 49-check validation suite (run before training)
- Source: Online Retail dataset (UK retailer, Dec 2010βDec 2011, 541,909 total transactions)
- Filtered to reusable shopping bag SKUs: 26,342 transactions across 56 SKUs
- Fit a calibrated OLS demand model:
D(t) = 33,743 β 17,641 Γ Price + 203 Γ t + Ξ΅ (Ο = 2,386, RΒ² = 0.516)
| Parameter | Meaning |
|---|---|
| a = 33,743 | Theoretical maximum weekly market demand |
| b = β17,641 | Demand falls by 17,641 units per Β£1 price increase (high elasticity) |
| c = 203 | Weekly growth trend in eco-friendly bag demand |
| Ο = 2,386 | Real market noise β genuine week-to-week unpredictability |
Seasonal multipliers were extracted directly from the data (0.478 in February β 1.395 in November).
- 52-week episodes simulating one year of competitive retail pricing
- Action space: 29 discrete price points (Β£0.80 to Β£2.20 in 5p steps)
- Observation vector (6 dimensions): own price, average competitor price, demand level, seasonal factor, active shock type, price spread vs. competitors
- Demand allocation: Logit model β
Share_i = exp(βΞ± Γ Price_i) / Ξ£ exp(βΞ± Γ Price_j)with Ξ± = 2.5 (calibrated from data) - Reward function:
The stability penalty (Ξ» = 2,500) discourages erratic repricing β a real deployment constraint on platforms like Amazon Seller Central.
Reward = [(Price β Cost) Γ Units Sold β Ξ» Γ |ΞPrice|] / 21,000
Shocks work by modifying the structural parameters of the demand equation, not arbitrary multipliers. This is the economically correct approach and a key technical novelty of this project.
| Shock Type | Active Period | Economic Effect | RL Lift vs. Benchmark |
|---|---|---|---|
| Normal | Baseline | Calibrated OLS parameters, no disruption | +24.4% |
| Inflation | Weeks 10β50 | Price sensitivity +60%, cost floor +30%, market size β10% | +13.7% |
| Recession | Weeks 10β52 | Market size β40%, demand volatility +50%, trend reverses | +8.1% |
| Demand Surge | Weeks 10β50 | Market size +50%, price sensitivity β40% | +79.3% |
| Stagflation | Weeks 10β50 | Inflation (0.8) + Recession (0.6) stacked simultaneously | +8.0% |
Shocks are composable β multiple shocks can be stacked multiplicatively, matching how real economic disruptions work.
| Competitor | Strategy | Real-World Parallel | RL Win Rate |
|---|---|---|---|
| Fixed Price Seller | Always charges Β£1.80 | Traditional high-street brand pricing | 25/25 (+70.6% avg lift) |
| Undercutter | Always 90β97% of agent's last price | Amazon loss-leader / discount repricers | 0/25 (β5.3% avg lift)* |
| Premium Seller | Always 105β115% of agent's last price | John Lewis / Dyson premium anchoring | 25/25 (+13.0% avg lift) |
| Chaotic Random | Random 70β130% of base price | Disorganised liquidation sellers | 25/25 (+49.5% avg lift) |
| Reactive Agent | Raises/lowers based on sales velocity threshold | Basic Amazon repricers | 25/25 (+70.3% avg lift) |
*The Undercutter creates a structural race-to-the-bottom. This is treated as a genuine finding, it defines the boundary condition of the RL approach and mirrors the real challenge of competing with Amazon Warehouse pricing.
The SmartHeuristic benchmark is a sophisticated market-aware rule-based system (undercuts by 5p by default, adjusts +8β18p for surges and β8β12p for recessions). Beating it proves RL adds genuine value beyond expert rule design.
| Parameter | Value |
|---|---|
| Algorithm | PPO (Proximal Policy Optimization) via Stable-Baselines3 |
| Network Architecture | MLP β 6 inputs β 256 β 256 β 29 outputs (ReLU) |
| Training Steps | 600,000 (hero run) |
| Parallel Environments | 6 (rotating shock types for diversity) |
| Learning Rate | 0.0003 |
| Discount Factor (Ξ³) | 0.99 |
| Stability Lambda (Ξ») | 2,500 |
| Random Seeds | 5 independent runs for statistical validation |
| Training Time | ~60β90 minutes on a standard laptop |
| Scenario | RL Profit (Mean Β± SD) | Lift vs. SmartHeuristic | RL Revenue Pool Share |
|---|---|---|---|
| Normal | 162,963 Β± 1,420 | +26.2% Β± 1.0% | 48.0% Β± 1.7% |
| Inflation | 18,782 Β± 639 | +15.6% Β± 2.0% | 45.2% Β± 1.7% |
| Recession | 21,938 Β± 679 | +8.7% Β± 2.0% | 43.3% Β± 1.7% |
| Demand Surge | 527,343 Β± 63,971 | +82.7% Β± 6.4% | 57.5% Β± 3.1% |
| Stagflation | 18,946 Β± 637 | +9.4% Β± 2.1% | 43.3% Β± 1.7% |
The 33.3% equal-share benchmark is the revenue each agent would capture if all three were equally effective. The RL agent consistently captures 43β58%, proving active market share capture.
| Configuration | Avg Profit | Avg Pool Share | Avg Weekly Price Change |
|---|---|---|---|
| Ξ»=0 (no penalty) | 146,912 Β± 8,746 | 25.5% Β± 1.5% | 0.055 Β± 0.041 |
| Ξ»=2,500 (with penalty) | 149,994 Β± 12,844 | 28.5% Β± 1.8% | 0.005 Β± 0.002 |
| Improvement | +2.1% profit | +3.0 pp share | β90.8% volatility |
The stability penalty is a win-win: the agent is both more profitable and more stable with it active.
| Figure | Description |
|---|---|
fig_A_learning_curve.png |
PPO reward convergence over training episodes |
fig_B_profit_comparison.png |
RL vs. benchmarks: total profit per scenario with error bars |
fig_C_revenue_pool.png |
β Revenue pool capture β the key result figure |
fig_D_price_behaviour.png |
Price trajectories and cumulative profit per scenario |
fig_E_robustness_heatmap.png |
Profit heatmap and pool share bar chart |
fig_F_weekly_profit_grid.png |
Week-by-week profit with profitable/loss fills |
fig_G_competitor_breakdown.png |
Three-panel RL vs. all 5 competitors overview |
fig_H_competitor_lift_heatmap.png |
Lift percentage grid β clearest wins/losses summary |
fig_I_head_to_head_scorecards.png |
Dumbbell charts: absolute profit per 1v1 matchup |
fig_J_multiseed_scoreboard.png |
Statistical reliability across 5 independent seeds |
fig_K_lambda_ablation.png |
Effect of stability penalty on profit, share, and volatility |
fig_L_pricing_heatmap.png |
Heatmap of the learned pricing policy (week Γ scenario) |
fig_M_market_efficiency.png |
RL pricing vs. theoretical optimum from demand model |
| Layer | Tools |
|---|---|
| Language | Python |
| RL Framework | Stable-Baselines3 (PPO) |
| Environment | OpenAI Gymnasium |
| Data Processing | Pandas, NumPy |
| Demand Modeling | Scikit-learn (OLS regression) |
| Visualization | Matplotlib, Seaborn |
| Validation | Custom 49-check suite (validate_simulator.py) |
pip install stable-baselines3 gymnasium pandas numpy scikit-learn matplotlib seabornpython validate_simulator.py
# Expected: 49/49 checks passed β
# In training/train_rl_agent.py, set:
QUICK = Truepython training/train_rl_agent.py# In training/train_rl_agent.py, set:
QUICK = Falsepython training/train_rl_agent.pypython scripts/cross_validate_demand.py
# Requires: online_retail_II.xlsb or Retail_Transaction_Dataset.csvAll figures and summaries are saved to scripts/output/.
- Undercutter counter-strategy β adversarial co-training to discover non-obvious differentiation responses to loss-leader competitors
- TitForTat competitor β test agent robustness against game-theoretic strategic imitation (already coded in
competitors.py) - Multi-product / multi-SKU pricing β extend the simulator to portfolio pricing
- Real-time API β wrap the trained PPO model into a live pricing recommendation endpoint
- Academic publication β three submission-ready angles: simulator architecture, RL result, and stability penalty contribution
This project has three publishable technical contributions:
- Composable Parameter-Shift Shock Engine β structurally modifies demand equation parameters rather than using ad-hoc multipliers; shocks are stackable and economically grounded
- Stability-Penalty Reward Shaping β reduces price volatility by 90.8% while improving profit, directly addressing the deployment barrier of platform repricing penalties on e-commerce marketplaces
- Multi-Seed Statistical Validation β 5 independent training seeds with standard deviations reported across all 25 matchups, providing publication-grade reliability evidence
Tejas Jaggi
MS Information Management β University of Illinois Urbana-Champaign
LinkedIn Β· Portfolio Β· GitHub
Built with real data. Trained with discipline. Validated with rigour.