jaggedsoft / node-binance-api

Node Binance API is an asynchronous node.js library for the Binance API designed to be easy to use.
MIT License
1.58k stars 767 forks source link

Futures trading placing a take profit and a stop loss #776

Open cosmicdust471 opened 2 years ago

cosmicdust471 commented 2 years ago

Hello everyone, I've been using node-binance-api API for a long time.

On the spot market, i've been placing a base order and susequently placing an OCO order for my take profit & stop loss.

Base order

await binance.buy('ETHUSDT', 0.005, 3800,{
    timeInForce: 'GTC'
});

Take profit & Stop Loss

await binance.sell('SELL', 'ETHUSDT', 0.005, 3900, { 
    type:'OCO', 
    stopLimitPrice: 3700,
    stopPrice: 3700,
    timeInForce: 'GTC'
});

However moving into the futures market, I can't seem to replicate this functionallity.

Base order:

await binance.futuresBuy('ETHUSDT',0.005,3800,{
    timeInForce: 'GTC'
});

Stop loss order:

await binance.futuresSell('ETHUSDT',0.005,3700,{
    timeInForce: 'GTC'
    stopPrice: 3700
    type: 'STOP'
});

Take profit order:

await binance.futuresSell('ETHUSDT',0.005,3900,{
    timeInForce: 'GTC'
    stopPrice: 3900
    type: 'TAKE_PROFIT'
});

And I end up with this on Binance: orders position

As you can see, the are stop loss & take profit orders are there, but they are in no way linked to one another (As shown in the position). And if one is executed, the other will persist (In this case acting as a short). I know I can close the other once one is executed, but I wanted to know i there is a right way to do this.

I don't see the option to open an OCO order in futures, am I missing something?

Is there a way to open a position with a stop loss and take profit?

NivEz commented 2 years ago

I had the same doubt and opened an issue about it not too long ago. As far as I know there is not support for OCO order type in the binance futures API. I guess the work around is to use the socket streams to catch the changes.

cosmicdust471 commented 2 years ago

Its kind of odd, because on Binance's GUI there is an option to set TP/SL for a position.

image

Anyway I have it working with this workaround for now. The position is closed whenever the TP/SL is reached, however, if TP was reached, the SL will stay open and if the price reaches it, a new position is opened, so I fear a bug on my could leave an open order unchecked, wich is preatty scray.

With OCO orders on the spot market, I can rest assure that no matter what happens on my side, the trade will play out as expected, with TP/SL executed.

If anyone knows a better way, any help is appreciated.

NivEz commented 2 years ago

Its kind of odd, because on Binance's GUI there is an option to set TP/SL for a position.

image

Anyway I have it working with this workaround for now. The position is closed whenever the TP/SL is reached, however, if TP was reached, the SL will stay open and if the price reaches it, a new position is opened, so I fear a bug on my could leave an open order unchecked, wich is preatty scray.

With OCO orders on the spot market, I can rest assure that no matter what happens on my side, the trade will play out as expected, with TP/SL executed.

If anyone knows a better way, any help is appreciated.

Did you work with the spot API? I think the futures support is better. I am kinda struggling with execution of simple market orders in the spot API. Can you help me with that? I am trying just to market buy and sell (no limits / tp / sl...) for now. Can you send me a snippet of code of the implementation? I can't parse the error / response objects... I am available on Telegram if it more convenient for you.

cosmicdust471 commented 2 years ago

Yes, I have the spot API working in production for a couple of months, I'm actually getting started in the futures market right now. I'll send you a full snippet of the Spot setup in a couple of minutes.

cosmicdust471 commented 2 years ago

First we initialize de Binance client. I sugest you use async await, it will make your life much easier.

const Binance = require('node-binance-api');
const binance = new Binance().options({
    APIKEY: 'YOUR API KEY',
    APISECRET: 'YOUR API SECRET',
    useServerTime: true,
    recvWindow: 60000,
    verbose: true
});

Then, we need some information about the pairs we'll be trading, like pricePrecision, quantityPrecision and minNotional. This is because when we place an order to buy BTC with USDT, the quantity parameter for example can have up to 5 decimal places, the price parameter up to 2 decimal places, and the minimum order can be of 10 USDT. Each pair has its own parameters, so we call exchangeInfo to extract that information. (If you don't follow this parameters, you'll end up with a lot of unwanted errors).

await binance.exchangeInfo();
//You'll actually need to dig through this to get the information needed

Then to place a order we just call binance.marketBuy or binance.marketSell to place a market order.

//BUY
await binance.marketBuy('BTCUSDT',0.00025);
//SELL
await binance.marketSell('BTCUSDT',0.00025);

You can set the request to a variable to see the output of the order (Don't forget the await)

var order = await binance.marketBuy('BTCUSDT',0.00025);
console.log(order);

We can also call binance.buy or binance.sell to place a limit order. In this case our order will be executed when the price reaches 40.000.

//BUY
await binance.buy('BTCUSDT',0.00025,40000.00);
//SELL
await binance.sell('BTCUSDT',0.00025,40000.00);

OCO orders are a bit more complex, so I suggest you get started with this.

To catch the errors (And read them) I always envolve my funcions in a try catch like so:

try {
    //Binancy code
} catch(error) {
    //Some errors are illegible, I think the plugin uses axios
    //So I check to see if the error has a body, 
    if (error.body) {
        //If it does, I parse it and output it
        error.body = JSON.parse(error.body);
        console.log(error.body)
    } else {
        //If it does not, I just output the whole error
        console.log(error)
    }
}

Let me know how this goes!

NivEz commented 2 years ago

First we initialize de Binance client. I sugest you use async await, it will make your life much easier.

const Binance = require('node-binance-api');
const binance = new Binance().options({
  APIKEY: 'YOUR API KEY',
  APISECRET: 'YOUR API SECRET',
  useServerTime: true,
      recvWindow: 60000,
      verbose: true
});

Then, we need some information about the pairs we'll be trading, like pricePrecision, quantityPrecision and minNotional. This is because when we place an order to buy BTC with USDT, the quantity parameter for example can have up to 5 decimal places, the price parameter up to 2 decimal places, and the minimum order can be of 10 USDT. Each pair has its own parameters, so we call exchangeInfo to extract that information. (If you don't follow this parameters, you'll end up with a lot of unwanted errors).

await binance.exchangeInfo();
//You'll actually need to dig through this to get the information needed

Then to place a order we just call binance.marketBuy or binance.marketSell to place a market order.

//BUY
await binance.marketBuy('BTCUSDT',0.00025);
//SELL
await binance.marketSell('BTCUSDT',0.00025);

You can set the request to a variable to see the output of the order (Don't forget the await)

var order = await binance.marketBuy('BTCUSDT',0.00025);
console.log(order);

We can also call binance.buy or binance.sell to place a limit order. In this case our order will be executed when the price reaches 40.000.

//BUY
await binance.buy('BTCUSDT',0.00025,40000.00);
//SELL
await binance.sell('BTCUSDT',0.00025,40000.00);

OCO orders are a bit more complex, so I suggest you get started with this.

To catch the errors (And read them) I always envolve my funcions in a try catch like so:

try {
    //Binancy code
} catch(error) {
    //Some errors are illegible, I think the plugin uses axios
    //So I check to see if the error has a body, 
    if (error.body) {
        //If it does, I parse it and output it
        error.body = JSON.parse(error.body);
        console.log(error.body)
    } else {
        //If it does not, I just output the whole error
        console.log(error)
    }
}

Let me know how this goes!

Thanks a lot! I appreciate it. I will let you know if it goes well or not.

NivEz commented 2 years ago

Hey again 👋. So I played with it a little bit. What do you think about my implementation of OCO order: Please let me know :)

const buy = async () => {
    try {
        const res = await binance.marketBuy('ADAUSDT', 10);
        console.log(res)
    } catch (error) {
        if (error.body) {
            error.body = JSON.parse(error.body);
            console.log(error.body)
        } else {
            console.log(error)
        }
    }
}

const sellOco = async () => {
    try {
        const res = await binance.order('SELL', 'ADAUSDT', 10, 1.350, {
            type: 'OCO',
            stopPrice: 1.334,
            stopLimitPrice: 1.335
        })
        console.log(res)
    } catch (error) {
        if (error.body) {
            error.body = JSON.parse(error.body);
            console.log(error.body)
        } else {
            console.log(error)
        }
    }
}

buy();
...waits for buy function to finish if no errors execute sellOco... (future logic just checking OCO now)
sellOco();
cosmicdust471 commented 2 years ago

Hey there! Yes I have OCO orders working on the Spot Market, and your method is fine.

However I don't seem to find any documentation about them on the Futures Market.

Anyone managed to set TP/SL or place OCO orders on the Futures Market?

ordimans commented 2 years ago

Not sure about OCO because i didn't use. But on futures, i can place a SL, and it correctly displayed on the desktop app.

Just use futuresBuy or futuresSell, with STOP_MARKET price, and it work. FOr me :

let params = {type:'STOP_MARKET',closePosition:true,stopPrice:price,positionSide:type,timeInForce:'GTC',newClientOrderId:orderID}

About TP it's probably same, with TAKE_PROFIT, but i didn't use, because i have several TP. and i think closePosition is required, because that's what desktop app do when you use this interface.

Blaag28 commented 2 years ago

Here I wrote how I managed to set the limit and stop loss

786