dougdellolio / coinbasepro-csharp

The unofficial .NET/C# client library for the Coinbase Pro/GDAX API
MIT License
193 stars 90 forks source link

Getting Started #118

Open GITMIKRO opened 6 years ago

GITMIKRO commented 6 years ago

Thank you for what I understand to be a fantastic resource.

I am struggling to just get off the ground here and hoping to get assistance with the most basic example for 2 tasks.

  1. I want a winform to update with the current bid and ask for BTC-USD. (Websocket or Rest example is fine)
  2. The simplest syntax for a function to submit a limit order for BTC.

If I have this, I can run from there.

I very much appreciate a response, and I understand that this question may be a hassle, but I think it will help others to get started as well.

Thx!

dougdellolio commented 6 years ago

@GITMIKRO To start... you will have to new up a new gdax client with your credentials which can be found here for the live server https://www.gdax.com/settings/api or https://public.sandbox.gdax.com/settings/api for sandbox.

//create an authenticator with your apiKey, apiSecret and passphrase
var authenticator = new Authenticator("<apiKey>", "<apiSecret>", "<passphrase>");

//create the GDAX client using sandbox
var gdaxClient = new GDAXSharp.GDAXClient(authenticator, true);

for getting the best bid/ask:

if you want to go the REST route it looks like https://docs.gdax.com/#get-product-ticker is what you want. You can call that endpoint by using the Products service and GetProductTickerAsync() method.

var result = await gdaxClient.ProductsService.GetProductTickerAsync(ProductType.BtcUsd)
var bestBid = result.Bid;
var bestAsk = result.Ask;

for placing a limit order, use the OrdersService. (example here is limit order for 1 BTC @ $400.00)

var result = await gdaxClient.OrdersService.PlaceLimitOrderAsync(OrderSide.Buy, ProductType.BtcUsd, 1, 400.0M)

let me know if you have any other questions.

GITMIKRO commented 6 years ago

Doug, Thank you for your reply.

I did see most of what you suggested in the documentation, but setting it all up with the correct functions and calls to have my form update with the events using websockets is where I get upside down. I'll keep trying different things until I get a simple test to work.

I already have the api keys that I need, but I did not think these were necessary for the public data like tickers.

I was able to get the REST api working directly with the GDAX api, but I prefer to get the websockets to work and skip the timers.

Appreciative!

dougdellolio commented 6 years ago

@GITMIKRO no worries. please provide code and i would be happy to take a look and help

GITMIKRO commented 6 years ago

@dougdellolio Here's where I am:

        private GDAXClient _GDAXsocketClient;
        private void GetGDAXSocketAsync()
        {                    
            var authenticator = new GDAXSharp.Network.Authentication.Authenticator(apikey, secretkey, passphrase);

            _GDAXsocketClient = new GDAXSharp.GDAXClient(authenticator, false);       

            var productTypes = new List<GDAXSharp.Shared.Types.ProductType>() { GDAXSharp.Shared.Types.ProductType.BtcEur, GDAXSharp.Shared.Types.ProductType.BtcUsd };
            var channels = new List<GDAXSharp.WebSocket.Types.ChannelType>() { GDAXSharp.WebSocket.Types.ChannelType.Full, GDAXSharp.WebSocket.Types.ChannelType.User }; 

            var webSocket = _GDAXsocketClient.WebSocket;
            webSocket.Start(productTypes, channels);          
            webSocket.OnHeartbeatReceived += WebSocket_OnHeartbeatReceived;
        }

        private static void WebSocket_OnHeartbeatReceived(object sender, WebfeedEventArgs<Heartbeat> e)
        {
         //------------------------------------------------------------------
         //Doug, I was thinking that I need to be updating my form here?
         //------------------------------------------------------------------
          this.Invoke(new Action(() =>
            {
                ??
                ??
            }));

            throw new NotImplementedException();
        }
dougdellolio commented 6 years ago

@GITMIKRO it looks like the channel you want to subscribe to is the ticker channel: https://docs.gdax.com/#the-code-classprettyprinttickercode-channel

here is some code I threw together to print out the best bid and ask from the ticker channel. the event update happens when an order goes through

    public class Program
    {
        public static void Main(string[] args)
        {
            //create an authenticator with your apiKey, apiSecret and passphrase
            var authenticator = new Authenticator("<apiKey>", "<unsignedSignature>", "<passphrase>");

            //create the GDAX client
            var gdaxClient = new GDAXSharp.GDAXClient(authenticator);

            //subscribe to the ticker channel type
            var productTypes = new List<ProductType> { ProductType.BtcUsd };
            var channels = new List<ChannelType> { ChannelType.Ticker };

            var webSocket = gdaxClient.WebSocket;

            webSocket.Start(productTypes, channels);

            webSocket.OnTickerReceived += (sender, e) =>
            {
                PrintBestQuotes(e);
            };

            Console.ReadKey();
        }

        private static void PrintBestQuotes(WebfeedEventArgs<Ticker> webfeedEventArgs)
        {
            Console.WriteLine("BestBid = " + webfeedEventArgs.LastOrder.BestBid);
            Console.WriteLine("BestAsk = " + webfeedEventArgs.LastOrder.BestAsk);
            Console.WriteLine("==============");
        }
    }
GITMIKRO commented 6 years ago

@dougdellolio That was exactly what I needed to get me going. I cannot thank you enough for helping me out.

GITMIKRO commented 6 years ago

@dougdellolio Do I need to send webSocket.Stop(); on program close, or will it just die? Thx.

olegboksner commented 6 years ago

Hi can you provide a sample of returning the data from the event subscribed as apposed to just writing it the console, what is the best method to do this thanks

dougdellolio commented 6 years ago

@olegboksner im not sure I understand your question. The data is contained in the eventargs (the e in webSocket.OnTickerReceived += (sender, e) =>. you can replace the write statement with something more practical like placing an order

olegboksner commented 6 years ago

Hi Doug, I see now, thanks very much webSocket.OnTickerReceived += (WebSocket_OnTickerReceived, args) => { Console.WriteLine(args.LastOrder.ProductId.ToString() + " : Price:" + args.LastOrder.Price.ToString());

             Product = args.LastOrder.ProductId.ToString();

              threadsafemethod( Product );

}

I then call a method which checks for thread safety and invokes my output to text box,

olegboksner commented 6 years ago

Hi Doug, Im a bit confused on the channel and level2 Im just looking for a stream of bid and asks but the gdax instructions point to level2 and then snapshot or update so I set my channel to var channels = new List() { ChannelType.Level2 }; since there is no Snapshot channel then hook up to: webSocket.OnSnapShotReceived += (WebSocket_OnLevel2UpdateReceived_Snapshot, args) => I'm getting an array list in bids asks, that seems to go from 0 to max and reverse?

im looking for this output ex:

{ "type": "snapshot", "product_id": "BTC-EUR", "bids": [["6500.11", "0.45054140"]], "asks": [["6500.15", "0.57753524"]] } using event WebSocket_OnLevel2UpdateReceived_Snapshot(object sender, WebfeedEventArgs <\ Snapshot > e)

dougdellolio commented 6 years ago

@olegboksner it sounds like you are looking at the right channel.....level2 is what you want.

The way this channel works is it will send a message with "snapshot" type and the corresponding bids and asks are returned. These are the bids and asks you are getting from max to 0.

Anything after that will send you l2update type which has the side, price and size.

The output you pasted is all deserialized for you in the Bids list on the snapshot object and the Changes list on the Level2 object.

Here is some code that may be helpful:

    class Program
    {
        static void Main(string[] args)
        {
           //create an authenticator with your apiKey, apiSecret and passphrase
            var authenticator = new Authenticator("<apiKey>", "<unsignedSignature>", "<passphrase>");

            //create the GDAX client
            var gdaxClient = new GDAXClient(authenticator);

            //subscribe to the ticker channel type
            var productTypes = new List<ProductType> { ProductType.BtcEur };
            var channels = new List<ChannelType> { ChannelType.Level2 };

            var webSocket = gdaxClient.WebSocket;

            webSocket.Start(productTypes, channels);

            webSocket.OnSnapShotReceived += (sender, e) =>
            {
                foreach (var bid in e.LastOrder.Bids)
                {
                    Console.WriteLine($"Price = {bid[0]} and Size = {bid[1]}");
                }
            };

            webSocket.OnLevel2UpdateReceived += (sender, e) =>
            {
                foreach (var bid in e.LastOrder.Changes)
                {
                    Console.WriteLine($"Side = {bid[0]} Price = {bid[1]} and Size = {bid[2]}");
                }
            };

            Console.ReadKey();
        }
    }

let me know if this still doesn't make sense

olegboksner commented 6 years ago

OK thanks Doug, I'm basically doing same, and seeing same results looping through all the Bids and Asks, initially was not sure of the results or as to why I need all bids( to zero) and ask's from current to infinite .

olegboksner commented 6 years ago
Hi Doug, sorry one more silly question. I have implemented all the channels authenticated via the web-socket as test case but I am just looking for: what the rest api does Get Product Order Book Example Response for /products/BTC-USD/book Only the best bid and ask is returned. Level Description
1 Only the best bid and ask

in a continuous stream, any more recommendations on that ?

olegboksner commented 6 years ago

to be more specific I subscribe to level2 var channels = new List() { ChannelType.Level2 };

which event handler will give me continuous stream showing top bid and ask snapshot event handler gives me entire order book, which I don't want and I don't want to have to call it each time

these seem to be my choices webSocket.OnHeartbeatReceived webSocket.OnLastMatchReceived webSocket.OnLevel2UpdateReceived webSocket.OnMatchReceived webSocket.OnOpenReceived webSocket.OnReceivedReceived webSocket.OnSnapShotReceived webSocket.OnSubscriptionReceived webSocket.OnTickerReceived

olegboksner commented 6 years ago

would this be correct after subscribing to level2

webSocket.OnTickerReceived += (sender3, e3) => { e3.LastOrder.BestAsk.ToString();

        };
dougdellolio commented 6 years ago

@olegboksner no worries. my comment above does exactly what you are looking for (the 6th comment down). it will print the best bid and ask continuously using the websocket feed after every trade is made. this is using the ticker channel.

olegboksner commented 6 years ago

thanks again, I implemented that, how would I do the same for bids and asks (continuously) on open trades that have yet to have made a trade, say for instance I wanted to trade large volumes and needed open or available bid and ask before the trade

dougdellolio commented 6 years ago

@olegboksner I am not sure I understand what you're asking for.

If you want a streaming view of all bids and asks you should subscribe to OnLevel2UpdateReceived as shown in the above comment. You can then match the side and price to the updated size to get a view of what has changed. The size is the updated size at that price level, not the delta.

olegboksner commented 6 years ago

Hi Doug I can do the above and I am getting the OnLevel2UpdateReceived stream, but then I have to get the full order book snap shot each time, is there an easy way to just stream top 5 or 10 from the order book without having to request a snapshot of the entire order book, or am I already doing that with on level updated received and simply need to order that by price? I have seen many api's that have a simple top 20 from the order book that streams out

I get this : via the rest api result = await gdaxClient.ProductsService.GetProductOrderBookAsync(ProductType.LtcUsd, GDAXSharp.Services.Products.Types.ProductLevel.One);

or result = await gdaxClient.ProductsService.GetProductOrderBookAsync(ProductType.LtcUsd, GDAXSharp.Services.Products.Types.ProductLevel.Two);

how would I get the above streaming

dougdellolio commented 6 years ago

from what I can tell, there is no way to do what you are asking for based on their docs itself (as a specific request related to the websocket)

when subscribing to the level2 channel it will send a message with the type "snapshot" which will return the entire book (only once). any response after that, from OnLevel2UpdateReceived, is the type "l2update" which is just an update to items in the book. what is wrong with just doing that and only taking the top 5 or 10 items in the book?

olegboksner commented 6 years ago

Hi Doug, I did the above where I get updates to the OnLevel2UpdateReceived, then I take that and drop it into a list and and group the last 10 updates received by size, the problem is I get updates from anywhere in the order book so the results are not the top 10 , but just last 10 updated in the order book, how to do I get OnLevel2UpdateReceived to return just the TOP 5 or 10 and not items from all over the order book. Essentially what I get is results sometimes matching the latest BID/ASK and sometimes updates to some where far from the the current price. thanks again for helping

dougdellolio commented 6 years ago

@olegboksner according to the docs, there is no way to get just the top 5 or 10 that I can find. Although as I said, I don't believe its expensive to pull the entire book and update everything and just take top 5/10. wish I could provide more help

guanm326 commented 5 years ago

I am wondering how does one track partial fills? What callback is trigger when a partial fill happened?

guanm326 commented 5 years ago

More specifically does partial fills come through as "Done" type from websocket with remaining_size that is not zero? I can't seem to replicate it at all in sandbox exchange..

dougdellolio commented 5 years ago

@guanm326 you can read about the Order Lifecycle here https://docs.pro.coinbase.com/#order-lifecycle. A Done message will be sent for orders which are fully filled and any part of the order not filled immediately will be considered open

ExceedingLife commented 4 years ago

I have been wondering how to get started. Do I need to make my own form or web project and use this api with it? sorry for the noob questions but once i understand more of what i need to do ill get started with it.

dougdellolio commented 4 years ago

@ExceedingLife it really depends on what you would like to do but I would recommend you start by creating a console app with the nuget package installed to get comfortable with the library. From there you can use the code snippets from either the readme or comments above to talk to coinbase pro. The full list of possible actions exists in the documentation here https://docs.pro.coinbase.com/ and they correspond to the services provided in this library https://github.com/dougdellolio/coinbasepro-csharp#what-services-are-provided.

ExceedingLife commented 4 years ago

I want to have it so it can Sell x amount when it drops to a certain price and then if it goes back to a price to be able to buy it back. What do you have? I code in c# daily but i havent done much with APIs. Ill start with a console to learn it like you suggest.

ExceedingLife commented 4 years ago

Hey man, I wanted to ask you this awhile ago, what are you currently using for a GUI with your project? do you have coinbase pro up to see the current data and then have a GUI you made to buy and sell. By the way Stay Safe man, I see your from New York. Sounds scary there at the moment.

dougdellolio commented 4 years ago

@ExceedingLife To be honest, I actually haven't built any front end for my purposes (just console apps), Although, I have talked to others that have built web apps (react/angular) that talk to web services using this library and others that have built full WPF desktop applications. Anything is really possible. I appreciate it and hope you are staying safe too!

ExceedingLife commented 4 years ago

Oh wow lol, I feel like we could make alot of $ with your API. It would be like a limit buy or sell but more advanced. if bitcoin dropped to a certain price sell it (limit sell) but then if it were to raise back up to buy it back so if it goes up alot you dont lose much if any. and otherwise if it were to keep dropping to have it sold so you can buy it back later when its cheaper. basically a limit buy or sell with some if conditions. then when it drops those big amounts you didnt loose anything of if it goes up you have it held onto. I still gotta play with the console app to learn it then im gunna build prob a WPF app with that functionality.

ExceedingLife commented 4 years ago

Wow, I finally took some time yesterday to take a look at this API. (I never used an API before). I built a Console App as you suggested., and wow it was so easy to use! I couldn't believe how easy it was to get going lol. I am going to build my GUI with WPF as I wanted. Maybe eventually ill make 1 on the web. A few questions I have: ProductsService.GetProductOrderBookAsync- What is the difference with the different levels. I noticed one is 1 order, two has more orders, three has the most orders and includes the ID. What does 'ProductsService.GetProductTickerAsync' Do? Get the most recent trade? Also .UserAccountService.GetTrailingVolumeAsync()- I see it gives [ExchangeVolume, ProdID, RecordedAt, Volume] but I wasn't fully understanding it. Also making a new project and calling the Nuget install is that the best way to use it in a project? I haven't used an API b4. Or having the source code and I'm not sure if adding a new project in that file and making my GUI maybe ill have to reference the other project or add usings to get it working with the new project. What would you recommend? Thank you!

ExceedingLife commented 4 years ago

So I have a question. I have everything working in a Console app. Now I'm making a GUI when I call the same method: PlaceStopOrderAsync() I get an error message 'Order Created Exception Invalid length for a Base-64 char array or string'

var response = await coinbaseProClient.OrdersService.PlaceStopOrderAsync ( OrderSide.Buy, ProductType.BtcUsd, order.CryptoAmount, order.LimitPrice, order.StopPrice );

dougdellolio commented 4 years ago

@ExceedingLife for questions where you believe there may be an issue with the library, please add a new github issue so we can discuss on a different thread. I'd like to keep this one related to "Getting Started" only.

I don't seem to have any issues placing stop orders on my end. Make sure you are updated to the latest version through Nuget (v1.0.36). You can also use the examples in the readme to help with placing orders. https://github.com/dougdellolio/coinbasepro-csharp#examples. Regarding your other question, please read Coinbase docs for a description on all endpoints (https://docs.pro.coinbase.com/).

ExceedingLife commented 4 years ago

Ok, Sorry doug, I figured it out as well. I'm LOVING this API.