mschneider / solcpp

A fast Solana and Mango Markets C++ SDK
Other
42 stars 14 forks source link

Create advanced example to fetch orderbook via websocket #9

Open mschneider opened 2 years ago

mschneider commented 2 years ago

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
papadpickle commented 2 years ago

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.

mschneider commented 2 years ago

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

mschneider commented 2 years ago

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.

papadpickle commented 2 years ago

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.

mschneider commented 2 years ago

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 commented 2 years ago

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

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

papadpickle commented 2 years ago

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.

mschneider commented 2 years ago

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

papadpickle commented 2 years ago

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 commented 2 years ago

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

mschneider commented 2 years ago

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

sean-thorburn commented 2 years ago

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);