webcerebrium / java-binance-api

Java Binance API Client
MIT License
73 stars 40 forks source link

ERROR: -1013, Filter failure: PRICE_FILTER #35

Open ben-arnao opened 6 years ago

ben-arnao commented 6 years ago

I'm getting this error even when i've parsed the exchangeInfo api and trimmed my price value to the appropriate asset precision. It's also above the minPrice value as well. Can't seem to find what the problem is. This is the value i am using to create my NANOBTC order with: 9.7504E-4. The base asset preicision for NANOBTC is 8. What am i missing?

BadRookiDev commented 6 years ago

doubles are not stored exactly some times if i am correct. you need to round it. I solved this on a really dirty way:

`public double determineRoundingPrice(String tickSize, double desired){ String decimalformat = ""; String out = ""; char splitter = '"'; String splt = "" + splitter; String[] ssSplitted = tickSize.split(splt); System.out.println("tickSize: "+tickSize); String firstchar = ""+ssSplitted[1].charAt(0); String secondchar = ""+ssSplitted[1].charAt(1);

    if (Objects.equals(firstchar, "0")) {
        System.out.println("ts: " + ssSplitted[1]);
        System.out.println("desired: " + desired);
        String regex = "\\.";
        String[] decimalsSplit = ssSplitted[1].split(regex);
        for (int i = 0; i < decimalsSplit[0].length(); i++) {
            decimalformat += "#";
        }
        decimalformat += ".";

        int amountofhastags = 0;
        for (int i = 0; i < decimalsSplit[1].length(); i++) {
            String one = ""+decimalsSplit[1].charAt(i);
            if (Objects.equals(one, "1")) {
                amountofhastags=i+1;
                i = ssSplitted[1].length();
            }
        }

        for (int i = 0; i < amountofhastags; i++) {
            decimalformat += "#";
        }

        System.out.println(desired);
        DecimalFormat df = new DecimalFormat(decimalformat);
        df.setRoundingMode(RoundingMode.FLOOR);
        String resultString = df.format(desired);
        System.out.println(resultString);
        String[] resultarray = resultString.split(",");
        if (resultarray.length>1) {
            out = resultarray[0] + "." + resultarray[1];
        }
        else if (resultarray.length==1){
            out = resultarray[0];
        }
    }
    else if (Objects.equals(firstchar, "1")){
        int whole = (int) desired;
        System.out.println(whole);
        out = String.valueOf(whole);
        if (Objects.equals(secondchar, "0")){
            String temp = "";
            for (int i = 0; i<out.length()-1; i++){
                temp+=""+out.charAt(i);
            }
            out=temp;
            System.out.println(out);
        }
    }

    double result = Double.parseDouble(out);
    System.out.println(result);
    return result;
}

public String getPriceFilter(String desiredSymbol) { System.out.println(desiredSymbol); String result = ""; BinanceExchangeInfo binanceExchangeInfo = null; try { binanceExchangeInfo = new BinanceApi().exchangeInfo(); List symbols = binanceExchangeInfo.getSymbols(); for (int i = 0; i<symbols.size(); i++) { if (desiredSymbol.equals(symbols.get(i).getBaseAsset() + symbols.get(i).getQuoteAsset())) { result = symbols.get(i).getPriceFilter().get("tickSize").toString(); System.out.println(symbols.get(i).getPriceFilter().toString()); System.out.println(); i=symbols.size(); } } } catch (BinanceApiException e) { e.printStackTrace(); String method = " getPriceFilter"; errors.add( new Error(e.toString()+method, LocalDateTime.now())); } return result; }`

Don't mind the variable names and the print lines! double desired is the inserted price, String tickSize in the first method. is actually the outcome of the method below AKA Price_filter (sorry about that), So thats why i split it up a couple of times.

Keep in mind its a messy solution! (was in a hurry)

ben-arnao commented 6 years ago

For those still have the same issue here's how i solved it...

double validatePrice(double price) {
    if (price < minTradePrice)
        return 0;
    price -= (price - minTradePrice) % tickSize;
    Double toBeTruncated = new Double(price);
    price = BigDecimal.valueOf(toBeTruncated).setScale(assetPrecision, RoundingMode.HALF_UP).doubleValue();
    return price;
}
double validateAmount(double amount, double price) {
    amount -= (amount - minTradeQty) % stepSize;
    if (amount < minTradeQty || amount * price <= minNotional)
        return 0;
    return amount;
}
luxel1103 commented 6 years ago

How do you get the assetPrecision?

if i use: int assetPrecision = client.getExchangeInfo().getSymbolInfo(symbol).getBaseAssetPrecision(); it always returns 8 for every coin.