Auction mechanisms¶
A mechanism decides how bids are collected and how ranked bids become awards and payments. Ranking is delegated to a selection policy. All built-in mechanisms are reverse auctions (agents compete to sell work to a buyer). Bids that fail validation (over budget, deadline infeasible, below the required quality, malformed) never reach the mechanism.
Statements below about incentives hold only under the stated assumptions. AuctionSI does not claim that any mechanism is truthful or optimal in general.
first_price_reverse — sealed-bid, pay-as-bid¶
- Rules: every eligible agent is asked once, in agent-id order, and sees no other bid. The top-ranked valid bid wins.
- Payment: the winner's own price.
- Inputs/outputs: valid bids, policy, features → ranking, one award.
- With
LowestPrice: the lowest valid bid wins (ties: earlier bid, then agent id). - Advantages: simple, predictable buyer cost.
- Limitations / strategy: a profit-seeking bidder has an incentive to bid above its cost ("shading"); how much depends on what it believes about rivals.
second_price_reverse — sealed-bid, critical-value payment¶
- Rules: as first-price.
- Payment: the winner's critical value: the highest price at which it would
still rank first with all other bids fixed, capped at the task budget. With a
price-only policy this is the runner-up's price. With other policies it is found
by bisection, assuming the score never rises when only the price rises (true of
every built-in policy). With one valid bid,
single_bid_payment="reserve"pays the budget (if any),"bid"pays the bid. Payment is never below the winner's bid. - Incentives: in the textbook setting (one task, one winner, price-only ranking, each bidder's cost private and independent, quasi-linear utility, a single one-shot sealed round, no effect of this auction on future auctions or reputation), bidding one's true cost is a weakly dominant strategy. In AuctionSI these conditions often fail: reputation links auctions together, failures are penalised, and multi-dimensional scores make the bid more than a price. Treat the property as a hypothesis to test, not a guarantee.
- Limitations: with bidders that do not adapt their strategy, buyers simply pay
more (see
research/results/mechanisms).
multi_winner_reverse — k winners¶
- Rules: sealed; the top
winnersbids win, one award per agent. - Payment:
pay_as_bid(own price) oruniform(every winner gets the best losing price, i.e. the (k+1)-th price; the budget or own price if nobody lost). Uniform pricing is only allowed with price-only policies. - Incentives: the uniform (k+1)-th-price rule is the multi-unit analogue of second price when each agent wants at most one unit; the same caveats apply.
- Execution: one contract per winner; recovery applies per slot.
open_reverse — descending open auction¶
- Rules: after a sealed round 0, agents see the standing best price each round
and may lower their own bid (
Agent.revise_bid). Revisions must lower the price. Agents without a bid may enter late. Stops after a round with no accepted revision or aftermax_rounds. Every revision is recorded (BidRevisedevents,Bid.revision). - Payment: pay-as-bid on final bids.
- Strategy: bidders learn about rivals during the auction; outcomes depend on
revision strategies (
BidStrategy.reviseundercuts by 2% down to a floor).
Writing a mechanism¶
from dataclasses import dataclass
from auctionsi.mechanisms import AuctionMechanism, Award, MechanismOutcome
@dataclass(frozen=True)
class FirstPriceExample(AuctionMechanism):
name = "my_mechanism"
def determine_winners(self, bids, task, policy, features):
ranking = policy.rank(bids, task, features)
if not ranking:
return MechanismOutcome([], [], ["no valid bids"])
top = ranking[0]
return MechanismOutcome(ranking, [Award(top, top.bid.price, 0, "pay-as-bid")])
from auctionsi import Marketplace
market = Marketplace()
market.register_auction_mechanism("my_mechanism", FirstPriceExample)
Rules for mechanisms: be deterministic given the inputs (replay depends on it),
never award an invalid bid, document payment rules in payment_rule, and override
collect_bids only if you need a different collection protocol.
forward — agents bid to buy¶
- Rules: sealed; the task describes what is on offer and
Task.reserve_priceis the minimum acceptable bid (lower bids are rejected withBELOW_RESERVE). The highest bid wins. Ranking is by price only; the selection policy is not used. - Payment:
pricing: firstcharges the winner its bid;pricing: secondcharges the larger of the runner-up bid and the reserve (Vickrey for one item under private values, single shot). - Settlement: contracts and settlements carry
direction: forward; buyer cost is negative (the market receives money) and no refund applies.
bundle_reverse — combinatorial procurement¶
- Rules: the task lists items in
requirements["items"]; each bid covers the items interms["items"](all items when absent). Winner determination picks the non-overlapping set of bids that covers every item at the lowest total price, solved exactly by dynamic programming over item subsets (capped atmax_items, default 12). Ties are broken by the policy ranking. - Payment: pay-as-bid, one contract per winner.
- Incentives: pay-as-bid bundle auctions invite strategic bundle pricing; no incentive property is claimed.
capacity — reserving future work¶
- Rules: the task asks for
requirements["units"]units (e.g. 100 tasks next hour). A bid'spriceis per unit andcapacity(orterms["units"]) is the units offered. Units are filled from the cheapest offers up; the last winner may be partially filled.Award.quantityrecords the units reserved. - Payment:
pricing: pay_as_bid(own unit price) oruniform(the first rejected unit price, or the budget per unit / own price when supply runs out).