Market makers are large financial institutions who act as intermediaries between buyers and sellers. They provide liquidity to traders, taking orders on both sides and reducing the difference between ask and bid price for assets. Market makers make profit from bid ask spreads. Our strategy is market-making on one of the Mag7 stocks, which includes Alphabet, Amazon, Apple, Meta, Microsoft, NVDIA, and Tesla. For our example, we will do MSFT. We will use the Stoikov market-making strategy, so we need two main equations: The first calculates the reservation price based on the equation:
Reservation Price
s = current market mid price q = quantity of assets in inventory of base asset (could be positive/negative for long/short positions) σ = market volatility T = closing time, when the measurement period ends (conveniently normalized to 1) t = current time (T is normalized = 1, so t is a time fraction)
The second sets optimal bid-ask spread using the equation:
Optimal Bid-Ask Spread
σ = market volatility T = closing time, when the measurement period ends (conveniently normalized to 1) t = current time (T is normalized = 1, so t is a time fraction) δa, δb = bid/ask spread, symmetrical → δa=δb γ = inventory risk aversion parameter κ = order book liquidity parameter
Entry conditions: We want to create symmetrical bid and ask orders around the market mid-price, but this could lead to the inventory skewing in one direction if there are significant market movements in one direction. The reference price is where the buy and sell orders will be created around.
We then enter into limit orders on both sides of this quote.
Exit conditions: As the trading day goes on, each parameter of the models will change, and new values for reservation price and optimal spreads will be calculated. We then set new orders based on the new parameters. This cycle continues indefinitely until the end of our backtesting period.
Stop Loss: Instead of setting a specific stop loss, we set inventory limits to try and control the portfolio during momentum shifts. We set this at 15.
Data: We can use ShinyBroker to obtain most of the assets’ attributes, such as price throughout the day, volatility, and timing, via fetch_historical_data.
Blotter:
timestamp
trade
fill_price
reservation_price
inventory
cash_position
portfolio_value
2025-03-05 11:15:00
SELL
392.07
391.42
-2
1000392.07
999609.31
2025-03-05 12:00:00
SELL
393.34
392.81
-3
1000785.41
999607.22
2025-03-05 12:30:00
BUY
394.62
395.01
-2
1000390.79
999600.94
2025-03-05 13:30:00
SELL
395.49
395.07
-3
1000786.28
999601.475
2025-03-05 14:15:00
BUY
398.52
399.11
-2
1000387.76
999589.89
2025-03-05 14:45:00
BUY
398.84
399.49
-1
999988.92
999589.51
2025-03-05 15:30:00
BUY
399.96
400.44
0
999588.96
999588.96
2025-03-06 12:15:00
BUY
395.26
395.92
1
999193.7
999589.625
2025-03-06 12:30:00
BUY
395.54
395.96
2
998798.16
999590.18
2025-03-06 13:00:00
BUY
396.93
397.19
3
998401.23
999593.34
Showing 1 to 10 of 695 entries
Ledger:
timestamp
inventory
cash_position
mid_price
portfolio_value
unrealized_pnl
2025-03-05 11:15:00
-2
1000392.07
391.38
999609.31
1.38
2025-03-05 12:00:00
-3
1000785.41
392.73
999607.22
1.83
2025-03-05 12:30:00
-2
1000390.79
394.93
999600.94
-0.61
2025-03-05 13:30:00
-3
1000786.28
394.94
999601.475
1.665
2025-03-05 14:15:00
-2
1000387.76
398.94
999589.89
-0.83
2025-03-05 14:45:00
-1
999988.92
399.41
999589.51
-0.57
2025-03-05 15:30:00
0
999588.96
400.38
999588.96
0
2025-03-06 12:15:00
1
999193.7
395.92
999589.625
0.665
2025-03-06 12:30:00
2
998798.16
396.01
999590.18
0.94
2025-03-06 13:00:00
3
998401.23
397.37
999593.34
1.32
Showing 1 to 10 of 695 entries
Portfolio Value Over Time
Inventory Level Over Time
Alpha: 1.2683641851897157e-06 Beta: 0.0013455253367804282 benchmark_volatility_annualized: 0.07183856080115263 asset_volatility_annualized: 0.00022642370194626593 benchmark_geometric_mean: 0.9999813518481299 benchmark_arithmetic_mean: -1.8648325749104094e-05 asset_geometric_mean: 1.0000012432731633 asset_arithmetic_mean: 1.2432723904057614e-06 Sharpe Ratio: 0.005490910976717492 Average Return per Trade: 1.2608092485550546 Average Number of Trades per Year: 4357.810344827586