An application for running double auction markets with customizable auction clearing mechanisms.
Buy and sell offers can be arbitrary terms as long as you provide a
module implementing the gen_market
behaviour to handle them. If you
don't want to implement your own market clearing algorithm byrslr
provides a default market mechanism that operates on {Quantity, Price}
tuples as offers.
The application supports periodic markets that restart at a fixed interval, as well as purely event-driven markets. You can also run as many concurrent markets as you want.
The architecture of the market is inspired by the market agent in VOLTTRON. Before making either a buy or a sell offer, market participants must declare their intent by making a buy/sell reservation. Reservations are assigned a unique Id that must be used when making an offer. Once offers are received corresponding to every reservation the market is automatically cleared.
To create an event-driven market with the default double-auction clearing algorithm:
byrslr:new_market(foo, []).
A market with a 5 minute cycle and a 120 second delay before accepting offers.
byrslr:new_market(foo, [{market_period, 300000}, {reservation_delay, 0}, {offer_delay, 120000}]).
Assuming the module bar
implements the gen_market
behavior, you
can specify that bar
should be used to clear the market like so:
byrslr:new_market(foo, [{market_impl, bar}]).
Optionally, extra data can be provided that will be passed to the
clear
callback along with the lists of buy and sell offers.
byrslr:new_market(foo, [{market_impl, bar},
{market_data, #{import_tariff => 1000, export_tariff => 800}}]).
To subscribe to be notified when market events occur (e.g. starting to accept reservations/offers, cleared, opened) use
byrslr:join_market(foo).
Once subscribed the calling process will receive messages of the form
{gen_market, Event}
.
For event-driven markets use the following functions to trigger events that drive the market.
%% open the market, clearing previous bids and offers and starting a new bidding round
byrslr:start_new_cycle(foo).
%% these are pretty self-explanatory
byrslr:start_accepting_reservations(foo).
byrslr:start_accepting_offers(foo).
$ rebar3 compile