JKorf / Binance.Net

A C# .netstandard client library for the Binance REST and Websocket Spot and Futures API focusing on clear usage and models
https://jkorf.github.io/Binance.Net/
MIT License
1.02k stars 421 forks source link

RestClient PlaceOrder #740

Closed ZigmundL closed 3 years ago

ZigmundL commented 3 years ago

Describe the bug restClient.Spot.Order.PlaceOrder("BTCUSDT", OrderSide.Buy, OrderType.Market, 0.1) returns null. Sometimes it places order and returns null but most of the time null is returned and order is not placed. It does not happen every time, but when some time has passed, it happens. KeepAliveUserStream is working fine.

To Reproduce

WebCallResult<BinancePlacedOrder> result = null;
try
{
    result = restClient.Spot.Order.PlaceOrder("BTCUSDT", OrderSide.Buy, OrderType.Market, 0.1);
    if (result.Success)
    {
         return result.Data.OrderId;
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message); --- Object reference not set to an instance of an object.
}

Expected behavior WebCallResult != null is returned, so Success or Error can be checked

ZigmundL commented 3 years ago

if (result.Success) this line causes null pointer exception if result is null.

ZigmundL commented 3 years ago

How is that possible I'm not using the client? It is stated that it works most of the time, the problem happens after a few hours or so. I use RestClient as a static object which does KeepAlive requests and places orders. Your example will not work if result is null, you can't reference Success of a null object. I've checked that restclient it is not null, but result is. WebCallResult must be [return: NotNull]. I'm using this code for a period of time, and the problem appeared after update.

ZigmundL commented 3 years ago

Very interesting info, thx. It seems to me a little wierd to create a new instance of restclient for every request. I thought that one object would be enough. Like you create a single instance, and use it so send different requests. That is what I was doing. I'm testing your examples with using and multiple restclients at the moment.

JKorf commented 3 years ago

Just to be clear, using it either way is fine, the client is threadsafe. Using either a single instance or an instance in a using statement per request is fine.

If you're stilling having a nullreference exception, have a look at the stack trace to see where it comes from

naserkaka commented 3 years ago

95999FRSER999EBBSBSSS8EsSTer Hi, I have the same problem as Zigmundl and I have tried everything in this thread.

I get the error : No Credential provided for private end point

I have tried both placeorder and placetestorder

naserkaka commented 3 years ago

95999FRSER999EBBSBSSS8EsSTer Hi, I have the same problem as Zigmundl and I have tried everything in this thread.

I get the error : No Credential provided for private end point

I have tried both placeorder and placetestorder

the api key and secret is from binance testnet https://testnet.binance.vision/

ZigmundL commented 3 years ago

I've switched to "Using Statements" and the problem has gone. I suppose something wrong with thread safety when RestClient is used as a static object (single instance).

naserkaka commented 3 years ago

@ZigmundL Did`nt I used the "Using Statements" correct on line 58? Where do I need to change?

naserkaka commented 3 years ago

orgs2388187 Hi everyone, it finaly worked! my mistake was that I used test API key and secret with wrong URL. I changed the url to testnet-url, on line 27.

svanmoerkerke commented 3 years ago

I have the same problem, one in 5 executions of client.Spot.Order.PlaceOrder results in a "Object reference not set to an instance of an object" error? I'm using the code in an Azure Function triggered via http

And yes, i'm using the Using statement.

any ideas?

        BinanceClient.SetDefaultOptions(new BinanceClientOptions()
            {
                ApiCredentials = new ApiCredentials(binanceKey, binanceSecret),
                LogVerbosity = LogVerbosity.Error,
                LogWriters = new List<TextWriter> { Console.Out },
                TradeRulesBehaviour = TradeRulesBehaviour.AutoComply,
                RequestTimeout = new TimeSpan(0, 0, 0, 0, 10000),
                ReceiveWindow = new TimeSpan(0, 0, 0, 0, 1000),
                RateLimitingBehaviour = CryptoExchange.Net.Objects.RateLimitingBehaviour.Fail
            });

`

           using (var client = new BinanceClient())
            {
                aantalEuros = client.General.GetAccountInfo().Data.Balances.First(b => b.Asset == baseCurrency).Free;
                aantalCoins = client.General.GetAccountInfo().Data.Balances.First(b => b.Asset == strCoin).Free;
                laatsteAsk = client.Spot.Market.GetOrderBook(strTradeSymbol).Data.Asks.ToList()[0].Price;
                laatsteBid = client.Spot.Market.GetOrderBook(strTradeSymbol).Data.Bids.ToList()[0].Price;
                if((strAction == "BUY" || strAction == "BUYTEST"))
                {
                    laatsteAskBid = laatsteAsk;
                    decMarge = 0.0m;
                    PriceBuySell = Math.Round(laatsteAsk * (1+decMarge),intCijfersNaKommaPrice);
                    dAantalCoinsBuySell = Math.Round(dEuroLimit/PriceBuySell,intCijfersNaKommaVolume);
                    if(dAantalCoinsBuySell*PriceBuySell>aantalEuros) dAantalCoinsBuySell = Math.Round(aantalEuros/PriceBuySell,intCijfersNaKommaVolume);
                    bBuyOrSell = true;                  
                }
                if(strAction == "SELL" || strAction == "SELLTEST")
                {
                    laatsteAskBid = laatsteBid;
                    PriceBuySell = Math.Round(laatsteBid * (1-decMarge),intCijfersNaKommaPrice);
                    dAantalCoinsBuySell = Math.Round(dEuroLimit/PriceBuySell,intCijfersNaKommaVolume);
                    if(dAantalCoinsBuySell>aantalCoins) dAantalCoinsBuySell = aantalCoins;
                    bBuyOrSell = true;

                }
                decimal decBedrag = dAantalCoinsBuySell*PriceBuySell;
                if(decBedrag < intOrderMinEuro)
                {
                    log.LogInformation("Order bedrag te laag: " + decBedrag);
                }
                else if(bBuyOrSell && (strAction == "BUY"))
                {
                    var buyOrderId = client.Spot.Order.PlaceOrder(strTradeSymbol, OrderSide.Buy, OrderType.Market, dAantalCoinsBuySell, null, null, null, null).Data.OrderId; 
                }
                else if(bBuyOrSell && (strAction == "SELL"))
                {
                    var buyOrderId = client.Spot.Order.PlaceOrder(strTradeSymbol, OrderSide.Sell, OrderType.Market, dAantalCoinsBuySell, null, null, null, null).Data.OrderId;
                }
            }`
svanmoerkerke commented 3 years ago

That's all i'm getting from debuggin locally my Azure Function after a couple of runs, so sometimes it runs fine and places the order, and sometime it breaks:

Exception has occurred: CLR/System.NullReferenceException Exception thrown: 'System.NullReferenceException' in BinanceBot.dll: 'Object reference not set to an instance of an object.' at CryptoBotBinance.HttpTriggerBinance.d__11.MoveNext() in /Users/stig/Documents/vscode/BinanceBot/HttpTriggerBinance.cs:line 128

BinanceBot.dll!CryptoBotBinance.HttpTriggerBinance.Run(Microsoft.AspNetCore.Http.HttpRequest req, Microsoft.Extensions.Logging.ILogger log) Line 128 (/Users/stig/Documents/vscode/BinanceBot/HttpTriggerBinance.cs:128) [External Code] (Unknown Source:0) [Resuming Async Method] (Unknown Source:0) [External Code] (Unknown Source:0) [Async Call Stack] (Unknown Source:0) [External Code] (Unknown Source:0)

this is line 128: var buyOrderId = client.Spot.Order.PlaceOrder(strTradeSymbol, OrderSide.Buy, OrderType.Market, dAantalCoinsBuySell, null, null, null, null).Data.OrderId;

strTradeSymbol = "TRUUSDT" strEuroLimit = "750" dAantalCoinsBuySell = 3444.33662

svanmoerkerke commented 3 years ago

look, tried 4x the same execution, only the last got executed: 2021-06-27T09:57:56 Welcome, you are now connected to log-streaming service. The default timeout is 2 hours. Change the timeout with the App Setting SCM_LOGSTREAM_TIMEOUT (in seconds). 2021-06-27T09:57:58.645 [Information] Executing 'HttpTriggerBinance' (Reason='This function was programmatically called via the host APIs.', Id=01296fd5-22c5-4880-87a5-0f03bb9f1dbc) 2021-06-27T09:57:58.648 [Information] C# HTTP trigger function processed a request. 2021-06-27T09:57:58.648 [Information] {"coin":"STPT","action":"BUY","eurolimit":1000} 2021-06-27T09:57:59.628 [Information] aantalEuros: 469.46308120 2021-06-27T09:58:00.326 [Information] ticker STPT, ask: 0.03439000, bid: 0.03428000 2021-06-27T09:58:00.326 [Information] bBuyOrSell: True 2021-06-27T09:58:00.327 [Information] strAction: BUY 2021-06-27T09:58:00.327 [Information] strTradeSymbol: STPTUSDT 2021-06-27T09:58:00.327 [Information] dAantalCoinsBuySell: 13651.15095 2021-06-27T09:58:03.325 [Error] Executed 'HttpTriggerBinance' (Failed, Id=01296fd5-22c5-4880-87a5-0f03bb9f1dbc, Duration=4659ms)Object reference not set to an instance of an object. 2021-06-27T09:58:07.703 [Information] Executing 'HttpTriggerBinance' (Reason='This function was programmatically called via the host APIs.', Id=c632d2a2-2b27-4b0f-912e-023fe9d013f4) 2021-06-27T09:58:07.703 [Information] C# HTTP trigger function processed a request. 2021-06-27T09:58:07.703 [Information] {"coin":"STPT","action":"BUY","eurolimit":1000} 2021-06-27T09:58:08.439 [Information] aantalEuros: 469.46308120 2021-06-27T09:58:09.122 [Information] ticker STPT, ask: 0.03439000, bid: 0.03428000 2021-06-27T09:58:09.122 [Information] bBuyOrSell: True 2021-06-27T09:58:09.122 [Information] strAction: BUY 2021-06-27T09:58:09.123 [Information] strTradeSymbol: STPTUSDT 2021-06-27T09:58:09.123 [Information] dAantalCoinsBuySell: 13651.15095 2021-06-27T09:58:11.903 [Error] Executed 'HttpTriggerBinance' (Failed, Id=c632d2a2-2b27-4b0f-912e-023fe9d013f4, Duration=4178ms)Object reference not set to an instance of an object. 2021-06-27T09:58:19.083 [Information] Executing 'HttpTriggerBinance' (Reason='This function was programmatically called via the host APIs.', Id=4284157a-7a8e-4fe3-969b-70582ea201f9) 2021-06-27T09:58:19.083 [Information] C# HTTP trigger function processed a request. 2021-06-27T09:58:19.083 [Information] {"coin":"STPT","action":"BUY","eurolimit":1000} 2021-06-27T09:58:20.053 [Information] aantalEuros: 469.46308120 2021-06-27T09:58:20.739 [Information] ticker STPT, ask: 0.03439000, bid: 0.03427000 2021-06-27T09:58:20.739 [Information] bBuyOrSell: True 2021-06-27T09:58:20.739 [Information] strAction: BUY 2021-06-27T09:58:20.739 [Information] strTradeSymbol: STPTUSDT 2021-06-27T09:58:20.739 [Information] dAantalCoinsBuySell: 13651.15095 2021-06-27T09:58:22.318 [Error] Executed 'HttpTriggerBinance' (Failed, Id=4284157a-7a8e-4fe3-969b-70582ea201f9, Duration=3199ms)Object reference not set to an instance of an object. 2021-06-27T09:58:24.186 [Information] Executing 'HttpTriggerBinance' (Reason='This function was programmatically called via the host APIs.', Id=762e269d-ef5d-4c66-9a51-9da82c5c09be) 2021-06-27T09:58:24.186 [Information] C# HTTP trigger function processed a request. 2021-06-27T09:58:24.186 [Information] {"coin":"STPT","action":"BUY","eurolimit":1000} 2021-06-27T09:58:24.923 [Information] aantalEuros: 469.46308120 2021-06-27T09:58:25.607 [Information] ticker STPT, ask: 0.03439000, bid: 0.03427000 2021-06-27T09:58:25.607 [Information] bBuyOrSell: True 2021-06-27T09:58:25.607 [Information] strAction: BUY 2021-06-27T09:58:25.607 [Information] strTradeSymbol: STPTUSDT 2021-06-27T09:58:25.607 [Information] dAantalCoinsBuySell: 13651.15095 2021-06-27T09:58:26.826 [Error] Executed 'HttpTriggerBinance' (Failed, Id=762e269d-ef5d-4c66-9a51-9da82c5c09be, Duration=2613ms)Object reference not set to an instance of an object. 2021-06-27T09:58:32.139 [Information] Executing 'HttpTriggerBinance' (Reason='This function was programmatically called via the host APIs.', Id=cec671a5-3eff-4aca-908c-11e14ac55681) 2021-06-27T09:58:32.139 [Information] C# HTTP trigger function processed a request. 2021-06-27T09:58:32.139 [Information] {"coin":"STPT","action":"BUY","eurolimit":1000} 2021-06-27T09:58:32.882 [Information] aantalEuros: 469.46308120 2021-06-27T09:58:33.560 [Information] ticker STPT, ask: 0.03439000, bid: 0.03427000 2021-06-27T09:58:33.560 [Information] bBuyOrSell: True 2021-06-27T09:58:33.570 [Information] strAction: BUY 2021-06-27T09:58:33.570 [Information] strTradeSymbol: STPTUSDT 2021-06-27T09:58:33.570 [Information] dAantalCoinsBuySell: 13651.15095 2021-06-27T09:58:35.398 [Information] action: BUY, aantal coins: 0.00000000, AantalCoinsBuySell: 13651.15095, aantal euro: 469.46308120, PriceBuySell: 0.03439, laatsteAskBid: 0.03439000 2021-06-27T09:58:35.399 [Information] Executed 'HttpTriggerBinance' (Succeeded, Id=cec671a5-3eff-4aca-908c-11e14ac55681, Duration=3260ms)

JKorf commented 3 years ago

You're not checking any result if it was successfull. If you call for example GetAccountInfo you'll have to check if the call was successful by doing something like this:

var accountInfoResult = client.General.GetAccountInfo();
if(!accountInfoResult.Success)
{
  // Handle error, the accountInfoResult.Error property will have more details on what went wrong
  return;
}

var data = accountInfoResult.Data;

Checking it like this will guarentee that data is never null. If the call fails for some reason then client.General.GetAccountInfo().Data.Balances will throw an exception because the Data property is null.

svanmoerkerke commented 3 years ago

ok, thanks, i'll change the code as you proposed

naserkaka commented 3 years ago

Hi, when I runt my code from Program.cs with BinanceNet binance = new BinanceNet(); await binance.StreamPrice(); I get only one price stream and then the program stops. REEBBESUBSSYHOSY39898089899833

 

naserkaka commented 3 years ago

this is the result

New Note

JKorf commented 3 years ago

https://github.com/JKorf/CryptoExchange.Net/tree/feature/replace-websocket4net#faq

naserkaka commented 3 years ago

Thanks @JKorf but I solved it just by writing Console.ReadLine(); at the end of the method, on line 87. Do I always need the Console.ReadLine(); ?

JKorf commented 3 years ago

No, the issue is your socket client gets disposed after the method is finished. You need to keep track of the socket client instance by assigning it to a field/property outside of the method. Which is what the FAQ tells you to do

naserkaka commented 3 years ago

@JKorf I did it like the FAQ but the client still get disposed. You see me private BinanceSocketClient SocketClient, is outside the test-method; I call the the method with await binancenet.test(); Connected Services

JKorf commented 3 years ago

I don't know enough about your program to answer this. Are you sure your application doesn't just end? Anyway, please open a new issue if you have a problem, don't hijack other peoples issues.