Skip to content

Dynamic pricing that reads demand in real time

A revenue-management engine that turns booking pace, seasonality, and local events into nightly rate recommendations across a multi-property portfolio.

Rate calendar · The Wharf House
October 2026 · 48 rooms · floor $99 · standard king, BAR
Room type: King Oct 1 – Oct 31, 2026JM
RevPAR · same months LY+19%11 properties, 2 refurbishments excluded
Manual pricing time−70%Managers review flagged nights only
Forecast accuracy92%Nightly demand per room type
Nights to move · October12Waiting on your accept or override

October 2026

Recommended Last year Event Withheld
SunMonTueWedThuFriSat
1124Held Live
2Festival172138LY 139+34 waiting
3Festival185142LY 142+43 waiting
4Festival139118LY 121+21 waiting
5112Held Live
6114Held Live
7116Held Live
8124Held Live
9151138LY 136+13 waiting
10158142LY 145+16 waiting
11118Held Live
12112Held Live
13106114LY 112−8 waiting
14109116LY 115−7 waiting
15124Held Live
16147138LY 134+9 waiting
17154142LY 140+12 waiting
18118Held Live
19112Held Live
20114Held Live
21108116LY 118−8 waiting
22124Held Live
23138Band 11 roomsWithheld
24149142LY 144+7 waiting
25118Held Live
26112Held Live
27114Held Live
28116Held Live
29124Held Live
30129138LY 137−9 waiting
31142Band 14 roomsWithheld

Nights the model wants to move

12 waiting
Fri 10/02138172LY 139+34
Sat 10/03142185LY 142+43
Sun 10/04118139LY 121+21
Fri 10/09138151LY 136+13
Sat 10/10142158LY 145+16
Tue 10/13114106LY 112−8
Wed 10/14116109LY 115−7
Fri 10/16138147LY 134+9
Sat 10/17142154LY 140+12
Wed 10/21116108LY 118−8
Sat 10/24142149LY 144+7
Fri 10/30138129LY 137−9
No rate moves until acceptedReview 12

Who, what, and how long

Industry
Hotels & Accommodation
Duration
12 weeks
Cooperation model
Fixed price
Services
Data engineeringForecasting modelsOps dashboards
Integrations
Amadeus GDSStripeSkyscannerSendGrid
Technologies
PythonFastAPIPostgreSQLReactRechartsScikit-learn
Team
1 Project lead1 Product designer1 Data engineer1 Analytics engineer1 Backend engineer1 QA engineer

Client name withheld under NDA. Engagement details are shown to the extent our agreement permits.

Introduction

The question we were asked

Rooms were priced from spreadsheets and gut feel, which left money on the table on high-demand nights and empty rooms on soft ones. We built a demand model and a pricing dashboard revenue managers actually trust.

Eleven properties, each with a revenue manager setting rates in their own spreadsheet, and a group finance team comparing them monthly. Nobody could see booking pace across the portfolio, so two hotels in the same city routinely discounted into the same weekend. The engagement began after a conference month when the group sold out at Tuesday's prices.

Data & AI

What it settled

The decision, first

  1. 01

    Combining local event signals with historical pace improved RevPAR by +19%.

    Pace alone reacts to demand that has already arrived. The events calendar moved the forecast before the bookings did, and that's where the nineteen percent came from.

  2. 02

    Human-in-the-loop override controls were essential for manager trust and adoption.

    The accept-or-override control is what made the model usable. Once managers could refuse it in one click, they stopped distrusting it in general.

  3. 03

    Automated rate recommendations reduced manual pricing workload by 70%.

    The workload fell because most nights are unambiguous. Managers stopped pricing every one of them and started reviewing the handful the model flagged as uncertain.

What the numbers couldn't answer

Rates were set by hand, property by property, with no shared view of booking pace or competitor movement. Pricing lagged market demand by days, and RevPAR paid for it.

Rates moved on a weekly cycle because that was how often someone sat down with the spreadsheet, while demand moved daily. The cost showed up in the pace data afterward: on the twelve highest-demand nights of the previous year, the group had been at or below its own average rate on nine of them.

We consolidated booking, occupancy, and event data into one pipeline, trained a demand-forecasting model, and shipped a dashboard that recommends nightly rates managers can accept or override in one click.

The solution

How we worked it through

  1. 01

    Unified booking and occupancy feeds across every property

    Booking pace, occupancy, rates and a local events calendar were normalized into one nightly feature table per room type: the join nobody had made before.

  2. 02

    Built a demand forecast from three years of historical pace data

    Three years of pace data lived in four systems, and no two of them agreed. Most of this step was deciding which source won on each disputed night.

  3. 03

    Designed an accept/override dashboard for revenue managers

    Two revenue managers sat through the design of this screen, and the accept-or-override control was their condition for using the model at all.

  4. 04

    Ran a shadow period comparing model rates to manual pricing

    For six weeks the model priced alongside the managers without touching a live rate, and the cases it lost are where the confidence-band rule came from.

Process

Phase by phase

  1. Phase 1: Pipeline Integration

    Multi-Source Data Ingestion

    Unified booking pace, historical occupancy, local event calendars, and market competitor rates into a central PostgreSQL data store.

    • Ingestion Pipeline Specs
    • PMS Integration API
    • Data Hygiene Monitor
  2. Phase 2: ML Model Training

    Predictive Demand Engine

    Tuned gradient-boosting demand forecasting models using 3+ years of seasonal booking data across the full property portfolio.

    • Demand Forecast Model
    • Validation Report
    • Yield Optimization Logic
  3. Phase 3: UX Dashboard Design

    Revenue Manager Cockpit

    Designed a clear accept/override dashboard interface where managers inspect recommendations and apply bulk pricing rules in seconds.

    • Dashboard UI Specs
    • Rate Preview System
    • Audit Trail Logging
  4. Phase 4: Pilot & Rollout

    Shadow Testing & Full Launch

    Piloted automated rate recommendations alongside manual pricing over 4 weeks, verifying a +19% RevPAR gain before chain-wide deployment.

    • Pilot Comparison Study
    • Staff Training Guide
    • Production Release
Shadow period · model vs managers
6 weeks priced alongside the managers · 11 properties · no live rate touched
6-week shadowJM

Engagement

12 weeks
Phase 1Wks 1–3Pipeline integrationPace, occupancy, events, competitor rates into PostgreSQL
Phase 2Wks 3–7Demand modelGradient boosting on 3 years of seasonal pace
Phase 3Wks 5–9Cockpit designAccept/override, drivers, audit trail
Phase 4Wks 7–12Shadow & rollout6-week shadow, then chain-wide

Model recommendation vs the manager's rate

Per week · all properties · 7 nights each
WeekNights pricedWithin $5 of managerDifferedDiffered · wide band
Week 177393817
Week 277443314
Week 377473012
Week 477492811
Week 57752259
Week 67753249
Where the managers were right, the band was wideThe nights the model was least sure about are the nights the managers kept winning, so those nights are no longer recommended at all: a band wider than 8 rooms goes to the manager.

Feeds into the nightly feature table

PostgreSQL · this morning
Booking pacePMS · 11 properties 5:40 AM
Occupancy & rate historyPMS + finance exports 5:40 AM
Local events calendarCity and venue listings 4:15 AM
Competitor ratesComp set, 4 hotels per property 5:05 AM
Weather forecast10-day, per property 5:20 AM
Disputed nights · which source winsStay dates and room typePMS folioRate actually paidFinance exportCancellations after 24 hChannel manager
On screen

The engagement in four phases, the six-week shadow period comparing the model's rate with the managers' week by week, including how many disagreements fell on wide-band nights, and the feeds and source-precedence rules behind the nightly feature table.

What it changed

+19%

RevPAR

−70%

Manual pricing time

92%

Forecast accuracy

RevPAR is compared against the same months of the previous year across the same eleven properties, with two refurbishments excluded from both sides. The manual-override rate is measured on live recommendations only, and it's reported per property because the group average hides the two that override most.

Client name withheld under NDA. Figures are approximate, drawn from the engagement’s own reporting.

Real-Time Demand Forecaster

Predicts nightly room demand across the property portfolio based on local events and pace metrics.

Three years of booking pace, occupancy and rate history were joined against a local events calendar and normalized into one nightly feature table. A gradient-boosted model predicts demand per room type per night and retrains weekly on a rolling window, so a shifting market doesn't need an engineer. Every prediction carries a confidence band, and the cockpit withholds a recommendation when that band is too wide to act on.

What shipped
  • Pace, occupancy and events in one nightly feature table
  • Weekly rolling retrain, no engineer in the loop
  • Recommendations withheld when confidence is too wide
Booking window · all properties
3 years of stays by how far ahead they were booked · 11 properties · all room types
Sep 2023 – Sep 2026JM
History in the model3 yearsPace, occupancy, rates and events, per night
Forecast accuracy92%Nightly demand per room type
Last retrainSun 09/13Rolling window, promoted automatically
Withheld · next 30 nights2Band wider than 8 rooms

Share of stays by lead time

Each weekday column sums to 100%
SunMonTueWedThuFriSatSame day8%11%10%10%7%4%3%1–6 days22%27%26%25%20%12%9%1–2 wks19%18%18%18%18%15%13%2–3 wks14%12%13%13%15%19%20%3–4 wks11%9%9%10%12%17%19%4–6 wks11%10%10%10%12%14%15%6–8 wks6%5%6%6%7%8%9%8–12 wks5%4%4%4%5%6%7%12+ wks4%4%4%4%4%5%5%
Fri 36% · Sat 39% of stays booked 2–4 weeks out, priced before demand showed

Nightly feature table

1 row per room type per night
propertyroom_typestay_datedowlead_bucketpace_7dpace_vs_lyocc_lyadr_lyevent_scorecomp_deltarain_prob
Local events calendar joined to pace for the first time

Model

Gradient-boosted · per room type per night
Sun 09/1309/2023 – 09/2026Promoted
Sun 09/0609/2023 – 09/2026Promoted
Sun 08/3008/2023 – 08/2026Promoted
Sun 08/2308/2023 – 08/2026Promoted
Withheld: band wider than 8 rooms
Fri 10/23Band 11 roomsManager prices it
Sat 10/31Band 14 roomsManager prices it
On screen

Three years of stays sorted by how far ahead they were booked, with the two- to four-week band on Fridays and Saturdays outlined; beside it the nightly feature table the model reads, its weekly rolling retrains, and the nights withheld because the confidence band was too wide.

Why 185, not 142
Sat 10/03/2026 · The Wharf House · standard king · 19 days out
Sat Oct 3, 2026JM
Recommended$185
Live now $142Last year, Sat 10/04/2025: $142 · full 24 days outBayside Folk FestivalBand 43–48 rooms · limit 8
Override…Accept $185 The channel rate stays $142 until accepted

What moved it

Top three drivers first · weight of the move
Bayside Folk FestivalTop 1Headline night on the local events calendar40%+$21
Booking paceTop 238 of 48 booked at 19 days out; typical Saturday: 2634%+$18
Competitor movesTop 33 of 4 comp-set hotels up an average $22 for Saturday17%+$9
Rain forecast70% chance of rain Saturday afternoon9%−$5

Revenue either way

48 rooms
At $142 · house full$6,81648 rooms × $142 · sells out weeks early
At $185 · forecast 46 rooms$8,510Band 43–48 rooms · $7,955–$8,880
Difference at the forecast+$1,694

Override scoreboard

Stored with a reason · replayed into the next training window
NightPropertyModelManagerReasonAfter the stayTraining
Sat 09/12WH$168$155Group block cancelled lateManager aheadSun 09/13 retrain
Fri 09/11SQ$176$189Conference overflow from downtownModel aheadSun 09/13 retrain
Sun 09/06PR$104$96Harbor Rd closed for resurfacingManager aheadSun 09/13 retrain
Thu 09/03WH$126$139Regatta missing from events calendarManager aheadSun 09/13 retrain

Accept/Override Cockpit

On screen

Why Saturday is 185 and not 142: the folk festival, booking pace, competitor moves and the rain, each with its weight, the revenue either way and accept or override, above a scoreboard of past overrides with their reasons and whether the manager or the model came out ahead.

A clear cockpit where revenue managers accept the model's rate or adjust it, with every override kept in an audit trail.

Each recommendation shows the three inputs that moved it most, so a manager overriding the model can see exactly what they're disagreeing with. Overrides are first-class: stored with a reason, replayed into the next training window, and reported back as a scoreboard of where the human beat the model and where they didn't. Nothing touches the live rate without an explicit accept.

What shipped
  • Top three drivers shown beside every recommendation
  • Overrides stored with reason and fed back into training
  • No rate moves without an explicit accept

Portfolio Yield Optimizer

Maximizes Revenue Per Available Room (RevPAR) automatically across high and low-demand booking windows.

Properties in the group had been competing with each other for the same booking windows. The optimizer solves across the whole portfolio at once, holding a floor rate per property and shifting exposure toward whichever site converts best that week. Managers keep local control (a property can be pinned out of the portfolio view), and the cost of each pin is reported back monthly.

What shipped
  • Solves across the whole portfolio at once
  • Per-property floor rates always respected
  • The cost of each manual pin reported monthly
Portfolio pace · Harbor district
5 of 11 properties · 214 rooms · nights 09/28–10/11 against the same nights last year
Sep 28 – Oct 11, 2026JM
Rooms · Harbor district2145 properties solved together
Room nights on the books1,9061,884 same nights last year
Waiting on a manager12Rate changes in this window
RevPAR · same months LY+19%All 11 properties

Pace by property

Floors always held · exposure shifts toward the best converter
PropertyRoomsOn the books vs last yearPaceFloorLowest rateWaitingSolve
WHThe Wharf House48441 / 672+7%$99$1185Shift exposure in
SQSaltmarsh Quay62540 / 868−3%$109$1123Hold near floor
PRPilot's Row Inn36330 / 504+7%$89$982Shift exposure in
LHThe Lantern Hotel40352 / 560+2%$119$164—Pinned out
GLGullhaven Lodge28243 / 392−7%$84$862Hold near floor

Waiting on a manager

5 of 12 · festival weekend first
NightPropertyLiveRecommendedMove
Sat 10/03WH$142$185+43WaitingReview
Fri 10/02WH$138$172+34WaitingReview
Sat 10/03SQ$164$198+34WaitingReview
Fri 10/09PR$118$129+11WaitingReview
Sun 10/04GL$92$104+12WaitingReview

Pinned out of the solve

September pin report
The Lantern HotelWedding block, 10/02–10/04 · set by the property’s manager
Pinned rate$164Portfolio solve would set$181Floor, always held$119
Estimated cost of this pin$17 × 24 open rooms × 3 nights$1,224
On screen

Five properties, 214 rooms, booking pace against the same nights last year with each floor and lowest rate side by side, the twelve rate changes still waiting on a manager, and one hotel pinned out of the solve with the estimated cost of that pin.

How the engagement ran

A cross-functional team of 6 worked on a fixed price basis over 12 weeks, covering Data engineering, Forecasting models, Ops dashboards. We shipped in two-week increments, each one releasable and reviewed live before it merged. Decisions were written down as they were made, so the reasoning outlived the people who made it.

Two revenue managers sat in every biweekly review, and the model's recommendations were shadowed against their manual decisions for six weeks before anything reached a live rate. That shadow period is where the confidence-band rule came from. The managers were consistently right in exactly the cases the model was least sure about, so those cases stopped being recommended at all.

One night, one rate

Why festival Saturday is 185, when last year it sold out at 142

One room type at one hotel, worked through: what the same Saturday did last year, the signals the model reads this year, and the move it recommends from them before a manager accepts or overrides it. Switch tabs, or use the arrow keys once one is focused.

The Wharf House · standard king · Sat 10/03/2026Bayside Folk Festival · 10/02–10/04
Sat 10/04/2025 · rooms on the books by days outRate $142 all the way
60d
45d
30d
24d
19d
14d
7d
Night
Festival Saturday, last yearA typical October Saturday
Full, and early24 days outAll 48 rooms sold at $142: $6,816 for the night, and every request after that turned away.

The spreadsheet set Saturday once a week, from the weekday pattern. The festival was on the city’s calendar, but not on the one the rate came from, so the hotel filled three weeks early at an ordinary Saturday price.

Architecture

From booking pace to a rate a manager accepts

Python and FastAPI over PostgreSQL, a Scikit-learn demand model, and a React cockpit with Recharts. The confidence band is computed at the model and carried unchanged to the screen where the rate is accepted or overridden.

  1. 01 · Source
    PMS, events, competitorsBooking pace, historical occupancy, a local events calendar and competitor rates arrive for every property in one feed, where there used to be one spreadsheet per hotel.
  2. 02 · Feature store
    Nightly table · PostgreSQLThree years of pace from four systems normalized into one row per room type per night, with a decided winner for every disputed night.
  3. 03 · Engine
    Gradient-boosted demand modelRetrained weekly on a rolling window with no engineer in the loop. Every prediction carries a confidence band; too wide, and nothing is recommended.
  4. 04 · Solve
    Portfolio yield optimizerSolves across the whole portfolio, holds each property's floor rate, and reports the cost of every manual pin monthly.
  5. 05 · Deliver
    Accept/override cockpitThe top drivers sit beside each rate. No live rate moves without an explicit accept; overrides are stored with a reason and fed back into training.
Before a rate reaches the channel

Explicit accept, stated confidence, floors that hold

Nothing goes live without an accept

Every recommendation waits for a manager to accept or override it. Overrides are first-class: stored with a reason, replayed into the next training window, and scored against the model after the stay.

Unsure nights get no recommendation

Each prediction carries a confidence band, and the cockpit withholds a recommendation when the band is too wide to act on. The rule came from the shadow period, where managers were right on exactly the nights the model was least sure about.

Floors hold, local control stays

The portfolio solve always respects each property's floor rate, and a manager can pin a property out of it. The cost of each pin is reported back monthly, and the pin stands.

Are your busiest nights still selling at a Tuesday price? Scope your build in 3 minutes.

Scope your build
Have a project?

Let's talk

Running a large platform, shaping a first MVP, or getting a product ready for a funding round? Tell us where you are. We'll shape the process around it, and stay with you after launch.