Skip to main content
DoneThat

AI Adoption GuideHospitalityBook

Dynamic demand-based pricing

ML model adjusts room rates in real time using demand signals, booking window, and comp set data, using tools like Duetto or IDeaS.

Hospitality processBookConfirmPrepareArriveStayDepartReviewReturn

By Don, DoneThat’s AI coach · updated

A suggested rate is unpublished until it cites three things

The usable output of demand-based pricing is not a live BAR. It is a suggested rate for a locked stay date and room type, with three citations attached: the demand signal, the booking window used for that stay date, and the vintage of the competitive-set file. If any cite is missing, the cell stays empty. Empty is a valid result. It means the model declined to invent a number.

Hotel teams get into trouble when a recommendation from a revenue-management or property system looks finished. Duetto, IDeaS, Oracle Hospitality, and Mews sit in this class: they can surface a recommended rate inside the workflow you already use to sell rooms. That recommendation is still an input. A revenue manager with rate authority has to publish before the selling rate changes. Treating the suggestion as published is how a property sells a number nobody approved.

Quality for this page is deliberately narrow. You are not asking the model to forecast how full the house will be, to fill holes in a pickup chart, or to invent occupancy where the feed is quiet. You are asking it to attach a rate only to evidence that already exists, and to refuse when that evidence is incomplete.

Lock the stay-date grid before anything scores

Score only the grid you froze. Stay dates, the room types or rate categories you actually sell, and restrictions already in force (closed to arrival, closed to departure, minimum or maximum length of stay) must be fixed before the model runs. If the grid can still move, you will get a suggested rate for a product you are not selling that night.

The sequence is review nights first, then freeze, then score. Do not run an open horizon and cherry-pick cells afterward. A festival Saturday and the Tuesday after it are different products. Mixing them in one pass hides which citation belongs to which night.

Restrictions belong in the freeze, not in a note after publish. If a date is already closed, the model should not propose a BAR as if the date were open. If a length-of-stay rule is in force, the suggestion must respect it or leave the cell blank with a cite that the restriction blocked pricing.

Keep capacity decisions out of the rate cell. Walk risk and overbooking policy are a different control. They belong with the overbooking risk scorer, not as a silent lift or cut to BAR.

Score each cell with demand, booking window, and competitor vintage

Every non-empty cell needs three cites a colleague on the next shift can audit without opening a ticket.

Demand signal: name the feed and the timestamp. That might be on-the-books pace for that stay date against a comparable window, a group block that just released, or a citywide event row. Do not convert a thin signal into a made-up occupancy figure. If you only know that booking velocity changed, cite the velocity change. If you do not know how full the house is, do not write a number that implies you do. Inventing occupancy is how a rate looks rigorous when the occupancy figure was never observed.

Booking window: state how far the stay date sits from today, and which lead-time bucket the model used. A same-week transient night and a stay ninety days out are not interchangeable, even when the competitive set looks similar.

Competitor vintage: record when the competitive-set rates were last captured and which set was in force. A suggested rate with no vintage is not a complete suggestion. Comp rates from this morning and comp rates from last week are different evidence. If the file is stale, do not paper over it with a BAR. Leave the cell empty and say why. Refreshing the set is competitor rate intelligence, not a silent overwrite inside pricing.

Write the three cites in the same place every time: rate code, stay date, room type, then demand, window, and vintage. If the comment field truncates, keep a matching line in the daily RM log for that date. Do not store a cite that points at a file you cannot retrieve. Treat the RMS or PMS recommendation as the number to annotate, not as proof the three cites exist.

Thin evidence means the cell stays blank

Shoulder dates with no event, a competitive-set extract that failed overnight, or a booking window with too few comparable observations should produce a blank, not an interpolated BAR.

Blank means: do not sell a new number, and do not backfill from last year's same weekday as if that were a cite. Last year is a different demand regime unless you explicitly document it as the demand signal and accept that choice. Most of the time it is not.

When the cell is blank, the live rate stays whatever was already published. Completeness of the grid is the wrong quality metric. Traceability is the right one. Filling holes so the RMS looks finished is how invented occupancy and missing vintage sneak in.

One walk-through: a revenue manager locks next month's Thursday through Sunday for standard king, with existing length-of-stay rules left in place. The model returns a suggested BAR for Friday and Saturday. Each of those cells names a pickup acceleration in the current booking window and a competitive-set file from that morning. Thursday returns blank because the competitive-set extract did not land, so vintage is missing. Sunday returns blank because the demand feed shows no material change and the remaining observations in that lead-time bucket are too few to treat as a signal. The manager does not type an occupancy guess into Thursday to complete the week. Friday and Saturday go to the publish queue. Thursday and Sunday stay on the last published BAR until a new extract or a real demand cite appears.

Publishing is a revenue-manager action

Publish is a named human step. It is not implied by a recommendation sitting in the RMS. Auto-loading suggestions into the selling rate is the same failure as treating the suggestion as published: guests see a number that never had a decision attached.

The publish step is also where you reject a well-cited suggestion for reasons the model cannot see: an owner mandate, a contracted rate that must remain the public floor, a brand BAR rule, or a group conversation already in flight. Those reasons belong in the decision note. Do not disguise them as demand cites.

After publish, anything that quotes a rate to a guest must read the published rate, not the suggestion queue. A conversational booking agent that recites a pending recommendation will sell a number that is not live.

Guest mix can inform which rate plan you attach the BAR to, but segmenting intent is upstream of this page. The demand-based suggestion still needs the three cites. Use the guest segment intent classifier for mix. Do not let a segment label stand in for vintage or for a demand feed you do not have.

Pricing should not absorb shopping, walks, or the guest quote

This use case produces a cited suggestion on a frozen grid. It does not replace competitive shopping, overbooking decisions, or the guest-facing booking conversation. The shopping job keeps vintage honest. The walk-risk job keeps inventory policy off the BAR. The guest quote must follow what you published, not what the model proposed.

If those neighboring jobs are weak, do not compensate by letting the pricing model invent occupancy or skip vintage. Fix the feed, then rescore the locked nights. The revenue manager still publishes.

Is this worth automating for you?

Whether this pays back depends on how much time it takes your team today. Most teams estimate that from memory, and the estimate is usually wrong in one direction or the other. This one is rated high effort to implement, so the baseline matters more than usual.

DoneThat reconstructs where the time actually went, with no timers to forget, so you can measure the baseline before committing to a project and check the gain afterward.

Measure the baseline first