pythonalgorithmic-tradingtradingbinanceccxt

Transfer USDT between spot and futures in Binance using ccxt python


exchange =   ccxt.binance({
--
"apiKey": 'xxx',
"secret": 'xxx',
'options': {
'adjustForTimeDifference': True
},
'enableRateLimit': True
})
 
exchange_f = ccxt.binance({
"apiKey": 'yyy',
"secret": 'yyy',
'options': {
'defaultType': 'future',
'adjustForTimeDifference': True
},
'enableRateLimit': True
})

exchange.load_markets()
exchange_f.load_markets()

#some calculations here

 if np.sum(sell_long_1) > 0:
            exchange.create_market_sell_order("ETH/USDT", np.sum(sell_long_1))
        elif np.sum(sell_short_1) < 0:
            exchange_f.create_market_buy_order("ETH/USDT", -np.sum(sell_short_1))
            account_balance_f = exchange_f.fetch_balance()['free']['USDT']
            exchange.sapi_post_futures_transfer({
                'asset': 'USDT',
                'amount': account_balance_f,
                'type': 2
            })

Hello, I am doing algotrading with Python. Let me try to explain my problem:

  1. Due to the funding rates in binance, i am taking long positions in spot market and taking short positions in futures market.
  2. My code always trasfer the free USDT to spot balance. If there is no position, USDT will be always in spot wallet.
  3. When i want to take short postion, the code transfers the USDT to futures wallet and open short position in ETH / USDT Perpetual market. After it closes the short positions in ETH/USDT futures market, the code transfers the free USDT to spot wallet.
  4. So let's say that i am in full short position. And then half of the short positions are triggered to close. The code is closing half of the short positions and with above code it is checking the free USDT amount in futures wallet. Let's say that after closing the half of positions, free USDT balance in futures wallet is 100 USDT.
  5. Then the code transfers that free 100 USDT from futures wallet to spot wallet. But here i am taking "Asset transfer failed: insufficient balance" error.
  6. I guess the reason of the error is, in that time i have 100 USDT but other half of my positions are still in short. So if the price goes up and i lose money in that miliseconds, free USDT amount in futures wallet will be less than 100 USDT.

My questions are:

  1. Is there any effective solution for this problem? What would you suggest?
  2. If there is an error in the code, it stops running. How can i update the code in money transfer part that if there is an error due to the insufficient balance to transfer, try again to transfer 99% of the balance of future wallet (account_balance_f * 99%) to spot wallet.

Thank you very much for your time in advance.


Solution

  • Is there any effective solution for this problem? What would you suggest?

    If you use isolated marginMode, your balance will not change when the value of your position goes up/down. In isolated mode, your collateral is put into a subaccount, but in cross mode, it's all taken from the same pool, which is why your balance will go up or down with the size of your positions

    You can set the margin mode with exchange.setMarginMode( symbol, 'isolated'); for each market.

    You can read more about isolated margin mode here

    If there is an error in the code, it stops running. How can i update the code in money transfer part that if there is an error due to the insufficient balance to transfer, try again to transfer 99% of the balance of future wallet (account_balance_f * 99%) to spot wallet.

    Do you know about error handling/exceptions in Python?


    I also suggest using the unified transfer method, instead of sapi_post_futures_transfer, here's an example of it

    # -*- coding: utf-8 -*-
    
    import os
    import sys
    from pprint import pprint
    
    root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
    sys.path.append(root + '/python')
    
    import ccxt  # noqa: E402
    
    
    def main():
    
        # apiKey must have universal transfer permissions
        binance = ccxt.binance({
            "apiKey": "...",
            "secret": "...",
        })
        binance.load_markets()
    
        pprint(binance.transfer('USDT', 0.1, 'spot', 'future'))
        transfers = binance.fetchTransfers()
        pprint('got ' + str(len(transfers)) + ' transfers')
        pprint(binance.transfer('USDT', 0.1, 'spot', 'margin'))
    
        # binance requires from and to in the params
        pprint(binance.fetchTransfers(None, None, None, {'from': 'spot', 'to': 'margin'}))
    
        # alternatively the same effect as above
        pprint(binance.fetchTransfers(None, None, None, {'type': 'MAIN_MARGIN'}))  # defaults to MAIN_UMFUTURE
    
    
    main()