Skip to main content

revmng

CI PyPI License: MIT

Revenue management for Python: the building blocks for selling fixed, perishable capacity well. Single-leg seat protection, overbooking, pricing, network bid prices and the standard performance metrics, computed from the textbook methods and validated against published worked examples.

The core has no third-party dependencies. Every result carries provenance (library version, input hash, timestamp) and a JSON-safe to_dict().

revmng framework: inputs (fares and demand, capacity, no-shows and costs) flow through the revenue-management methods (single-leg control with Littlewood, EMSR-a/b and the exact DP, overbooking, pricing, network bid prices, group and length-of-stay) into a result with provenance, over a measurement layer of RevPAR, yield, load factor and ROM

pip install revmng

Quick start

import revmng

# Two-class seat protection (Littlewood's rule)
revmng.littlewood(fare_high=1000, fare_low=400, mean_high=50, sd_high=18)
# -> protect this many seats for the high fare; sell the low fare below it

# Multi-class nested booking limits (EMSR-b, the industry-standard heuristic)
a = revmng.emsr_b(
    [(1000, 30, 12), (700, 40, 15), (400, 60, 20)],   # (fare, demand mean, sd)
    capacity=120,
)
a.booking_limits_int          # nested whole-seat booking limits
print(a.summary())

# Overbooking: balance the cost of bumping against the cost of empty seats
o = revmng.overbooking_limit(100, no_show_rate=0.12,
                             denied_cost=400, spoilage_cost=180)
o.authorization_limit         # how many reservations to accept

# Pricing: the newsvendor stocking quantity and the profit-maximising price
revmng.newsvendor(price=10, cost=4, demand_mean=100, demand_sd=30).optimal_quantity
revmng.optimal_price(revmng.LinearDemand(intercept=100, slope=2), unit_cost=10)

# Score booking limits against perfect-hindsight and no-control benchmarks
revmng.revenue_opportunity([1000, 800, 600, 200], [25, 30, 20, 50], capacity=100,
                           booking_limits=[100, 70, 45, 32]).rom

# Exact optimal protection levels (and the expected revenue EMSR leaves behind)
opt = revmng.optimal_protection_levels(
    [(1000, 30, 12), (700, 40, 15), (400, 60, 20)], capacity=120)
opt.expected_revenue

# Should we take this group? (displacement analysis)
cost = revmng.group_displacement(group_size=30, capacity=100,
                                 demand=[70, 95, 85], value_per_unit=70)
revmng.evaluate_group(group_rate=60, units=90, displacement_cost=cost,
                      variable_cost=50).accept

# Should we accept this multi-night stay? (length-of-stay bid-price control)
revmng.evaluate_stay({"Mon": 80, "Tue": 120, "Wed": 90},
                     ["Mon", "Tue", "Wed"], total_rate=320).accept

Network bid prices need SciPy and the charts need matplotlib:

pip install "revmng[network]"   # bid_prices via the deterministic LP
pip install "revmng[plot]"      # booking-limit, overbooking and ROM charts
from revmng import Product
n = revmng.bid_prices(
    [Product(fare=200, uses={"AB": 1}, demand=60),
     Product(fare=300, uses={"AB": 1, "BC": 1}, demand=40)],
    capacities={"AB": 100, "BC": 100},
)
n.bid_prices                       # marginal value of each resource
n.accept(fare=250, uses={"AB": 1, "BC": 1})

What it covers

Area Functions
Single-leg capacity control littlewood, emsr_a, emsr_b
Exact optimal control optimal_protection_levels, policy_revenue
Overbooking overbooking_limit (service level and cost based)
Pricing newsvendor, optimal_price (LinearDemand, ConstantElasticityDemand)
Group evaluation evaluate_group, group_displacement
Length-of-stay evaluate_stay
Performance metrics revpar, adr, occupancy, yield_, load_factor, rasm, casm, spill, spoilage
Revenue opportunity revenue_opportunity, nested_revenue
Network (needs SciPy) bid_prices, Product
Charts (needs matplotlib) booking_limit_chart, emsr_curve, overbooking_cost_curve, price_curve, newsvendor_curve, revenue_opportunity_chart, bid_price_chart

optimal_protection_levels computes the exact optimal nested protection levels by dynamic programming (the policy the EMSR heuristics approximate) and reports the optimal expected revenue; policy_revenue scores any policy against it. Group and length-of-stay decisions share one idea: accept a request when its contribution covers the opportunity cost of the capacity it displaces (a marginal seat value or a sum of nightly bid prices).

Demand for the capacity-control methods is assumed normal and independent, with the classic low-before-high booking assumption. EMSR-a and EMSR-b are heuristics; for two classes both reduce to Littlewood's optimal rule.

What is out of scope

revmng computes decisions from the demand you supply. It does not forecast demand, estimate willingness-to-pay, or unconstrain censored bookings, and it does not connect to any reservation, property-management or distribution system. Those belong upstream; keeping them out is what lets every result here be reproduced and audited.

Validation

The methods are checked against published and hand-derived worked examples (see tests/validation_cases.json):

Method Source Result
Littlewood booking limits Phillips, Pricing and Revenue Optimization (2005), Ex. 9.2 25 / 50 / 76 reproduced
Revenue opportunity metric Phillips (2005), Ex. 9.7 perfect 66000, no-control 46000, realized 59200, ROM 66%
EMSR-b (two classes) Belobaba (1989) equals Littlewood's optimal rule
EMSR-b (three classes) Belobaba (1989) formula, arithmetic shown protection 23.71 / 70.83, limits 97 / 50
Optimal control (DP) Talluri and van Ryzin (2004) matches Littlewood for two classes; expected revenue at least EMSR-b's

A clean multi-class EMSR-b worked example with both inputs and outputs is hard to find in the open literature, so the heuristics are also cross-checked two independent ways (tests/test_crosscheck.py): their protection levels match a separate SciPy implementation of the same formulas to 1e-9, and over many random instances EMSR-b never exceeds revmng's exact dynamic program and stays within about 0.5% of it, matching Belobaba's reported near-optimality. | Group displacement | standard displacement analysis, arithmetic shown | 40 displaced room-nights, cost 2800, break-even rate 81.11 | | Length-of-stay bid price | Talluri and van Ryzin (2004), arithmetic shown | 290 hurdle, accept at rate 320 | | Newsvendor quantity | critical-fractile rule | reproduced | | Overbooking (service level) | deterministic no-show formula | reproduced |

Definitions and methods

  • K. Littlewood, "Forecasting and control of passenger bookings" (1972).
  • P. Belobaba, "Application of a probabilistic decision model to airline seat inventory control," Operations Research (1989). EMSR-a and EMSR-b.
  • K. Talluri and G. van Ryzin, The Theory and Practice of Revenue Management (2004).
  • R. Phillips, Pricing and Revenue Optimization (2005).

License

MIT. Written and maintained by Atakan Arikan, MSc Student at Tsinghua University and Politecnico di Milano.

Metadata

Release files for revmng 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for revmng 0.2.0
File Size Uploaded Provenance Actions
revmng-0.2.0.tar.gz 34.6 kB With provenance Details for revmng-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for revmng 0.2.0
File Interpreter ABI Platform Actions
revmng-0.2.0-py3-none-any.whl Python 3 none any Details for revmng-0.2.0-py3-none-any.whl

Total release size: 65.5 kB

Release files / revmng-0.2.0.tar.gz

Download URL revmng-0.2.0.tar.gz
Size 34.6 kB
Tags Source
SHA-256 checksum
How to use checksums
c47d946eff1acea4653cba5a903002afaebee5413ba48d9f320476ea6a1e3725
BLAKE2b-256 checksum
How to use checksums
802a7257f07cdac322416fb52838e195d5a4872c12e47821cedbffccf3466a94
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.

Transparency log

Release files / revmng-0.2.0-py3-none-any.whl

Download URL revmng-0.2.0-py3-none-any.whl
Size 30.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6ff1910085e736e23efa7b90e472df007e6ef172b846f5d40b1bb9d12132dd46
BLAKE2b-256 checksum
How to use checksums
c89070ca7028512295c7bba1090f84820392de8dbc9b78e5944a29e445057c95
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.

Transparency log

Security for revmng 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for revmng-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jun 16, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page