Paolo Giani

Simulation models for economics

Project work on

"Stock market with multiple agents."

 

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.


Here you can find an introduction to the Stock market with multiple agents application.


powered by NetLogo

view/download model file: stock_market_with_multiple_agents.nlogo

WHAT IS IT?

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.

HOW IT WORKS

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!

HOW TO USE IT

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.

THINGS TO NOTICE

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.

THINGS TO TRY

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.

EXTENDING THE MODEL

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!)

CREDITS AND REFERENCES

Starting point of this work is:
http://eco83.econ.unito.it/terna/simoec12/NetLogo_examples/f2_CDA_basic_model_movingAverage.nlogo

CODE

;; 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