One of the best ways to learn about something is to build it. When you build
something for the first time you are forced to think of intimate details that
you might not have thought of in advance, because it’s something that is
strange or counter-intuitive but absolutely essential to how that thing
functions. Repeatedly you will stumble across several seemingly minor details
and are forced to stop for a moment to think about how you’re going to tweak
things to incorporate them. Sometimes this will only require some minor changes,
but other times it will require a major rethink on how you’re doing what you’re
doing.
As part of this series, we’re going to take this idea and apply it to building
an economy. Over the course of several tutorial posts, we’re going to outline a
design to build an economy on the computer, write the code that will follow the
rules in our design, and run it to see what happens. We’ll create some output
using a database, from which we can construct charts and run statistics to have
an idea on what is going on inside our new virtual world. Through this,
hopefully we’ll learn all sorts of interesting things about economies that we
may not have known already, either because it came out of the simulation, or we
had to do some research into existing work to see how other people have solved
this problem in the past.
On the way, in addition to learning plenty about economics, we’ll become quite
familiar with the tools we use to build the economy: computer programming,
software engineering, and mathematics. These on their own are very interesting
and useful tools, so it’s worth the exercise even if we aren’t particularly
concerned about the economics side of things.
I hope you enjoy this journey, and learn plenty along the way!
Before we get started building any sort of more complex economy, the first thing
we’ll want to do is confirm that it actually works by comparing the results of
a simple virtual economy with what economic theory predicts will happen. We’ll do this
by writing out a mathematical model of a very simple economy using standard
economic theory, and see what sort of results it gives out. This will give us a
prediction on what we’d expect to see, and then we can compare what we get from the
simulation. If they match up then we have a good idea that our simulation works
well, and we have more faith in it as we scale it up to larger economies. If
they don’t match up it will probably indicate that we have a bug, but it could
also point to something interesting in the way we’re doing our simulation.
As mentioend, this first version of our economy is going to be very simple, since as we scale
up we probably won’t be able to do the same mathematical analysis - the number
of variables and equations makes solutions impossible to find very quickly.
Over time we’ll add complexity to add more interesting ideas, but because we
started from a solid mathematical base and tested each step thoroughly, we can
have a reasonable assurance that we didn’t make a mistake somewhere.
Let’s start off by describing our mathematical model of the economy. Imagine a
very basic economy where we have some firms and some workers. We’ll say that in
this imaginary economy, firms produce a good: biscuits. The firms own the means
of production (the ovens) but don’t know how to actually make the biscuits,
where the workers know how to make them but don’t have ovens and have no
possibility of getting them. Firms pay their
workers in biscuits instead of with money (which doesn’t exist in this fictional
world).
This means that workers don’t actually have much thinking to do. They just work.
The whole process is determined entirely by the firms, who have some sort of
profit maximizing objective:
\begin{equation}
\max_L \pi(w) = Q(L) - wL
\end{equation}
Given a market wage $w$, the firm chooses the amount of labour $L$ that they
hire in order to produce a
certain amount of goods, determined by a production function $Q$. For simplicity
we can just use the standard Cobb-Douglas production function:
\begin{equation}
Q = AL^\alpha
\end{equation}
Here $A$ is a technology multiplier, and $\alpha$ is a factor that
determines the returns to scale of labour. We’ll want to restrict this to be
between 0 and 1,
which means that as you add more labour you get more quantity but the amount
you get for each additional person declines over time (aka diminishing marginal
product of labour).
Lastly, we’ll say that our economy is finite. There are $F$ firms and $N$
workers in our world.
This gives us our labour supply and demand curves:
\begin{equation}
L_s = N
\end{equation}
\begin{equation}
L_d = F\left (\frac{w}{A\alpha} \right )^{\frac{1}{\alpha - 1}}
\end{equation}
In equilibrium, we get the following for the market wage:
\begin{equation}
w = A\alpha\left (\frac{N}{F}\right)^{\alpha - 1}
\end{equation}
The workers should be evenly distributed among the firms, there will be
$\frac{N}{F}$ workers per firm.
Note that there is one degenerate case here: profits should never be negative,
or firms will not demand any labour at all. In a Cobb-Douglas world it is never
possible for profits to be negative unless $\alpha$ > 1, which is ruled out by
assumption.
Now that we have our prediction, we can build our economy and see if it lines up.
The first thing we have to think about now that we didn’t have to in the
mathematical analysis is: how do we get to equilibrium? Instead of just plugging
the formula into the code which would make for a very boring simulation but also
very unscalable to more complicated models, we want to have each agent make their
own decisions and hope that we’ll arrive at the same value. We’ll have to come
up with some sort of decision process that each agent follows.
The next thing we’ll have to think about is how do firms and workers connect
with one another? From the mathematical analysis it’s easy for us to say that
each firm will have $\frac{N}{F}$ workers, but we have no idea how those workers got
there in the first place. We’ll have to build some mechanism for matching
workers with firms.
Lastly, we’ll have to think about time. The mathematical analysis assumes we’re
in equilibrium, which means that time doesn’t actually matter any more - the
system has settled to a stable state, and all time after that point is the same.
In our simulation though we aren’t going to start off in equilibrium, so we’ll
need to think about how things change over time from the initial state to when
it settles to equilibrium.
We’ll address the issue of time first, since it’s the easiest. We’ll just
split up time into discrete steps, call them “days”. Each day all firms and
workers will make their decisions, and absolutely none of them will be binding
the next day - workers will not stay at a firm. This simplifies things because
firms won’t have to decide about firing workers, and workers won’t have to
decide about finding a new job.
Next we’ll decide how firms and workers get matched up with one another.
There are many ways we can do this, but for this model we’ll use a market
mechanism. It’s a relatively simple but flexible mechanism that we’ll be able
to re-use when we start making our economy more complex.
This market will be a double auction modelled off of the stock market: workers
(the sellers of labour) submit the
minimum wage that they are willing to work for, and firms (the buyers of labour)
submit the maximum
wage they are willing to pay and the amount of workers they want to hire. This
will potentially result in an overlap in wage values, so the market will
match all the workers and firms who are in that overlap and notify them using
a callback mechanism to say that they were matched. The market will track the
high $w_h$ and the low $w_l$ of the overlap and expose those values for firms and workers
so they can use them in future decision processes; ideally in equilibrium
the high and low values will converge to a value that we can call the market
wage.
Lastly, the decision processes of firms and workers.
Workers are very simple: they are trying to get the highest wage possible while
remaining employed. If the agent was unemployed last round, it will try to
guarantee itself a job by undercutting the market and offer a wage equal to
$w_l - \tau$ ($\tau$ being an adjustment factor, provided as a parameter to the
simulation). If they were employed then it’s possible they offered too low a
wage, so they will offer $w_h$ as their wage.
Firms are slightly more complex because they are looking to fill a number of
workers rather than just a single one, and are optimizing over a curve instead
of a binary value. So firms will first decide on a wage to offer the market. A
firm that did not get enough employees last period will try to lure workers from
competitors by offering a wage of $w_h + \tau$; a firm that satisfied its
requirements last period will attempt to offer $w_l$.
Based on the chosen wage, the firm knows they can maximize their profits by
using the individual labour demand function, so this will result in the number
of workers to hire (with a few exceptions, they need to submit discrete values
so they’ll choose the value of $floor(L)$ and $ceil(L)$ that maximizes profits).
There is one degenerate case for firms: if the wage they decide on results in
them making negative profits, they will instead choose to hire no workers. In
this model this should theoretically never be the case, but we’ll add it to the
code anyway for two reasons: (1) we’re not 100% sure what will happen outside of
equilibrium, so adding this condition avoids going off into non-sensical
outcomes; and (2) as we make our models more complex this could become a
realistic outcome for some firms, so we can add it now so we don’t forget to
add it later.
We now have an outline for a simple virtual economy. The next few articles
we’ll actually be writing some code for these, which will lay some framework
for future simulations. Lastly, we’ll define a way we can extract results from
this model and compare to the mathematical version. I’m looking forward to it!
Now we’re going to describe how we’ll build our markets. Before we get started
though, I’d like to distinguish two concepts in our simulations. The first
element is an agent, which is an entity in our simulation that attempts to
make an intelligent decision to accomplish some kind of goal. Individuals
attempt to maximize their utility/happiness, firms attempt to maximize profits,
governments attempt to maximize…something. Contrast with the second concept,
a mechanism, which is an element that simply follows a set of mechanical
rules. An example of this is the double-auction market that we’ll describe in
this article; it simply accepts orders and in all cases it follows a set of
well-defined rules. It does not have any sort of objective.
It’s important to distinguish this because our simulations are decentralized:
there is no auctioneer or benevolent overlord guiding the system. We expect to
see a true invisible hand at work. If we had some sort of agent managing the
interaction between other agents, then we don’t really have a decentralized
system.
Now with that out of the way, let’s talk a bit about double-auction markets.
These are markets where participants submit orders to buy or sell a certain
quantity of a good with a certain price called the limit price. As the market receives these
orders, it will compare them to the existing orders it has received and execute
a match if possible. It will then notify both the buyer and the seller of a fill
which says that the owner has traded a certain amount at a certain value.
Let’s run through an example. There are some existing orders already placed in
the market; one buy order at $\$$5, a sell order at $\$$5.50, and a sell order at $\$$6.
In this case the bid, the highest buy order price, is $\$$5; and the ask, the
lowest sell order price, is $\$$5.50.
Suppose someone comes along and submits a buy order with a limit price of $\$$5.51.
Since this is greater than the ask, the order will execute with a price of $\$$5.50
(the price is based on the order that was already in the market). What happens
next depends on the sizes of the orders. If the buy order has a greater size
than the sell order then the entire sell order will be filled, the buy order
will be partially filled, the new bid will be $\$$5.51, and the new ask will be $\$$6
to match the sell order remaining in the market. If the sell order has a greater
size, then the buy order will be completely filled, the sell order will be
partially filled, and the bid/ask prices will remain the same. If the sizes
are equal, then both orders will be filled and the new ask will be $\$$6.
The way we’ll implement this is with two heaps: one for buy orders and one for
sell orders. These heaps will be indexed by the price of the orders. When each
order comes in, we’ll check against the heap containing the opposite types of
orders, and pop orders off and fill them until we either no longer have a price
overlap, or the size of the new order has been reduced to zero. As mentioned
earlier, there will be a callback that is sent to the owner of each order to
let them know they have been filled.
That’s it for the primary logic of the system. There are a few edge cases that
we haven’t talked about, those are handled in the code and you’re welcome to
browse that if you want to know more details. We’ll move on now to how we’re
going to code this up.
The code is in two Git repositories called econerra
and econerra-main, which is the name
I’ve given the virtual economy we’re playing with. The code is written in the Go
programming language, a newer language that makes a good trade-off between
performance (much faster than Python, Matlab) and ease-of-use (much easier to
use than C++, Java, Fortran).
The econerra-main
repository is the one where you run things, it will contain
all the infrastructure and tools for the project. The actual agents and things
are in the econerra
repository.
You can run the project easily enough, however you’ll want to follow the
instructions for the baseline-2019-03-09
tag since this repo will be liable
to change over time as I play around with new ideas. The code for the double
auction market is here.
Enjoy!