Bulls and Bears

Bulls and Bears preview image

1 collaborator

Default-person Franco Busetti (Author)

Tags

price formation 

Tagged by Franco Busetti 19 days ago

stock market 

Tagged by Franco Busetti 19 days ago

Visible to everyone | Changeable by the author
Model was written in NetLogo 6.2.0 • Viewed 53 times • Downloaded 5 times • Run 0 times
Download the 'Bulls and Bears' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Info tab cannot be displayed because of an encoding error

Comments and Questions

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

;; Bulls & Bears
;; A Minimalist Artificial Stock Market

globals [
;; From sliders:
;; investors                         ;; total number of investors/agents
;; fraction-contrarians              ;; percentage of investors that are contrarians
;; memory                            ;; number of periods m that price is remembered
;; wealth-factor                     ;; coefficient k1
;; maximum-herd-effect-followers     ;; coefficient k2
;; maximum-herd-effect-contrarians   ;; coefficient k3
;; maximum-risk-appetite             ;; coefficient k4
;; price-sensitivity-to-demand       ;; coefficient k5

;; Others:
  num-contrarians                    ;; total number of contrarians
  num-followers                      ;; total number of followers
  risk-appetite-big                  ;; used for ma >=0
  risk-appetite-small                ;; used for ma < 0
  tot-demand-followers               ;; total demand of followers
  tot-demand-contrarians             ;; total demand of contrarians
  tot-demand                         ;; total value of shares demanded
;;  tot-share-demand                   ;; total number of shares demanded
  price                              ;; current calculated price
  last-price                         ;; price at time t-1
  return                             ;; percentage price change from t-1 to t
  value-traded                       ;; equal to smaller of demands, to clear market
  volume-traded                      ;; value traded divided by share price
  followers-wealth                   ;; total wealth of followers
  contrarians-wealth                 ;; total wealth of contrarians
  total-wealth                       ;; total wealth of all investors
  max-wealth                         ;; highest wealth of all investors
  min-wealth                         ;; lowest wealth of all investors
  max-demand-c                       ;; maximum demand of contrarians
  max-demand-f                       ;; maximum demand of followers
  max-demand                         ;; highest demand of all investors
  min-demand                         ;; lowest demand of all investors
  all-return-list                    ;; collects all returns
  return-list                        ;; collects last m returns
  moving-average                     ;; average return over last m periods
  all-volatility-list                ;; collects all volatilities
  volatility-price-list              ;; collects last 36 prices
  volatility                         ;; standard deviation of returns over last 36 periods
  value-traded-list                  ;; collects values traded
  volume-traded-list                 ;; collects volumes traded
  graph-max                          ;; maximum of previous two lists
  graph-min                          ;; minimum of previous two lists
  ]

turtles-own
[
  follower
  contrarian
  cash
  shares-value
  shares
  wealth
  wealth-effect                     ;; part of investors' demand function
  herd-effect-follower              ;; part of followers' demand function
  herd-effect-contrarian            ;; part of contrarians' demand function
  risk-appetite                     ;; part of investors' demand function
  demand-follower
  demand-contrarian
  shares-value-transacted
]

to setup
  ca
  random-seed 1051100757  ;; if required
  ask patches [ set pcolor white ]  ;; create a blank background
  create-turtles investors [ setxy random-xcor random-ycor set size 3 ]

;; Create empty lists for return histogram, moving average of last m returns, 36-period price volatility, trade
  set all-return-list [ 0 ]  ;; for histogram scaling
  set return-list []  ;; for moving average
  while [ length return-list < memory ] [ set return-list lput 0 return-list ]
  set all-volatility-list [ 0 0.2]  ;; for volatility graph scaling
  set volatility-price-list []
  while [ length volatility-price-list < 36 ] [ set volatility-price-list lput 100 volatility-price-list ]
  set value-traded-list []  ;; for trade graph scaling
  set volume-traded-list []  ;; for trade graph scaling

 set num-contrarians round ( ( fraction-contrarians ) / ( 100 ) * ( investors ) )
 set num-followers ( investors - num-contrarians )

;; Initialise some variables
  set price ( 100 )
  set moving-average ( 0 )
  set graph-min ( 0 )
  set graph-max ( 1 )

;; Divide into two investor types
ask turtles
  [
   set cash 50
   set shares-value 50
   set wealth  cash + shares-value

   ifelse who < num-contrarians
      [
        set contrarian 1
        set follower 0
        set shape "wolf 3"
        set color red
      ]
      [
        set contrarian 0
        set follower 1
        set shape "cow skull"
        set color blue
      ]
  ]
  reset-ticks
end 

to go
;; For each investor calculate *magnitudes* of demands, i.e. "desired size of bet"
  set risk-appetite-big maximum-risk-appetite / 1 * moving-average
  set risk-appetite-small maximum-risk-appetite / 2.5 * moving-average  ;; investors hate losses ~2.5 times as much as they love gains

  ask turtles
      [
        ;; Wealth: range of wealth parameter (i.e. on slider) and other parameters need to be determined empirically
        set wealth-effect ( ( wealth-factor ) * ( wealth ) )  ;; this is per investor

        ifelse contrarian = 1
        [
          ;; Herding: the susceptibility of investors to herding by their own type ranges randomly from zero to the maximum
          set herd-effect-contrarian random-float abs ( ( maximum-herd-effect-contrarians ) * ( tot-demand-contrarians ) / ( num-contrarians ) )  ;; normalize per investor
          ;; Risk appetite:
            ifelse moving-average >= 0
              [ set risk-appetite random-float risk-appetite-small ]
              [ set risk-appetite random-float ( - ( risk-appetite-big ) ) ]  ;; this is per investor
          set demand-contrarian max list 0 ( wealth-effect + herd-effect-contrarian  +  risk-appetite )
          ;; Full demand function: is "desired size of bet" so cannot be less than zero; the sign is then determined purely by type of investor
          set demand-contrarian min list demand-contrarian wealth  ;; Can't bet more than one's wealth
          ;; Scaling for main graph
          if ticks > 2 [set color scale-color blue risk-appetite ( max [ risk-appetite ] of turtles + 1 ) ( min [ risk-appetite ] of turtles) ]  ;; + 1 is error trap for when m.a. = 0
          set size min list ( 0.5 * herd-effect-contrarian + 1.3 ) 7
        ]
        [
          set herd-effect-follower random-float abs ( ( maximum-herd-effect-followers ) * ( tot-demand-followers ) / ( num-followers) )
           ifelse moving-average >= 0
             [ set risk-appetite random-float ( - ( risk-appetite-big ) ) ]
             [ set risk-appetite random-float risk-appetite-small ]
          set demand-follower max list 0 ( wealth-effect + herd-effect-follower + risk-appetite )
          set demand-follower min list demand-follower wealth
          if ticks > 2 [ set color scale-color red risk-appetite ( max [ risk-appetite ] of turtles + 1 ) ( min [ risk-appetite ] of turtles ) ]
          set size min list ( 0.5 * herd-effect-follower + 1.3 ) 7
        ]
    ]
;; In the risk appetite calculation above it is assumed that if e.g. moving-average >= 0 followers would have largely been long, so their
;; risk appetite will be big, with the converse for contrarians. Ideally, each investor should have their own personal moving-average.

;;  For each investor type, aggregate demand
        set tot-demand-followers sum [ demand-follower ] of turtles
          if  tot-demand-followers = 0 [ set tot-demand-followers (10) ]  ;; error trap for division by zero
        set tot-demand-contrarians sum [ demand-contrarian ] of turtles
          if  tot-demand-contrarians = 0 [ set tot-demand-contrarians (10) ]  ;; error trap for division by zero

;;  For each investor type now calculate *sign* of aggregate demand, i.e. direction of aggregate bet
      ifelse return > 0
        [ set tot-demand-contrarians (- tot-demand-contrarians) ]
        [ set tot-demand-followers (- tot-demand-followers) ]

   set tot-demand ( tot-demand-followers ) + ( tot-demand-contrarians )  ;; i.e. is *net* demand

;; Calculate new price
  set last-price price
  set price ( ( last-price ) + ( price-sensitivity-to-demand ) * ( tot-demand ) )
  if price <= 0 [set price (1)]  ;; error trap - price floor

;; Calculate return over period
  set return ( ( price ) / ( last-price ) - ( 1 ) ) * ( 100 )

;; Add return to the all-return list, then the moving-average return list and take average of this list
  set all-return-list lput return all-return-list
  set return-list lput return return-list
  set return-list remove-item 0 return-list
  set moving-average ( mean return-list )

;; Add price to the volatility price list, take standard deviation of list, cumulate volatilities
  set volatility-price-list lput price volatility-price-list
  set volatility-price-list remove-item 0 volatility-price-list
  set volatility ( standard-deviation volatility-price-list )
  if ticks > 36 [ set all-volatility-list lput volatility all-volatility-list ]  ;; start to cumulate volatilities when past initialized dummy data

;; Calculate value traded (equal to smaller of demands, to clear market) and volume
  set value-traded min list abs tot-demand-followers abs tot-demand-contrarians
  set volume-traded ( value-traded ) / ( price ) * ( 100 )

;; For trade graph scaling
  set value-traded-list lput value-traded value-traded-list
  set volume-traded-list lput volume-traded volume-traded-list
  set graph-max max list ( max value-traded-list ) ( max volume-traded-list )
  set graph-min min list ( min value-traded-list ) ( min volume-traded-list )

;; Recalculate investors' wealth
  ask turtles
    [
      ifelse contrarian = 1
      [  set shares-value-transacted ( demand-contrarian ) / ( tot-demand-contrarians ) * ( value-traded )  ;; get share value allocated pro-rata to relative demand
        ;; change investors' cash and share balances
           ifelse return >= 0
        [
          set shares-value shares-value - shares-value-transacted
          set shares ( shares-value ) / ( last-price )
          set cash cash + shares-value-transacted
        ]
        [
          set shares-value shares-value + shares-value-transacted
          set shares ( shares-value ) / ( last-price )
          set cash cash - shares-value-transacted
        ]
      ]
      [  set shares-value-transacted ( demand-follower ) / ( tot-demand-followers ) * ( value-traded )
           ifelse return >= 0
        [
          set shares-value shares-value + shares-value-transacted
          set shares ( shares-value ) / ( last-price )
          set cash cash - shares-value-transacted
        ]
        [
          set shares-value shares-value - shares-value-transacted
          set shares ( shares-value ) / ( last-price )
          set cash cash + shares-value-transacted
        ]
       ]
        set wealth ( shares ) * ( price ) + ( cash )  ;; update investors' wealth
    ]

  ;; Scaling of main graph
  set followers-wealth sum [ wealth ] of turtles with [ follower = 1 ]
  set contrarians-wealth sum [ wealth ] of turtles with [ contrarian = 1 ]
  set total-wealth sum [ wealth ] of turtles
  set max-wealth max [ wealth] of turtles
  set min-wealth min [ wealth] of turtles
  if max-wealth = min-wealth [ set max-wealth ( max-wealth + random ( 10 ) )  set min-wealth ( min-wealth - random ( 10 ) ) ]  ;; error trap to stop division by zero in plot
  set max-demand-c max [ demand-contrarian ] of turtles
  set max-demand-f max [ demand-follower ] of turtles
  set max-demand max list max-demand-c max-demand-f   ;; must be a cleverer way to do this
  set min-demand min list min [ demand-contrarian ] of turtles min [ demand-follower ] of turtles

ask turtles
;;  [ if wealth >= 0
    [
     ifelse contrarian = 1
      [ setxy ((( wealth - min-wealth ) / ( max-wealth - min-wealth ) * ( max-pxcor - min-pxcor)) + min-pxcor ) ((( demand-contrarian - min-demand ) / ( max-demand - min-demand ) * ( max-pycor - min-pycor)) + min-pycor ) ]
      [ setxy ((( wealth - min-wealth ) * ( max-pxcor - min-pxcor) / ( max-wealth - min-wealth )) + min-pxcor ) ((( demand-follower - min-demand ) / ( max-demand - min-demand ) * ( max-pycor - min-pycor)) + min-pycor ) ]
;;    ]
  ]
  tick
end 

There is only one version of this model, created 19 days ago by Franco Busetti.

Attached files

File Type Description Last updated
Bulls and Bears.png preview Preview for 'Bulls and Bears' 19 days ago, by Franco Busetti Download

This model does not have any ancestors.

This model does not have any descendants.