Hotel pricing engine
Six demand signals set the rate for every room, every night.
Data and BI · Python · Browsable demo

The problem
A hotel room expires every night: the one empty tonight is not sold tomorrow, it is lost. Price it high and it stays empty, price it low and margin is given away — so the decision repeats daily, per room type.
What it does
- Encodes the pricing decision as an algorithm built on six demand factors.
- One of them is booking lead time: a last-minute premium within thirty days.
- Projects the revenue impact sixty days out.
- Computes the industry indicators: average daily rate, revenue per available room and occupancy.
What was decided while building it
- A safety band the model cannot jump
- The final rate is capped between seventy and two hundred and twenty per cent of the base price, whatever the factors do. A multiplicative model with no ceiling produces, on the day high season, weekend, event and last-minute all land together, a price no manager would sign off. The band is what gets signed, and a test refuses to let anything out of it.
- The last-minute premium switches off at thirty days
- Booking well in advance carries no premium at all: the surcharge grows linearly only inside the last thirty days and tops out at twenty-nine per cent. Charging for advance booking is charging people for planning ahead, which is the opposite of what you want to reward.
- Occupancy pressure looks at fourteen days, not yesterday
- The last two weeks of occupancy are averaged and turned into three steps: high pressure, normal or slack. Reacting to yesterday's figure turns any noise into a rate change, and a rate that moves every day stops being a pricing policy and becomes an alarm.
- The seed is stated, and so is the fact that it is not enough
- The generator seeds on import, so two consecutive calls give different numbers: anyone who needs to reproduce a dataset has to re-seed explicitly. There are two tests, one for each side, because promising reproducibility and not testing it is the most common way of not having it.
How far it goes
- The six factors act on the forecast. The two-year history behind average rate and occupancy uses only three: season, day of week and event.
- It is not an optimiser. There is no demand curve and no elasticity: expected occupancy is computed without looking at the proposed price, so raising the rate does not lower it. It does not demonstrate that the model increases revenue.
- Four of the six factors are pure calendar — month, weekday, marked date and lead time — hand-written tables. Only occupancy pressure observes anything, and what it observes is data the script itself generated.
- The data is synthetic, the event calendar is American and the amounts are in dollars. The dashboard that draws them lives in a different repository.
- 6 pricing factors
- 730 days of history
- 60 days of forecast
Built with
- Python
- NumPy
- React
Where the data comes from
Synthetic data generated by the repository itself: no client information involved.