How do you fix Binance API timestamp errors?

Your first API call will probably fail with:

Timestamp for this request was 1000ms ahead of the server's time

Binance requires your request timestamp to be within 1 second of their server time. Your computer’s clock drifts. Their server’s clock drifts.

Fix:

1
2
3
4
5
6
exchange = ccxt.binance({
    'options': {
        'adjustForTimeDifference': True
    }
})
exchange.load_time_difference()

And resync every hour. I learned this after random failures at 3 AM when nobody was around to restart the bot.

How do you set leverage on Binance Futures with ccxt in Python?

The official ccxt method set_leverage is what you want, but the parameters are not obvious from the docs:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
exchange = ccxt.binance({
    'apiKey': API_KEY,
    'secret': API_SECRET,
    'options': {
        'defaultType': 'future',
        'adjustForTimeDifference': True,
    }
})

# Set 3x leverage on BTC/USDT perpetual
exchange.set_leverage(3, 'BTC/USDT:USDT')

Three things that will trip you up:

  1. Symbol format matters. Use 'BTC/USDT:USDT' (with the settle currency suffix), not 'BTC/USDT'. The plain spot-style symbol may silently fail or set leverage on the wrong market.

  2. You must call set_leverage before the first order on each symbol. Binance does not auto-apply your account default leverage to new symbols you trade.

  3. Re-set after symbol rotation. If your bot drops a coin and picks up a new one, call set_leverage again on the new symbol before opening a position.

Also handy:

1
2
3
4
5
# Switch to isolated margin (per-position liquidation)
exchange.set_margin_mode('isolated', 'BTC/USDT:USDT')

# Or cross margin (shared collateral)
exchange.set_margin_mode('cross', 'BTC/USDT:USDT')

set_margin_mode will throw an error if the position is already open in the other mode. Catch that and continue — it just means you don’t need to change anything.

Why does fetch_balance return zero on Binance Futures?

On Binance Futures, the “correct” way to fetch your USDT balance:

1
2
3
4
5
# WRONG — returns empty or wrong data
balance = exchange.fetch_balance({'type': 'future'})

# RIGHT — just call it plain
balance = exchange.fetch_balance()

The type parameter behaves differently across exchange versions. Without parameters, ccxt handles the routing correctly for futures.

I spent half a day debugging “why is my balance always zero” because of this.

Why can’t I find my stop order with fetch_order on Binance?

This is the biggest gotcha. On Binance Futures, any order with a stopPrice is treated as a conditional/algorithmic order. This means:

  • exchange.fetch_order(id)Can’t find it
  • exchange.cancel_order(id)Fails silently

You need special API endpoints:

1
2
3
4
5
6
7
8
# Check status
exchange.fapiPrivateGetAlgoOrder({'algoId': order_id})

# Cancel
exchange.fapiPrivateDeleteAlgoOrder({'algoId': order_id})

# List open orders
exchange.fapiPrivateGetOpenAlgoOrders()

This is barely documented. I only found it by reading ccxt source code and Binance API changelogs.

What does “ReduceOnly order is getting rejected” mean on Binance?

Race condition: your trailing stop closes a position via market order, then your exchange-side SL triggers on the same position. The SL order gets rejected with:

-2022: ReduceOnly order is getting rejected

This is actually fine — it means the position is already closed. But if your bot doesn’t handle this error gracefully, it’ll spam retry loops for 30 seconds.

Fix: Catch -2022 errors and treat them as “position already closed, move on.”

How do you fix the TradFi-Perps agreement error on Binance?

If your bot tries to trade TSLA/USDT, NVDA/USDT, or other equity-backed tokens:

-4411: Please sign TradFi-Perps agreement contract fapi

You need to sign a legal agreement on the Binance website first. But better yet, just auto-exclude them:

1
2
3
for symbol, market in exchange.markets.items():
    if market.get('info', {}).get('underlyingType') != 'COIN':
        exclude_list.append(symbol)

This catches equities, commodities, indices, and pre-market tokens — about 24 pairs that will cause problems.

Why does fetch_ohlcv return stale candle data on Binance?

When you call fetch_ohlcv() right after a 5-minute candle closes, the API might return stale data. The new candle takes 1-3 seconds to appear.

Wrong approach:

1
2
time.sleep(2)  # Hope for the best
data = exchange.fetch_ohlcv(symbol, '5m', limit=1)

Right approach:

1
2
3
4
5
6
7
for attempt in range(5):
    data = exchange.fetch_ohlcv(symbol, '5m', limit=2)
    latest_ts = data[-1][0]
    expected_ts = current_5m_boundary()
    if latest_ts >= expected_ts:
        break
    time.sleep(1)

Verify the timestamp. Don’t trust sleep timers.

How do you handle order dust on Binance Futures?

After closing a position, you sometimes have tiny leftover amounts (0.001 of a coin) that are too small to trade. These show up as phantom positions in your balance.

The API says you have a position. You can’t close it because it’s below minimum order size. Your bot thinks it’s still in a trade.

Fix: Check position size against the market’s minimum order quantity before treating it as an active position.

Are Binance API rate limits per API key or per IP address?

If you’re running multiple bots from the same server, they share rate limits. I found this out when my trend-following bot and FVG bot started getting 429 Too Many Requests errors simultaneously.

Fix: Stagger your API calls. Use enableRateLimit: True in ccxt, and add small delays between bot instances.

Why is resampled RSI different from native candle RSI on Binance?

This is subtle. If you build 1-hour candles by combining 5-minute candles:

1
2
3
4
5
# Resampled — NOT the same as exchange native
df_1h = df_5m.resample('1h').agg({
    'open': 'first', 'high': 'max', 
    'low': 'min', 'close': 'last'
})

The RSI calculated from these resampled candles will be slightly different from RSI calculated on native 1-hour candles from the exchange.

The difference is tiny — maybe 0.5 RSI points. But when your entry condition is “RSI > 50,” that 0.5 can flip the signal.

Fix: Always fetch native candles for the timeframe you need. Don’t resample.

The Meta-Lesson

Binance’s API is powerful but full of edge cases. The documentation covers the happy path. The unhappy paths — the ones that hit at 3 AM on a Sunday — aren’t documented anywhere.

Build defensively. Log everything. Handle every error code. And test with real (small) money before scaling up.


The API documentation tells you how it should work. Production tells you how it actually works.