solcpp icon indicating copy to clipboard operation
solcpp copied to clipboard

Create advanced example to fetch orderbook via websocket

Open mschneider opened this issue 3 years ago • 12 comments

https://github.com/mschneider/solcpp/blob/main/examples/accountSubscribe.cpp is a basic example for how to get the recent fills. We need a more complete example that is able to fetch the orderbook in addition and prints the following to the CLI on every SOL-PERP order book update:

  1. Last traded price
  2. Mid-price
  3. Spread in basis points
  4. $ +2% depth
  5. $ -2% depth

mschneider avatar Feb 16 '22 16:02 mschneider

i have started working on this one. would be good to have a board to mark it as in progress lest someone else starts this from scratch in parallel.

papadpickle avatar Feb 21 '22 00:02 papadpickle

created a board: https://github.com/mschneider/solcpp/projects/1

mschneider avatar Feb 21 '22 12:02 mschneider

also we are just about to roll out v3.4 from mango side, i was planning to write a simple order book parser for that purpose. lmk if that causes a conflict on your end.

mschneider avatar Feb 21 '22 12:02 mschneider

i am using the mango bowl wss server to subscribe to the data. not sure if the rollout to newer mango version will affect that or not. https://github.com/papadpickle/solcpp/blob/example_orderbook/examples/orderbookSubscribe/orderbookSubscribe.cpp

let me know if you had something else in the mind re this orderbook parsing example.

papadpickle avatar Feb 21 '22 13:02 papadpickle

yeah, we should probably connect directly to the on-chain data rather then through mango-bowl which does a lot of intermediate processing. i'll try to make a simple example of getting the order book via json rpc.

mschneider avatar Feb 21 '22 14:02 mschneider

https://github.com/mschneider/solcpp/commit/9deb4c90abec347db7cdf288c7cc2d603d65b7aa

here's a rough sketch of the code to parse the order book

mschneider avatar Feb 22 '22 02:02 mschneider

thanks for the rough idea. added lowest asks now https://github.com/papadpickle/solcpp/blob/example_orderbook_subscribe/examples/orderbookSubscribe.cpp

still unclear though how to have a websocket subscription to orderbook update instead of the rpc polling. if you have any code somewhere in other projects which wss'es solana, please let me know.

papadpickle avatar Feb 22 '22 23:02 papadpickle

accountSubscribe is the correct request to implement this, you can either open multiple websockets or subscribe to multiple account updates on the same socket

mschneider avatar Feb 23 '22 09:02 mschneider

makes sense. have added two subscriber objects for bids and asks. 8760e5748be6dd41392872ab9be20f7f452c0782 will have to see how/when to log the required info since the bids and asks are separate wss messages.

papadpickle avatar Feb 23 '22 23:02 papadpickle

do you have any specific way to calculate market depth? that is just the volume of orders at $+% right? would be cool if you already have a logic in rust code or some other mango project to look into before i try to reinvent the wheel.

that''s the remaining part, everything else is ready at https://github.com/papadpickle/solcpp/tree/example_orderbook_subscribe_sol

papadpickle avatar Feb 25 '22 00:02 papadpickle

noticed you use getSpreadBsp in your code, i think BPS is a more common abbreviation for basis points

mschneider avatar Feb 25 '22 16:02 mschneider

do you have any specific way to calculate market depth? that is just the volume of orders at $+% right? would be cool if you already have a logic in rust code or some other mango project to look into before i try to reinvent the wheel.

here is an example in C#:

IStreamingRpcClient streamingRpcClient = ClientFactory.GetStreamingClient(Cluster.MainNet);
IMangoClient mangoClient = Solnet.Mango.ClientFactory.GetClient(rpcClient, streamingRpcClient);

AccountResultWrapper<PerpMarket> perpMarket = await mangoClient.GetPerpMarketAsync("DtEcjPLyD4YtTBB4q8xwFZ9q49W89xZCZtJyrGebi5t8"); // BTC-PERP
AccountResultWrapper<OrderBookSide> bidsRequest = await mangoClient.GetOrderBookSideAsync(perpMarket.ParsedResult.Bids, Commitment.Processed); // Bids side of the orderbook
AccountResultWrapper<OrderBookSide> asksRequest = await mangoClient.GetOrderBookSideAsync(perpMarket.ParsedResult.Asks, Commitment.Processed); // Asks side of the orderbook

List<OpenOrder> bids = bidsRequest.ParsedResult.GetOrders().OrderByDescending(o => o.RawPrice).ToList();
List<OpenOrder> asks = asksRequest.ParsedResult.GetOrders().OrderBy(o => o.RawPrice).ToList();

long midPrice = (bids[0].RawPrice + asks[0].RawPrice) / 2;
double midLessDepth = midPrice * 0.98; // 2%
long depth = bids.Where(o => o.RawPrice > midLessDepth).Sum(o => o.RawQuantity);

sean-thorburn avatar Feb 25 '22 17:02 sean-thorburn