Search code examples
javascriptfirebasefirebase-realtime-databasefirebase-admin

Firebase Realtime Database Query is not working with larger number


I am making query for my orders list, here is the data structure and my database rules: enter image description here

enter image description here

I use a query like this to find out whether the latest price hit the tp or sl price like this:

function GetBuyList(symbol, currentPrice) {
    //Less than or equal to, for buying search tp lesser than current price
    var buy_tp = db.ref(`orders/active_orders/${symbol}`).orderByChild("tp").startAt(`buy_tp_${0}`).endAt(`buy_tp_${currentPrice}`)

    //More than or equal to, for buying search sl higher than current price
    var buy_sl = db.ref(`orders/active_orders/${symbol}`).orderByChild("sl").startAt(`buy_sl_${currentPrice}`).endAt(`buy_sl_${100000000}`)

    buy_tp.once("value", function (snapshot) {
        // do some stuff once
        if (snapshot.val() !== null) {
            ProcessOrders(snapshot.val(), 'tpHit', currentPrice)
        }
    });

    buy_sl.once("value", function (snapshot) {
        // do some stuff once
        if (snapshot.val() !== null) {
            ProcessOrders(snapshot.val(), 'slHit', currentPrice)
        }
    });
}

For price that is in lower value like 1.211, it working fine, but when the price goes larger, the buy_sl query is not working, but the buy_tp query is still working fine. Example, when I query for the price like 34886 for the data below the buy_sl is not working:

enter image description here

Edit: Hi Frank, herein the json exported:

{
  "active_orders" : {
    "BTCUSD" : {
      "-Masii03kq9LvuLfWOyG" : {
        "close_type" : "None",
        "lot_size" : 1,
        "order_price" : 34888.17,
        "sl" : "buy_sl_34887",
        "symbol" : "BTCUSD",
        "tp" : "buy_tp_34889",
        "ts" : 1622301925456,
        "type" : "buy",
        "uid" : "6XaKYgXCsuMNg1d5bWYHg6ej5sd2"
      }
    },
    "EURUSD" : {
      "-MasVPCtD4sdPCcdF9S9" : {
        "close_type" : "None",
        "lot_size" : 1,
        "order_price" : 1.211,
        "sl" : "buy_sl_1.210",
        "symbol" : "EURUSD",
        "tp" : "buy_tp_1.23",
        "ts" : 1622298174339,
        "type" : "buy",
        "uid" : "6XaKYgXCsuMNg1d5bWYHg6ej5sd2"
      }
    },
    "USDJPY" : {
      "-MasWoRREHQhvOR6iQ8G" : {
        "close_type" : "None",
        "lot_size" : 1,
        "order_price" : 109.861,
        "sl" : "buy_sl_107.0",
        "symbol" : "USDJPY",
        "tp" : "buy_tp_110",
        "ts" : 1622298543910,
        "type" : "buy",
        "uid" : "6XaKYgXCsuMNg1d5bWYHg6ej5sd2"
      }
    }
  }
}

Example, when I perform the function GetBuyList("EURUSD", 1.3) or GetBuyList("EURUSD", 1.1), the result returned as:

{
  '-MasVPCtD4sdPCcdF9S9': {
    close_type: 'None',
    lot_size: 1,
    order_price: 1.211,
    sl: 'buy_sl_1.210',
    symbol: 'EURUSD',
    tp: 'buy_tp_1.23',
    ts: 1622298174339,
    type: 'buy',
    uid: '6XaKYgXCsuMNg1d5bWYHg6ej5sd2'
  }
}

When I perform the function like this, GetBuyList("BTCUSD", 34890), it would return:

{
  '-Masii03kq9LvuLfWOyG': {
    close_type: 'None',
    lot_size: 1,
    order_price: 34888.17,
    sl: 'buy_sl_34887',
    symbol: 'BTCUSD',
    tp: 'buy_tp_34889',
    ts: 1622301925456,
    type: 'buy',
    uid: '6XaKYgXCsuMNg1d5bWYHg6ej5sd2'
  }
}

But when I run this, GetBuyList("BTCUSD", 34886), nothing is return.


Solution

  • sl and tp are both strings and because they are, they won't be parsed as numbers and instead are subject to lexiographic sorting.

    One of the most common examples of this happening is if you look at a file list in a folder:

    0.jpg
    1.jpg
    10.jpg
    11.jpg
    12.jpg
    2.jpg
    3.jpg
    4.jpg
    5.jpg
    6.jpg
    7.jpg
    8.jpg
    9.jpg
    

    If you can't switch from using strings, you need to pad the number with your expected maximum number:

    000.jpg
    001.jpg
    002.jpg
    003.jpg
    004.jpg
    005.jpg
    006.jpg
    007.jpg
    008.jpg
    009.jpg
    010.jpg
    011.jpg
    012.jpg
    
    const formatWithPadding = (inp, digits) => {
      let n = Number(inp), nStr = `${Math.abs(n)}`, sign = n<0;
      return (sign ? '+' : '-') + (
        nStr.length > digits
          ? nStr
          : `${"0".repeat((digits || 1) - 1)}${nStr}`.slice(-digits)
      )
    };
    
    const tpVal = 1.210;
    const [integerPart, fractionalPart] = String(tpVal).split(".");
    const tp = `buy_tp_${formatWithPadding(integerPart, 6)}.${fractionalPart || 0}`;
    
    // tp is "buy_tp_+000001.210"