Julia wrapper for ABIDES-Markets: a J.P. Morgan Chase's multi-agent discrete event simulator specialised for financial markets.


Preliminary setup

This package uses PyCall to load ABIDES within Julia. Therefore, the ABIDES should be installed in the Python version being used by PyCall. On Mac and Windows systems, PyCall will use Conda to install a separate version of Python that is private to Julia by default. This version of Python has minor incompatibilities with the dependencies and it is therefore easier to switch to a different one in which ABIDES is correctly installed. This can be done by running:

ENV["PYTHON"] = "... path of the python executable ..."
import Pkg; Pkg.build("PyCall");

On GNU/Linux systems, PyCall will default to using the python3 program (if any, otherwise python) in your PATH. Thus, as long as this version of Python has ABIDES installed, the previous lines of code should not be necessary.

Package installation

Having setup PyCall, AbidesMarkets can then be installed with the Julia package manager. From the Julia REPL, type ] to enter the Pkg REPL mode and run:

pkg> add AbidesMarkets

Or, equivalently, via the Pkg API:

julia> import Pkg; Pkg.add("AbidesMarkets")


The following example shows how to replicate in Julia the official demo for ABIDES-Markets:

# Dependencies
using AbidesMarkets;
using DataFrames, DataFramesMeta, Dates, Plots, Statistics;

# Build runnable configuration
config = AbidesMarkets.build_config("rmsc04", (seed=0, ));
println(sort(collect(keys(config)))); # <- show keys in `config` in alphabetical order

# Run simulation
end_state = AbidesMarkets.run(config);

# Retrieving results from `end_state`
order_book = end_state["agents"][1].order_books["ABM"]; # Julia starts indexing from 1, not 0

# Get L1 snapshots
L1 = AbidesMarkets.get_L1_snapshots(order_book);

# All times are in ns from 1970, this loop converts them to a more readable format
best_bids_time = Time[];
best_asks_time = Time[];
for i in axes(L1.best_bids, 1) # same as best_asks by default
    # x*1e-9 converts ns to seconds, the remaining part of the conversion is performed with the Dates library functions
    push!(best_bids_time, Time(unix2datetime(L1.best_bids[i, 1]*1e-9)));
    push!(best_asks_time, Time(unix2datetime(L1.best_asks[i, 1]*1e-9)));

# Generate plots for L1 output
fig = plot(best_bids_time, L1.best_bids[:, 2], linecolor=:orange, label=nothing);
plot!(fig, best_asks_time, L1.best_asks[:, 2], linecolor=:steelblue, label=nothing);
ylims!(fig, 100000-100, 100000+100);

# Order book history L2
L2 = AbidesMarkets.get_L2_snapshots(order_book, 10);

# Generate plots for L2 output (plotting fifth best bid and fifth best ask)
fig = plot(scatter(L2.times, L2.bids[:,5,1], markersize=2.5, markerstrokewidth=0, markercolor=:orange, label=nothing));
scatter!(fig, L2.times, L2.asks[:,5,1], markersize=2.5, markerstrokewidth=0, markercolor=:steelblue, label=nothing);
ylims!(fig, 100000-100, 100000+100);

L2_bids_avg, L2_bids_avg_times = aggregate_LOB_measurement_avg(L2.bids[:,5,1], L2.times, Minute(1));
L2_bids_eop, L2_bids_avg_times = aggregate_LOB_measurement_eop(L2.bids[:,5,1], L2.times, Minute(1));