model

model preview image

1 collaborator

Default-person ifelab lerma (Author)

Tags

(This model has yet to be categorized with any tags)
Visible to everyone | Changeable by the author
Model was written in NetLogo 6.2.0 • Viewed 27 times • Downloaded 1 time • Run 0 times
Download the 'model' modelDownload this modelEmbed this model

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


Comments and Questions

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

Click to Run Model

; import native netlogo library to use tables and array
extensions [table array]

; define global variables
globals
[
         ; Global fix variables (hypothesis of simulation)
         COMPANIES-MAX-LEVERAGE  ; companies max leverage set at 0,9 for non sharia compliant companies and 0,33 for sharia compliant companies
         MIN-DEBT-RATIO ; companies min debt ratio set at 0 for sharia compliant companies and 0,6 for non sharia compliant for optimization purposes
         AUCTION-RISE-PERCENT; ; pourcentage of price rise for each round in the auction process

         ; Global variables for companies
         avg-companies-ebit
         avg-companies-equity std-dev-companies-equity
         avg-companies-leverage
         tot-companies-bankrupt
         avg-companies-multiple-offer ; average multiple offer while companies are bought by funds
         min-companies-debt avg-companies-debt tot-companies-debt
         tot-companies-PE ; total of private equity backed companies
         tot-companies-monetized-badwill tot-companies-monetized-goodwill  ; monetized badwill and goodwill while companies are bought by funds

         ; Global variables for funds
         avg-funds-wealth   avg-fund-commitment
         number-of-funds-drivers ; a fund is considered driver if other funds imitate his investments


         ; Global variables for market data
         tot-IPO-transactions tot-transactions nb-transactions-per-tick ; informations of transactions
         multiple-market next-multiple-market  cumulative-multiple-market next-cumulative-multiple-market ; information of multiple market
         created-market-wealth ; created wealth for the global market

         ; Global counter variables
         company-counter fund-counter

         ; Global bank variables
         bank-available-debt bank-loses

     ]

; companies and funds are both breeds of turtle.
breed [companies company]
breed [funds fund]

companies-own [id-company ebit ebit-growth cash ebit-growth-n-1 enterprise-value debt debt-rate status  debt-reimbursment age-on-status initial-investment multiple-offer fund-owner-id ownership-percent]
;status 0,1,2,3 -> normal, PEbacked, bankrupt,forsale
; multiple-offer is the last multiple offer used

funds-own[id-fund age available-commitment investments wealth  max-investment-on-company min-investment-on-company isDriver]



; setup functions

to setup
  clear-all
  setup-globals-variables
  setup-companies
  setup-funds
  calculate-avg-tot
  reset-ticks
end 

to setup-company [id-c]

 ask companies with [id-company = id-c]
 [

    set shape  "flag"
    set color white
    set size .8
    setxy random-xcor (random-ycor / 3 - 2 * max-pycor / 3)
    set company-counter company-counter + 1

    set status 0
    set age-on-status 0

    set ebit 100
    set ebit-growth 0
    set debt 0
    set enterprise-value 800
    set debt-rate 0.05
    set debt-reimbursment  0
    set cash enterprise-value * 2 / 3
    ; each company has initial value of 800
    set initial-investment 0
    set ownership-percent 0.66

    set  multiple-offer 0
    set  fund-owner-id 0
  ]
end 

to setup-companies

  create-companies NUMBER-OF-COMPANIES; initial-number-companies  ; create the companies, then initialize their variables
  [
    set id-company company-counter
    setup-company id-company

  ]
end 

to setup-funds
  create-funds NUMBER-OF-FUNDS; initial-number-companies  ; create the companies, then initialize their variables
  [
    set id-fund fund-counter
    set shape  "house"
    set color gray
    set size 1.2
    setxy (min-pxcor + (fund-counter - .5) * (max-pxcor - min-pxcor) / NUMBER-OF-FUNDS) (max-pycor - 1)
    if (fund-counter mod 2 = 0) [set ycor ycor - 1]
    set fund-counter fund-counter + 1
  ]
  ask funds
  [
  set isDriver 0
  set available-commitment 20000
  set age 0

  set max-investment-on-company MAX-INVESTMENT-ON-COMPANY-PER-FUND * available-commitment
  set min-investment-on-company MIN-INVESTMENT-ON-COMPANY-PER-FUND * available-commitment

  set investments []
  set wealth available-commitment
  ]


  ask  n-of  NUMBER-OF-FUNDS-DRIVERS funds
  [
    set isDriver 1
    set color yellow
  ]
end 

to setup-globals-variables

  set multiple-market 8 ; is set at 8 as initial value
  set next-multiple-market 0
  set next-multiple-market  0
  set created-market-wealth 0
  set  cumulative-multiple-market multiple-market

  set company-counter 1
  set fund-counter 1

  set nb-transactions-per-tick 0
  set tot-transactions 0

  set tot-companies-bankrupt 0

  set bank-available-debt TOTAL-DEBT ; bank available debt is set to total debt as initial value


  ; initial fix values
  set AUCTION-RISE-PERCENT 0.1
  set MIN-DEBT-RATIO  0.6
  set COMPANIES-MAX-LEVERAGE 0.9
  if isShariaCompliant? [
    set MIN-DEBT-RATIO 0
    set COMPANIES-MAX-LEVERAGE 0.33]


  ;Min 1 et x% of number of funds
  set number-of-funds-drivers  int (PERCENTAGE-OF-DRIVERS / 100 * NUMBER-OF-FUNDS)
  if number-of-funds-drivers = 0 [set number-of-funds-drivers 1]
end 



; run functions

to initialize-tick

 set next-multiple-market  0
 set nb-transactions-per-tick 0
end 


; calculate funds wealth

to calculate-funds-wealth
  ; fund wealth = available commitement (cash available)  + value of each owned company  (equity value of the company  * owned percent)
  ask funds
  [
    ;calculate fund wealth
    set wealth available-commitment

    foreach investments
    [
      id-c -> let m-status item 0 [status] of companies with [id-company = id-c ]
              if m-status != 2
      [
              let m-value item 0 [enterprise-value] of companies with [id-company = id-c ]
              let m-debt item 0 [debt] of companies with [id-company = id-c ]
              let m-ownership-percent item 0 [ownership-percent] of companies with [id-company = id-c ]
              set wealth wealth  + (m-value - m-debt ) * m-ownership-percent
      ]
    ]

    set max-investment-on-company MAX-INVESTMENT-ON-COMPANY-PER-FUND * wealth
    set min-investment-on-company MIN-INVESTMENT-ON-COMPANY-PER-FUND * wealth
  ]
end 

; calculate multiple market

to calculate-multiple-market
 if   nb-transactions-per-tick > 0
  [set multiple-market  next-multiple-market / nb-transactions-per-tick ]
  if  tot-transactions > 0
  [ set cumulative-multiple-market next-cumulative-multiple-market / tot-transactions ]
end 

; calculate companies performance

to calculate-companies-performance

  ask companies with [status != 2]
  [


    ;calculate ebit
    set ebit-growth-n-1 ebit-growth
    ; different growth for private equity backet company
    ifelse (status = 1 or status = 3) ; Private equity backed company
    [ set ebit-growth 0.04 + 0.2 * ebit-growth + (random-normal 0 Vol-PE) ]  ;AR(1) process for ebit growth modelling

    ;else
    [ set ebit-growth 0.01 + 0.2 * ebit-growth + (random-normal 0 Vol-Non-PE) ]  ;AR(1) process for ebit growth modelling

    set ebit (1 + ebit-growth ) * ebit ; one year pace
    ifelse ebit-growth > 0 [set color green][set color red]


    ;calculate net income and entreprise value
    let RN (ebit - debt-rate * debt )
    if RN > 0 [ set RN RN * 0.7  ]; 0.7 = 1 - tax (30%)]


     ; calculate debt reimbursment
    let reimbursment debt-reimbursment
    if debt - debt-reimbursment <= 0
    [ set reimbursment debt]
    if debt = 0
    [ set reimbursment 0]
    set debt debt - reimbursment


    set bank-available-debt bank-available-debt + reimbursment
    set cash cash + RN - reimbursment

    ; update created wealth and enterprise value
    set  created-market-wealth  created-market-wealth  + RN
    set enterprise-value   enterprise-value + RN - reimbursment ; value entreprise  = Equity + Debt



  ]
end 

; set aging funds and companies

to set-aging-companies-funds
    ; update age of funds
  ask funds
  [set age age + 1]


  ; update forsale status
  ask companies
  [
    set age-on-status age-on-status + 1

    ; after one year if company is not saled, the multiple offer is discounted
    if status = 3
    [
        set multiple-offer  ( 1 - ANNUAL-DISCOUNT-ON-UNSOLD-COMPANIES) * multiple-offer
    ]

    ; put forsale investments to IPO if Eq > 5 * initial investment
    if status = 3
    [
      let amount-eq (enterprise-value - debt) * ownership-percent
      if ( amount-eq > 5 * initial-investment   )
      [
        ; sale on IPO
        if debug-mode? [show (list "IPO" id-company initial-investment amount-eq )]
        set tot-IPO-transactions tot-IPO-transactions + 1
        let f-owner fund-owner-id
        let id-c id-company
        ask funds with [id-fund = f-owner ]
        [
          set investments remove id-c  investments
          set available-commitment available-commitment + amount-eq
        ]

        set bank-available-debt bank-available-debt + debt
        setup-company  id-c
        set multiple-offer  multiple-market

      ]
    ]

    ; put to sale old investments
    if status = 1
    [
      if ((ebit * multiple-market - debt) * ownership-percent > 3 * initial-investment or age-on-status > 5 )
      [
        set status 3
        set age-on-status 0

        set multiple-offer  ((( 3 * initial-investment ) / ownership-percent )+ debt) / ebit

      ]
    ]

  ]
end 




; auction processus

to launch-auction

   clear-links
  ;initilize auction tables

  let dict-auct-drivers table:make
  let dict-auct table:make

  ask companies
  [

    table:put dict-auct id-company []
    table:put dict-auct-drivers  id-company []
  ]


  ask funds with [available-commitment >= min-investment-on-company ];
  [

    let fund-id id-fund
    let dict-score table:make
    let nb-companies-to-look calculate-nb-companies-to-look fund-id

    ; for each fund choose "random" companies to look that are availables and score them
    ask n-of nb-companies-to-look companies with [status != 2 and status != 1 and  (isInFund id-company fund-id) = 0 ]
    [
      let m-score scoring-function  ebit ebit-growth ebit-growth-n-1 length table:get dict-auct-drivers id-company
      table:put dict-score   id-company m-score
    ]

    ; sort scored companies
    let scores-sorted  (sort-by [ [id1 id2] ->  table:get dict-score id1 >  table:get dict-score id2 ] table:keys dict-score )
    let m-commitment available-commitment


    ; based on  scores determine wich company is interesting for investment
    foreach  scores-sorted
    [
      id-c ->
      if ( table:get dict-score id-c > MIN-SCORE-TO-INVEST )
       [
          let m-amout-eq  calculate-amount-eq id-c

          if min (list available-commitment max-investment-on-company) > ( 1 - COMPANIES-MAX-LEVERAGE) * m-amout-eq
          [

            ask companies with [id-company = id-c ]
            [
              create-link-from myself
            ]

            if isDriver = 1
            [
              let m-list  lput id-fund  table:get  dict-auct-drivers id-c

              table:put dict-auct-drivers id-c m-list
            ]

            let m-list  lput id-fund  table:get  dict-auct id-c
            table:put dict-auct id-c m-list
          ]

      ]
    ]
  ]



  ; auction process
  foreach table:keys  dict-auct
  [
   id-c ->
    let m-list-funds table:get dict-auct id-c

         let nb-funds length m-list-funds
         if ( nb-funds != 0 ) [

          let m-amout-eq  calculate-amount-eq id-c
          if ( nb-funds = 1 ) ; if only one fund os interested by a company , fund buy it
          [
             Observer-buy-company id-c ( item 0 m-list-funds ) m-amout-eq
          ]
          ; else another round launched where price is rised
          if (nb-funds > 1 )
          [
          negociation-to-buy m-list-funds INCREMENT-PROBABILITY-TO-QUIT  m-amout-eq id-c]
        ]

   ]
end 

; main

to go

 clear-links ; delete all the links
 initialize-tick
; aging process
 calculate-companies-performance
 set-aging-companies-funds
 check-bankrupty

; auction process
 launch-auction

; update variables
 calculate-funds-wealth
 calculate-multiple-market
 calculate-avg-tot

; display
 display-labels
  if debug-mode?
  [
 ask funds
  [show (list id-fund age available-commitment investments wealth  max-investment-on-company isDriver)]
 ask companies
 [ show (list id-company  ebit enterprise-value debt  status  initial-investment multiple-offer fund-owner-id  )]
  ]
 ;export-data
 tick
end 


; update average global variables

to calculate-avg-tot

  set avg-companies-equity mean [enterprise-value] of companies with [status != 2]
  set avg-companies-equity avg-companies-equity  - (mean [debt] of companies with [status != 2])

  set std-dev-companies-equity standard-deviation [enterprise-value - debt] of companies with [status != 2]

  set tot-companies-debt sum [debt]  of companies with [status != 2]
  set avg-funds-wealth mean [wealth] of funds
  set avg-companies-ebit mean [ebit] of companies with [status != 2]
  set tot-companies-PE count companies with [ status = 1 or status = 3]

  set avg-companies-debt mean [debt] of companies with [status != 2]
  set avg-companies-multiple-offer mean [multiple-offer] of companies with [status != 2]
  set avg-fund-commitment mean [available-commitment] of funds

  ;calculation of average levrage
  ifelse count companies with [status = 1 or status = 3] > 0
    [ set avg-companies-leverage mean[debt / enterprise-value]  of companies with [status = 1 or status = 3]

      set min-companies-debt min [debt ]  of companies with [status = 1 or status = 3]

  ]
      [set avg-companies-leverage 0]
end 




; private functions for auction process

to-report isInFund [id-c id-f]
  ; check if company of id id-c is owned by the fund of id id-f
  let m-investments  item 0  [investments] of funds with [id-fund = id-f ]
  foreach m-investments
  [
    id -> if id = id-c [report 1]
  ]
  report 0
end 

to-report calculate-amount-eq [id-c]
  ; calculate equity amount that a fund is able to pay for the company
  ; equity amount = ebit * multiple -debt
  ; multiple = to multiple offer if teh company is forsale ( it is different from market multiple)
  let result 0

  ask companies with [id-company = id-c]
  [
    let m-multiple multiple-market
    if status = 3
    [
      set m-multiple   multiple-offer ;
    ]
    set result  (ebit * m-multiple - debt)
    if debug-mode?
    [ show (list id-c result  multiple-market multiple-offer m-multiple )]
  ]

  report result
end 

to negociation-to-buy [list-funds probability-to-quit amount id-c ]

   ; remove form list of funds  intrested by the company, companies that are not able because amount is too high that their financial capacity
   foreach list-funds
   [
      id-fd ->  let rand random 100
                if  rand / 100  < probability-to-quit ; funds can quit for different reasons with a probability to quit that is incremented each round
                [
                    set list-funds remove id-fd list-funds
                ]
                let m-max-investment-on-company item 0 [max-investment-on-company] of funds with [id-fund = id-fd]
                let m-commitment item 0 [available-commitment]of funds with [id-fund = id-fd]
                if min (list m-commitment m-max-investment-on-company) < ( 1 - COMPANIES-MAX-LEVERAGE) * amount
                [
                     set list-funds remove id-fd list-funds
                ]

   ]
   ifelse length list-funds = 0 [
    if debug-mode?
    [show "quit"]
        stop ]
   [
     ifelse length list-funds = 1
     [ Observer-buy-company id-c  item 0 list-funds  amount ]
         ; recursive function, we rise price another time
     [
      ; if more than a fund is intrested , another round of negociation until only one fund or no fund is intrested , price is rised next round
           negociation-to-buy list-funds probability-to-quit + INCREMENT-PROBABILITY-TO-QUIT amount * ( 1 + AUCTION-RISE-PERCENT)   id-c
     ]
  ]
end 

to-report calculate-nb-companies-to-look [ fund-id]

  ; calculate number of companies are available forsale or not yet owned , this number is capped ; funds can only look at a limied number of companies du to the associated cost
    let nb-companies-to-look count companies with [status != 2 and status != 1 and  (isInFund id-company fund-id) = 0 ]

    if nb-companies-to-look > NUMBER-OF-COMPANIES-TO-LOOK
      [set nb-companies-to-look  NUMBER-OF-COMPANIES-TO-LOOK]

  report nb-companies-to-look
end 

to Observer-buy-company [id-c id-f amount]

; function to update variables when a fund id-f buy the company with id id-c at an amount "amount"
 let fund-is-able-to-buy-company 1

 let m-ownership-percent item 0 [ownership-percent] of companies with [id-company = id-c]

 let m-debt item 0 [debt] of companies with [id-company = id-c]
 let new-debt max (list ( MIN-DEBT-RATIO * amount )    ( ( amount +  m-debt ) * COMPANIES-MAX-LEVERAGE - m-debt )) ; what does this mean?
 let amount-eq-fund ( amount - new-debt ) * m-ownership-percent



  ask funds with [id-fund = id-f]
  [

    ; check if  fund  is able to buy the company at the amount

    let possible-amount-eq  min (list available-commitment max-investment-on-company)

    if amount-eq-fund  > possible-amount-eq
    [
      if possible-amount-eq < ( 1 - COMPANIES-MAX-LEVERAGE) * amount * m-ownership-percent
      [
        set fund-is-able-to-buy-company 0
      ]

      set amount-eq-fund possible-amount-eq
      set new-debt  amount - amount-eq-fund / m-ownership-percent

    ]

    if amount-eq-fund < min-investment-on-company
    [
        set amount-eq-fund  min-investment-on-company
        set new-debt  amount - amount-eq-fund / m-ownership-percent
    ]
    if   new-debt < 0  or new-debt / amount < min-debt-ratio
    [
       set fund-is-able-to-buy-company 0

    ]

    ; if yes, upadte fund , companies and market variables
    if fund-is-able-to-buy-company = 1
    [
      ; update company data
      ask companies with [id-company = id-c]
      [

        let multiple  ( amount   +  debt)/ ebit

        let new_enterprise-Value  amount  + debt
        let leverage ( debt + new-debt ) / (new_enterprise-Value )

        if  ( ( multiple - multiple-offer ) > -0.01 and bank-available-debt > new-debt  and leverage < COMPANIES-MAX-LEVERAGE)
        [
          ; update market data
          set bank-available-debt  bank-available-debt - new-debt
          set nb-transactions-per-tick   nb-transactions-per-tick + 1
          set tot-transactions tot-transactions + 1
          set next-multiple-market next-multiple-market +  multiple
          set next-cumulative-multiple-market next-cumulative-multiple-market + multiple

          if item 0 [status] of companies with [id-company = id-c] = 3
          [
            ; update investement of fund
            ask funds with [id-fund = item 0  ([fund-owner-id] of companies with [id-company = id-c] ) ]
            [
              set available-commitment available-commitment + amount-eq-fund
              set investments remove id-c  investments
            ]
          ]

          let diff-eq new_enterprise-Value - enterprise-value
          ifelse diff-eq > 0 [set tot-companies-monetized-goodwill tot-companies-monetized-goodwill + diff-eq]  [set tot-companies-monetized-badwill tot-companies-monetized-badwill + diff-eq]

          set debt   debt + new-debt
          set enterprise-value new_enterprise-Value

          set debt-reimbursment  debt / 5
          set status   1
          set fund-owner-id id-f
          set age-on-status  0
          set initial-investment amount-eq-fund

          ; upodate fund data
          ask funds with [id-fund = id-f]
          [
            set available-commitment available-commitment - amount-eq-fund
            set investments lput id-c  investments
          ]
        ]


      ]
    ]
  ]

 ; update display data ( link between funds and companies owned )
 display-fund-own-company
end 

to display-fund-own-company
; this function create link between funds and its owned companies for display purposes
 let nb-investments 0
 let xfund 0
 let yfund 0
 ; display function
  ask funds
  [
     ;coordinates of fund
    set xfund xcor
    set yfund ycor
    set nb-investments length investments
    let counter  1
    foreach investments
    [
      id ->
            ask companies with [id-company = id]
           [
             set counter counter + 1
             ; positionner société sous le fonds
             setxy xfund yfund - counter
           ]
    ]
  ]
end 

to display-labels
  ask companies [ set label "" ]
  if show-status? [
    ask companies [ set label status ]
    ask funds [set label int (wealth / 5000) ]

  ]
end 

to-report scoring-function [ i-ebit perf-n perf-n-1 number-driver-in-auction]
  ; scoring function as explained in the article
  if i-ebit < 0 [ report 0 ]
  let perf-i ( ( i-ebit / 100 )^( 1 / (ticks + 1) ) - 1 )
   if debug-mode?
  [
  show (list "Perf" perf-i perf-n perf-n-1 ticks i-ebit)
  ]
  report (( 1 - IMITATION-RATIO ) * score-perf perf-i perf-n perf-n-1 +  IMITATION-RATIO  * min (list 1  ( 4 * ( number-driver-in-auction / number-of-funds-drivers ))))
end 

to-report score-perf [perf-i perf1 perf2]
  ifelse perf1 < 0.05 or perf2 < 0.05 or perf-i < 0
  [ report 0 ]
  [

    report (( min(list  perf1 0.1)   + min (list perf2 0.1))/ 2  ) * 10
  ]
end 



; private aging functions

to check-bankrupty
  ; check if a company is bankrupt
  ask companies with [status != 2]
  [
    if (  enterprise-value - debt  < 1 or ebit * multiple-market < 1 or cash < 0 )
    [
      if debug-mode?
      [show ( list "bankrupt " id-company enterprise-value debt ebit ) ]
      set bank-loses bank-loses + debt
      set tot-companies-bankrupt tot-companies-bankrupt + 1

      let f-owner fund-owner-id
      let id-c id-company
        ask funds with [id-fund = f-owner ]
        [
          set investments remove id-c  investments

        ]
      setup-company id-company
    ]
  ]
end 

;;;;
;to export-data
; export data for debug and check
 ;if export-data?
 ; [
 ; file-open "output-netlogo.csv"
 ; file-print tot-companies-bankrupt
 ; file-print avg-leverage
  ;file-print avg-companies-equity
  ;  file-print cumulative-multiple-market
  ;if ticks = 0 [file-print "standard deviation of equity"]
  ;file-print std-dev-equity
 ; if ticks = 39 [
 ;   file-print "Company Equity"
  ;  ask companies [file-print enterprise-value - debt]
  ;  ]
  ;file-close
 ; ]

;end

There is only one version of this model, created 4 months ago by ifelab lerma.

Attached files

File Type Description Last updated
model.png preview Preview for 'model' 4 months ago, by ifelab lerma Download

This model does not have any ancestors.

This model does not have any descendants.