Skip to content

Instantly share code, notes, and snippets.

@jweinst1
Created January 5, 2026 09:21
Show Gist options
  • Select an option

  • Save jweinst1/c9ce66cdac04a1aef790db9f8383e24d to your computer and use it in GitHub Desktop.

Select an option

Save jweinst1/c9ce66cdac04a1aef790db9f8383e24d to your computer and use it in GitHub Desktop.
Call Auction implementation with traders
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
struct Trader {
int id;
double cash;
int inventory;
};
struct Order {
Trader* trader;
bool is_buy;
double price; // limit price
int size; // quantity
};
// Run a single call auction for a turn
double run_call_auction(const std::vector<Order>& orders) {
std::map<double, int> demand; // price -> cumulative buy size
std::map<double, int> supply; // price -> cumulative sell size
// Step 1: aggregate orders by price
for (const auto& o : orders) {
if (o.is_buy)
demand[o.price] += o.size;
else
supply[o.price] += o.size;
}
// Step 2: create sorted unique price levels
std::vector<double> prices;
for (auto& [p, _] : demand) prices.push_back(p);
for (auto& [p, _] : supply) prices.push_back(p);
std::sort(prices.begin(), prices.end());
prices.erase(std::unique(prices.begin(), prices.end()), prices.end());
// Step 3: find clearing price (max volume)
double clearing_price = prices[0];
int max_traded = 0;
for (double p : prices) {
int buy_vol = 0, sell_vol = 0;
// cumulative buy at >= p
for (auto& [bp, bs] : demand)
if (bp >= p) buy_vol += bs;
// cumulative sell at <= p
for (auto& [sp, ss] : supply)
if (sp <= p) sell_vol += ss;
int traded = std::min(buy_vol, sell_vol);
if (traded > max_traded) {
max_traded = traded;
clearing_price = p;
}
}
// Step 4: execute trades
if (max_traded > 0) {
// Track remaining quantity per trader
std::map<Trader*, int> buy_remaining;
std::map<Trader*, int> sell_remaining;
for (auto& o : orders) {
if (o.is_buy && o.price >= clearing_price)
buy_remaining[o.trader] += o.size;
if (!o.is_buy && o.price <= clearing_price)
sell_remaining[o.trader] += o.size;
}
int total_buy = max_traded;
int total_sell = max_traded;
// Simple proportional allocation for partial fills
for (auto& [trader, size] : buy_remaining) {
int trade_qty = size * total_buy / std::max(total_buy, 1);
trader->cash -= trade_qty * clearing_price;
trader->inventory += trade_qty;
}
for (auto& [trader, size] : sell_remaining) {
int trade_qty = size * total_sell / std::max(total_sell, 1);
trader->cash += trade_qty * clearing_price;
trader->inventory -= trade_qty;
}
}
std::cout << "Clearing price: " << clearing_price
<< " | Volume: " << max_traded << "\n";
return clearing_price;
}
int main() {
Trader alice{1, 10000.0, 0};
Trader bob{2, 0.0, 100};
Trader charlie{3, 5000.0, 50};
// All orders generated in this turn
std::vector<Order> orders = {
{&alice, true, 101.0, 10},
{&bob, false, 101.0, 5},
{&charlie, false, 102.0, 10}
};
run_call_auction(orders);
std::cout << "\nTrader states after auction:\n";
std::cout << "Alice: cash=" << alice.cash << " inventory=" << alice.inventory << "\n";
std::cout << "Bob: cash=" << bob.cash << " inventory=" << bob.inventory << "\n";
std::cout << "Charlie: cash=" << charlie.cash << " inventory=" << charlie.inventory << "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment