3s3s / opentrade

OpenTrade - Open Source Cryptocurrency Exchange
MIT License
397 stars 401 forks source link

Scientific Notation Prices #141

Open joenilan opened 6 years ago

joenilan commented 6 years ago

Setting a sell price low like 0.0000005 causes "Price" to show up as scientific notation price

and the trade gets canceled after... however long the timer is. am I doing something wrong?

huuhait commented 6 years ago

toFixed(8) on index.js javascript

joenilan commented 6 years ago

It's already set to that. order.price.toFixed(8)*1 specifically.

Unless you mean by removing the *1

knkrth commented 6 years ago

@3s3s Fix this issue.

joenilan commented 6 years ago

https://github.com/3s3s/opentrade/issues/146#issue-362969753

is the same issue.

MerlinMagic2018 commented 6 years ago

in /opentrade/server/utils.js :+1: exports.roundDown = function(number, decimals) {

try
{
    if (!exports.isNumeric(number)) 
        return number;

    decimals = decimals || 7;       ( COULD THIS BE THE PROBLEM ???? )

    if (!exports.isNumeric(decimals))
        return number;

    const ret =  ( Math.floor( number * Math.pow(10, decimals) ) / Math.pow(10, decimals) )*1;

    return ret; //(ret < 0.000001) ? 0 : ret;
}
catch(e)
{
    return number;
}

}

MerlinMagic2018 commented 6 years ago

in : /opentrade/static_pages/js/utils.js

MakePrice2: function(str) { const roundFull = (3-Math.log10(str1)).toFixed(0)1; const round = roundFull < 0 ? 0 : (roundFull > 8) ? 8 : roundFull; return (utils.MakePrice(str)1).toFixed(round)1; }, MakePrice: function(str) { if (!utils.isNumeric(str)) return 0.0;

    if ((str*1.0).toFixed(8)*1.0 == str*1.0)
        return str*1.0;

    const str0 = str.toString();
    const ret = str0.substring(0, str0.indexOf(".") + 8);

    if ((ret*1.0).toString().length < ret.length)
        return ret*1.0;
    return ret;
},
MerlinMagic2018 commented 6 years ago

I'm haing difficulties understanding this.... But it's as if it rounded to only 6 digits after the dot......

Could it be that it rounds according to string length...... so if its " 0.00000001 " the lenght is above 8 so it dosent round correctly ?

MerlinMagic2018 commented 6 years ago

I can reproduce the problem here :

https://www.w3schools.com/code/tryit.asp?filename=FVLSQC6NXVRN

MerlinMagic2018 commented 6 years ago

And the solution here :

https://www.w3schools.com/code/tryit.asp?filename=FVLSTXGGCGG3

MerlinMagic2018 commented 6 years ago

And the implemented solution here :

https://www.w3schools.com/code/tryit.asp?filename=FVLTE7WAZEUS

joenilan commented 6 years ago

@MerlinMagic2018 does your order go through? say using 0.00000001 or 0.00000002

I've gotten the number to display correctly, but the order just seems to get canceled.

MerlinMagic2018 commented 6 years ago

https://www.w3schools.com/code/tryit.asp?filename=FVLUVRZYRFM1

final implementation..... the order being canceled.... might be due to minimum transaction of 0.00001 .... I changed this value a few places.... I'll get back to you

kifirkin commented 6 years ago

good practice is to use something like https://github.com/MikeMcl/bignumber.js for money arithmetics

MerlinMagic2018 commented 6 years ago

https://www.w3schools.com/code/tryit.asp?filename=FVLX3T45ZA49

MerlinMagic2018 commented 6 years ago

Complicated, not really simplified, but perfect :

https://www.w3schools.com/code/tryit.asp?filename=FVLX76I7GA99

MerlinMagic2018 commented 6 years ago

it's crap... we only need to remove the " 1 " in " .toFixed(8)1 " at a few places in index.js ( /opentrade/static_pages/js/index.js ) I'll post changes here in a few minutes.

It's working now.

MerlinMagic2018 commented 6 years ago

function UpdateBuyComission() { const amount = $('#inputBuyAmount').val() || 0; const price = $('#inputBuyPrice').val() || 0; try { const comission = utils.COMISSIONamountprice; const total = amountprice+comission; $('#inputBuyComission').val(comission.toFixed(8)); // removed both 1 here..... $('#inputBuyTotal').val(total.toFixed(8)); $('#inputBuyTotal').attr('title', 'title'); } catch(e) {}

UpdateHelpers(); }

function UpdateBuyComissionFromTotal() { const total = $('#inputBuyTotal').val()1 || 0.0001; const price = $('#inputBuyPrice').val()1 || 0.0001; try { const amount = (total / (price + utils.COMISSIONprice)).toFixed(8); / ??? / const comission = utils.COMISSIONamountprice; $('#inputBuyComission').val(comission.toFixed(8)); // removed both 1 here $('#inputBuyAmount').val(amount.toFixed(8)); } catch(e) {}

UpdateHelpers(); } function UpdateSellComissionFromTotal() { const total = $('#inputSellTotal').val()1 || 0.0001; const price = $('#inputSellPrice').val()1 || 0.0001; try { const amount = (total / (price + utils.COMISSIONprice)).toFixed(8); / ??? / const comission = utils.COMISSIONamountprice; $('#inputSellComission').val(comission.toFixed(8)); // removed both 1 here... $('#inputSellAmount').val(amount.toFixed(8)); } catch(e) {} //UpdateSellComission();

UpdateHelpers(); }

function UpdateSellComission() { const amount = $('#inputSellAmount').val() || 0; const price = $('#inputSellPrice').val() || 0; try { const comission = utils.COMISSIONamountprice; const total = amountprice+comission; $('#inputSellComission').val(comission.toFixed(8)); // removed both 1 here $('#inputSellTotal').val(total.toFixed(8)); } catch(e) {}

UpdateHelpers(); }

MerlinMagic2018 commented 6 years ago

index.js.txt

just rename this file to index.js and you can see more clearly the changes needed ...

Enjoy !!

joenilan commented 6 years ago

order sends, sits there for... maybe 30 seconds and still cancels.

Note: you've missed up under

function AddOrder(order)
{
  const MC = coinNameToTicker[utils.MAIN_COIN] ? coinNameToTicker[utils.MAIN_COIN].ticker || 'MC' : 'MC'; 
  const bodyModal = 
    '<table class="table">'+
      '<tr>'+
        '<th>Order</th>'+
        '<th>Amount</th>'+
        '<th>Coin</th>'+
        '<th>Price</th>'+
      '</tr>'+
      '<tr>'+
        '<td>'+order.order+'</td>'+
        '<td>'+order.amount.toFixed(8)*1+'</td>'+
        '<td>'+order.coin+'</td>'+
        '<td>'+order.price.toFixed(8)*1+" "+MC+'</td>'+ // This one converts the price on the confirm window
      '</tr>'
    '</table>';

There's more too but I'm going through my index.js atm to find them.

joenilan commented 6 years ago

I've gotten the prices to show up correctly using a working index.js from a working exchange if you go-to an exchange site knowingly using opentrade, just type /js/index.js after the url and you can view the code.

This is without modifying the utils.js

https://pastebin.com/6GBVKBnJ - /opentrade/static_pages/js/utils.js https://pastebin.com/7zZWd7LF - /opentrade/static_pages/js/index.js

This displays the prices correctly but the orders still cancel out.

in /opentrade/server/modules/users/orders.js I believe is where the price and such is submitted to the database. There are alot of < 0.000001 which i've changed to 0.00000001 along with

function AddOrder(status, WHERE, newBalance, req, res, c)
{
    const counter = c || 0;
    if (counter > 5)
        return onError(req, res, 'Coin locked. Please try later');

    const coinName = escape(req.body.coin);    
    if (!g_LockExchange[status.id]) g_LockExchange[status.id] = {};
    if (g_LockExchange[status.id]['lock'])
        return setTimeout(AddOrder, 1000, status, WHERE, newBalance, req, res, counter+1);

    const amount = utils.roundDown(req.body.amount);
    const price = utils.roundDown(req.body.price);
    const balance = utils.roundDown(newBalance*1);

    if (!utils.isNumeric(amount) || !utils.isNumeric(price) || !utils.isNumeric(balance) ||
        amount <= 0 || price <= 0 || balance < 0) 
    {
        return onError(req, res, 'Bad amount or price or balance');
    }

    const uuid = Date.now()+"-"+status.id+"-"+Math.random();
    const log = [{action: "init", amount: amount, price: price, time: Date.now()}];

    if (require("./orderupdate").IsLockedUser(status.id)) return onError(req, res, 'User is locked for orders');

    g_LockExchange[status.id]['lock'] = true;
    require("./balanceupdate").UpdateBalance(status.id, unescape(req['queryCoin']), balance, "AddOrder", err => {
        if (err) 
        {
            g_LockExchange[status.id]['lock'] = false;
            return onError(req, res, 'Update balance error');
        }

        g_constants.dbTables['orders'].insert(
            status.id,
            req.body.coin,
            req.body.order,
            amount,
            price.toFixed(8), //ADDED THIS SO IT DOESN'T SUBMIT 5e-7 type numbers
            g_constants.share.TRADE_MAIN_COIN,
            Date.now(),
            JSON.stringify(log),
            uuid,
            err => {
                g_LockExchange[status.id]['lock'] = false;

               // if (status.id == 2 && req.body.coin == "Bitcoin")
               //     utils.balance_log('Call FixBalance from AddOrder amount='+amount+" balance="+balance);

                adminUtils.FixBalance(status.id, escape(req.body.coin), () => {});

                if (err) 
                    return onError(req, res, err.message || 'Database Insert error');

                wallet.ResetBalanceCache(status.id);
                if (allOrders[req.body.coin]) delete allOrders[req.body.coin];
                if (userOrders[status.id])
                    delete userOrders[status.id];

                return onSuccess(req, res, {uuid: uuid});
            }
        );
    });
}

Specifically

g_constants.dbTables['orders'].insert(
            status.id,
            req.body.coin,
            req.body.order,
            amount,
            price.toFixed(8), //ADDED THIS SO IT DOESN'T SUBMIT 5e-7 type numbers
            g_constants.share.TRADE_MAIN_COIN,
            Date.now(),
            JSON.stringify(log),
            uuid,

This does NOT fix it but it does seem to send the correct price to the DB

joenilan commented 6 years ago

https://github.com/3s3s/opentrade/issues/153#issuecomment-424470646

@3s3s can you help me?

Just change this constant https://github.com/3s3s/opentrade/blob/master/server/constants.js#L20

in /opentrade/server/constants.js

   DUST_VOLUME: 0.00000001, //DUST_VOLUME: 0.000001,

this seems to sort of do it.

mixed in with the index.js and utils.js modifications

/opentrade/server/utils.js

exports.roundDown = function(number, decimals) {

    try
    {
        if (!exports.isNumeric(number)) 
            return number;

        decimals = decimals || 8; // from 7 to 8

        if (!exports.isNumeric(decimals))
            return number;

        const ret =  ( Math.floor( number * Math.pow(10, decimals) ) / Math.pow(10, decimals) )*1;

        return ret; //(ret < 0.000001) ? 0 : ret;
    }
    catch(e)
    {
        return number;
    }
}

0.00000002 seems to stick, but not 0.00000001

MerlinMagic2018 commented 6 years ago

I knew it already, had done the same changes !! lol

yeah I guess DUST_VOLUME is to limit small transactions...

and yes, an order of 0.00000001 won't stick, and 0.00000002 will.

Also, I suggest searchmonkey ( sudo apt install searchmonkey ) on ubuntu to search through directories for a particular string.... ( like the famous : " toFixed(8)*1 " ) hehe....

But the prices in user orders will still be scientific notation.... still need to find where this one is...

joenilan commented 6 years ago

I knew it already, had done the same changes !! lol

yeah I guess DUST_VOLUME is to limit small transactions...

and yes, an order of 0.00000001 won't stick, and 0.00000002 will.

Also, I suggest searchmonkey ( sudo apt install searchmonkey ) on ubuntu to search through directories for a particular string.... ( like the famous : " toFixed(8)*1 " ) hehe....

But the prices in user orders will still be scientific notation.... still need to find where this one is...

lol nice, I just use sublime text right click on root folder and "Find in Folder", similar.

BUT with that said, doing a dust volume of 0.000000009 lets 0.00000001 stick, not even sure if that's right in general to be honest hah... it seems to stick but the orders don't go through, the buy order won't buy the sell order... both just sit in sell and buy.

0.00000002 Orders Buying and Selling works.

cryptonana commented 6 years ago

@joenilan problem solve or not i get this error when trade buy or sell Bad order price ( price < 0.00001 ) ( 1e-8 < 0.00001 )

MerlinMagic2018 commented 6 years ago

Problem not solved... Need a few updates for scientific notation to be replaced everywhere... But setting dust price to 0.000000001 makes transactions of 0.00000001 to be registered correctly. Have to move today but I'll try to check this out before tomorrow

zoowcoin commented 5 years ago

I have same problem, what are the solutions? I want change limit of price of 0.00001 to 0.000001