The applet requires Java 5 or higher. Java must be enabled in your browser settings. Mac users must have Mac OS X 10.4 or higher. Windows and Linux users may obtain the latest Java from Oracle's Java site.
powered by NetLogo
view/download model file: stock_market_with_multiple_agents.nlogo
The model aims at simulating a stock market populated by a set of agents equipped with realistic behaviours. To improve completeness, two other cathegories of agents are introduced: “moving average” agents and operators acting following their own market strategy.
A tick is a day of open market: every day each agent decides whether he is willing to buy/sell or if he prefers to stay put because of uncertainty (in this case dark gray colour is set).
If he will move, his buy/sell decision is taken randomly but strictly according to ambient levels of expectations, etc.
Then the market book is formed and bid/ask orders are collected and ordered like in real markets, and transactions are performed if and only if each bid order finds a (less or equal) counterpart or if each ask order finds a (grater or equal) bid offer.
In the interface, links are shown between each seller and buyer!
If an agent does not find his counterpart, he has to “pass”: in this case, light gray color is set!
Finally, in the world may exist two sets of agents that introduce “regularity” market strategies: moving average agents and “periodic” agents. As to them, buy/sell decisions are takes not randomly but according to their own speculating beliefs, and regardless to any ambient variable!
Intuition about ambient variables is really straightforward: the user shall decide several parameters about the world that he wants to simulate (real economy growth rate per year, expectations level, investment propensity, dividend pay-off rate, etc.).
Then, in order to check how (and how much!) “regular” agents affects market trends, the user may set higher or lower percentages of MA agents of “periodic” agents.
Two features really make the difference in this model.
First, the out-and-out realistic simulation of the bid/ask book: without a real and complete mechanism about stocks demand and supply, all outcomes of the model would have little explanatory power.
Second, random trend of the stock index if all ambient and agent variables are set to “neutral”: that means that no distortion is present in the code, i.e. all distortions shall be tested by the user.
Try to start with a “neutral” market.
Then, try to introduce slight improvements in real economy or shocks or booms.
Then, try to rise the “weight” of oriented-behaving agents, and check how real economy shocks are then enlarged or minimised.
In any case, try to often stop the forever go: you will have a daily “photo” of the situation with interesting outputs.
A good expantion to this model could be programming a mechanism that can improve or reduce (and then maximise) market liquidity (which is, in this model, relatively low due to small market population… with more agents netlogo starts working slowly!)
Starting point of this work is:
http://eco83.econ.unito.it/terna/simoec12/NetLogo_examples/f2_CDA_basic_model_movingAverage.nlogo
;; there is only a breed and several global/agent variables: all characterizations of agents are set as probabilities using random-float breed [randomAgents randomAgent] randomAgents-own[out-of-market buy sell stay pass offer cash stocks pricing Mael PPA] globals [logB logS exePrice volume gr rd gy dd bid %% asx MA pricelist II-MA days-MAlist price dailypricelist psi pss hyps hypb listcash liststocks totalcash totalcountervalue totalstocks totalwealth counter asklist bidlist] to setup ;; (for this model to work with NetLogo's new plotting features, ;; __clear-all-and-reset-ticks should be replaced with clear-all at ;; the beginning of your setup procedure and reset-ticks at the end ;; of the procedure.) __clear-all-and-reset-ticks set exePrice 100 set logB [] set logS [] set pricelist [] set listcash [] set liststocks [] set days-MAlist [] set counter holding-period set asklist [] set bidlist [] create-randomAgents nRandomAgents let side sqrt nRandomAgents let step (max-pxcor / side) ask randomAgents [ set shape "person" set out-of-market False set sell false set buy false set pass false set stay false set PPA false set Mael false set size 2 set stocks 1 set cash 150 set listcash lput cash listcash set liststocks lput stocks liststocks set totalcash sum listcash set totalstocks 100 set totalcountervalue (totalstocks * exePrice) set totalwealth (totalcash + totalcountervalue) ] set psi (count turtles with [cash > exePrice]) set pss (count turtles with [stocks > 0]) let an 0 let x 0 let y 0 while [an < nRandomAgents] [ if x > (side - 1) * step [set y y + step set x 0 ] ask randomAgent an [setxy x y] set x x + step set an an + 1 ] end to go ifelse (any? randomAgents with [out-of-market = False]) [tick] [] ;; this makes the market "stop" if all agents are dead ;show ticks ;NB in future implementation it would be interesting to make empty both the side of ; the market at regular intervals of more than one cycle ;; this counter is needed for "periodic" agents if counter <= holding-period [set counter (counter - 1)] if counter > holding-period [set counter holding-period] if counter = 0 [set counter holding-period] ;; clear all dailylists clear-links set dailypricelist [] set listcash [] set liststocks [] set asklist [] set bidlist [] ;; this calculates daily the MA ifelse length days-MAlist > days-for-IIMA - 1 [set days-MAlist filter [length days-MAlist < days-for-IIMA + 1] days-MAlist] [set days-MAlist days-MAlist] set logB [] set logS [] ;; here you have the three kinds of agents ask randomAgents [ if not out-of-market [ifelse stocks < 1 [set cash (0.001 + cash * (1 + (real-economy-growth-rate / 365)))] [ifelse real-economy-growth-rate > 0 [set cash ((dividend-rate * stocks) + cash * (1 + (real-economy-growth-rate / 365)))] [set cash (0.001 + cash * (1 + (real-economy-growth-rate / 365)))] ] ] ;; define Probability for PPA ifelse out-of-market [set color white] [ifelse random-float 1 < ratioPeriodicAgents/others [set PPA True if counter = holding-period [set sell True set buy False set PPA True ] if counter = (holding-period / 2) [set buy True set sell False set PPA True]] [set PPA False set pass False]] ;; define Probability for MAelements ifelse out-of-market or PPA or pass [] [ifelse random-float 1 < ratio-MAinvestors/others [ifelse II-MA > exeprice [set sell True set buy False set MAel True set stay false] [set buy True set sell False set MAel True set stay false]] [set MAel False] ] ;; finally, define mechanisms for "normal" agents ifelse out-of-market or MAel or PPA or pass [] [ifelse random-float 1 < Uncertainty [set stay True set color 2] [set stay False ifelse random-float (1.5 - expectations-rate) < InvestmentPropensity [set buy True set sell False set pass False] [set sell True set buy False set pass False]] ] ] ask randomAgents [set pricing abs (1 - (sqrt (10 * InvestmentPropensity))) if sell [set offer exePrice - (random-normal 2 sqrt pricing)] if buy [set offer exePrice + (random-normal 2 sqrt pricing)] if offer < 0 [set offer 0] if sell and stocks < 1 [set pass True set sell False set color gray] if buy and cash < offer [set pass True set buy False set color gray] set hypb (count turtles with [buy = true]) set hyps (count turtles with [sell = true]) if sell [set asklist lput offer asklist] if buy [set bidlist lput offer bidlist] if not stay and not out-of-market and not pass [ let tmp[] if buy [set tmp lput offer tmp] if sell [set tmp lput offer tmp] set tmp lput who tmp if buy [set logB lput tmp logB] set logB reverse sort-by [item 0 ?1 < item 0 ?2] logB ;show logB ifelse (not empty? logB and not empty? logS) and item 0 (item 0 logB) >= item 0 (item 0 logS) [set exePrice item 0 (item 0 logS) let agB item 1 (item 0 logB) let agS item 1 (item 0 logS) ask randomAgent agB [set stocks stocks + 1 set cash cash - exePrice] ask randomAgent agS [set stocks stocks - 1 set cash cash + exePrice] set logB but-first logB set logS but-first logS ] [set color gray set pass True] set volume (count turtles with [color = green]) if sell [set logS lput tmp logS] set logS sort-by [item 0 ?1 < item 0 ?2] logS ;show logS ifelse (not empty? logB and not empty? logS) and item 0 (item 0 logB) >= item 0 (item 0 logS) [set exePrice item 0 (item 0 logB) let agB item 1 (item 0 logB) let agS item 1 (item 0 logS) ask randomAgent agB [set stocks stocks + 1 set cash (cash - exePrice) set color green] ask randomAgent agS [set stocks stocks - 1 set cash (cash + exePrice) set color red create-link-with randomAgent agB] set logB but-first logB set logS but-first logS ] [set color gray set pass True] ] ] ask randomAgents [if not out-of-market and random-float 1 < out-of-marketLevel [if exePrice > 1 [set out-of-market False] if exePrice < 1 [set out-of-market True] ] if out-of-market [set color white] set volume (count turtles with [color = green] * 2) set gr (count turtles with [color = green]) set rd (count turtles with [color = red]) set gy (count turtles with [color = gray] + count turtles with [color = 2]) set dd (count turtles with [color = white]) set %% (count turtles with [color = green] / (count turtles with [color = gray] + 1 + count turtles with [color = 2])) set psi (count turtles with [cash > exePrice]) set pss (count turtles with [stocks > 0]) set listcash lput cash listcash set liststocks lput stocks liststocks ;; show ask and bid set asklist filter [? > exePrice] asklist set asklist sort-by < asklist set bidlist filter [? < exePrice] bidlist set bidlist sort-by < bidlist ifelse not empty? asklist [set asx first asklist] [set asx "#"] ifelse not empty? bidlist [set bid last bidlist] [set bid "#"] if (exePrice >= 50 and out-of-market) [set out-of-market False set pass True] ] ;; show some other outputs set dailypricelist lput exePrice dailypricelist set totalcash sum listcash set totalstocks sum liststocks set totalcountervalue (totalstocks * ((exePrice + II-MA) / 2)) set totalwealth (totalcash + totalcountervalue) set price last dailypricelist set pricelist lput price pricelist set MA mean pricelist set days-MAlist lput price days-MAlist set II-MA mean days-MAlist end to graph set-current-plot "Market values" plot exePrice end