avaialable from (https://rpubs.com/staszkiewicz/FM03_Price_Discovery)

Introduction

  • Dynamic Market: Stock prices fluctuate constantly based on various factors like supply and demand, news, and economic indicators.

  • Order Book: A collection of buy and sell orders at different prices.

  • Price Discovery: The process of determining a fair market price through interaction of buy and sell orders.

Simmple modeling

  1. Load library
library(quantmod)
## Ładowanie wymaganego pakietu: xts
## Ładowanie wymaganego pakietu: zoo
## 
## Dołączanie pakietu: 'zoo'
## Następujące obiekty zostały zakryte z 'package:base':
## 
##     as.Date, as.Date.numeric
## Ładowanie wymaganego pakietu: TTR
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
  1. Simulate a simple order book

We will assume that 5 buy orders were sent to the stocke exchange at prices of: 102,100, 99, 101, 97 the investors would like to buy respectively: 18,100, 200, 150, 50.

On the opposite side of the markets the different investors would like to buy the stock for 103, 105, 104, 102 the following quantity: 50, 100, 200, 150. First crease two data frames with the buy orders prices and corresponding quantities, the second frame with the sell orders.

buy_orders <- data.frame(price = c(102,100, 99, 101, 97), quantity = c(18,100, 200, 150, 50))
sell_orders <- data.frame(price = c(103, 105, 104, 102), quantity = c(50, 100, 200, 150))

buy_orders
##   price quantity
## 1   102       18
## 2   100      100
## 3    99      200
## 4   101      150
## 5    97       50
sell_orders
##   price quantity
## 1   103       50
## 2   105      100
## 3   104      200
## 4   102      150

Note our list are not arranged by the prices, as the orders comes with different prices and quantity. So we now need to arrange market by prices bid and ask

  1. Sort orders by price
 buy_orders <- buy_orders[order(buy_orders$price, decreasing = TRUE), ]
  sell_orders <- sell_orders[order(sell_orders$price), ]
buy_orders
##   price quantity
## 1   102       18
## 4   101      150
## 2   100      100
## 3    99      200
## 5    97       50
sell_orders  
##   price quantity
## 4   102      150
## 1   103       50
## 3   104      200
## 2   105      100
  1. Find the highest bid and lowest ask price

We need to check if the market can execute any orders, this means we need to have at least one price at winch there is demand and supply for. So let us check the highest buy price and the lowest sell price.

 # Find the highest bid and lowest ask
  highest_bid <- buy_orders$price[1]
  lowest_ask <- sell_orders$price[1]


  highest_bid 
## [1] 102
  lowest_ask 
## [1] 102

Because the min sell is equal to max buy, we might execute the transaction at the strike price.

  1. Check if there is match in the highest bid and lowest ask
(highest_bid >= lowest_ask)
## [1] TRUE

But we need to establish the quantity.

  1. If true calculate the maximum number of shares to be exchanges, determine the trade quantity
    # Determine the trade quantity
    trade_quantity <- min(buy_orders$quantity[1], sell_orders$quantity[1])

   trade_quantity
## [1] 18

At the price 102 we are able to transfer 18 shares. Now we have to update the new trade book after execution of the transactions. The matched orders will be sent to the CCP for clearance (usually +3d)

Match supply and demand and update trade book after execution of matched transactions

 # Update orders
    buy_orders$quantity[1] <- (buy_orders$quantity[1] - trade_quantity)
    sell_orders$quantity[1] <- (sell_orders$quantity[1] - trade_quantity)
# Remove exhausted orders
    # Remove exhausted orders
    buy_orders <- buy_orders[buy_orders$quantity > 0, ]
    sell_orders <- sell_orders[sell_orders$quantity > 0, ]

Show now the orders book buy oders

buy_orders
##   price quantity
## 4   101      150
## 2   100      100
## 3    99      200
## 5    97       50

sells orders

sell_orders
##   price quantity
## 4   102      132
## 1   103       50
## 3   104      200
## 2   105      100

Calculate the new market price

 # Calculate the new price
    new_price <- (highest_bid + lowest_ask) / 2
    list(price = new_price, buy_orders = buy_orders, sell_orders = sell_orders)
## $price
## [1] 102
## 
## $buy_orders
##   price quantity
## 4   101      150
## 2   100      100
## 3    99      200
## 5    97       50
## 
## $sell_orders
##   price quantity
## 4   102      132
## 1   103       50
## 3   104      200
## 2   105      100

All in one

Below you have a full code check what the difference between the first one?

library(quantmod)

# Simulate a simple order book
buy_orders <- data.frame(price = c(100, 99, 98, 97), quantity = c(100, 200, 150, 50))
sell_orders <- data.frame(price = c(105, 104, 103, 102), quantity = c(50, 100, 200, 150))

# Function to process orders and determine price
process_orders <- function(buy_orders, sell_orders) {
  # Sort orders by price
  buy_orders <- buy_orders[order(buy_orders$price, decreasing = TRUE), ]
  sell_orders <- sell_orders[order(sell_orders$price), ]

  # Find the highest bid and lowest ask
  highest_bid <- buy_orders$price[1]
  lowest_ask <- sell_orders$price[1]

  # If there's an overlap, execute trades and update orders
  if (highest_bid >= lowest_ask) {
    # Determine the trade quantity
    trade_quantity <- min(buy_orders$quantity[1], sell_orders$quantity[1])

    # Update orders
    buy_orders$quantity[1] <- buy_orders$quantity[1] - trade_quantity
    sell_orders$quantity[1] <- sell_orders$quantity[1] - trade_quantity

    # Remove exhausted orders
    buy_orders <- buy_orders[buy_orders$quantity > 0, ]
    sell_orders <- sell_orders[sell_orders$quantity > 0, ]

    # Calculate the new price
    new_price <- (highest_bid + lowest_ask) / 2
    return(list(price = new_price, buy_orders = buy_orders, sell_orders = sell_orders))
  } else {
    return(list(price = NA, buy_orders = buy_orders, sell_orders = sell_orders))
  }
}

# Simulate multiple iterations
for (i in 1:10) {
  result <- process_orders(buy_orders, sell_orders)
  if (!is.na(result$price)) {
    print(paste("Iteration", i, "Price:", result$price))
    buy_orders <- result$buy_orders
    sell_orders <- result$sell_orders
  } else {
    print("No trades executed.")
    break
  }
}
## [1] "No trades executed."

Task

Now you might show the price discover in your reports for the Coca Cola assume the quantity bid and ask prices, please make sure the data in your reports are replicable.