├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── .travis.yml ├── Endpoints.md ├── LICENSE ├── PYPIREADME.rst ├── README.rst ├── binance ├── __init__.py ├── client.py ├── depthcache.py ├── enums.py ├── exceptions.py ├── helpers.py ├── streams.py └── threaded_stream.py ├── docs ├── Makefile ├── account.rst ├── binance.rst ├── changelog.rst ├── conf.py ├── constants.rst ├── depth_cache.rst ├── exceptions.rst ├── faqs.rst ├── general.rst ├── helpers.rst ├── index.rst ├── margin.rst ├── market_data.rst ├── overview.rst ├── sub_accounts.rst ├── websockets.rst └── withdraw.rst ├── examples └── save_historical_data.py ├── pytest.ini ├── requirements.txt ├── setup.cfg ├── setup.py ├── test-requirements.txt ├── tests ├── __init__.py ├── test_api_request.py ├── test_depth_cache.py └── test_historical_klines.py └── tox.ini /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Code snippet to reproduce the behavior: 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Environment (please complete the following information):** 20 | - Python version: [e.g. 3.5] 21 | - Virtual Env: [e.g. virtualenv, conda] 22 | - OS: [e.g. Mac, Ubuntu] 23 | - python-binance version 24 | 25 | **Logs or Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .tox 2 | .cache/v/cache 3 | docs/_build 4 | binance/__pycache__/ 5 | build/ 6 | dist/ 7 | python_binance.egg-info/ 8 | *__pycache__ 9 | *.egg-info/ 10 | .idea/ 11 | venv*/ 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | 3 | language: python 4 | 5 | python: 6 | - "3.6" 7 | - "3.7" 8 | - "3.8" 9 | - "3.9" 10 | 11 | install: 12 | - pip install -r test-requirements.txt 13 | - pip install -r requirements.txt 14 | - pip install tox-travis 15 | 16 | script: 17 | - tox 18 | 19 | after_success: 20 | - coveralls 21 | -------------------------------------------------------------------------------- /Endpoints.md: -------------------------------------------------------------------------------- 1 | > :warning: **Disclaimer**: 2 | 3 | > * Before using the endpoints, please check the [API documentation](https://binance-docs.github.io/apidocs/#change-log) to be informed about the latest changes or possible bugs/problems. 4 | 5 | > * Not all parameters are mandatory. Some parameters are only mandatory in specific conditions/types. Check the official documentation the type of each parameter and to know if a parameter is mandatory or optional. 6 | 7 | > * This documentation only includes methods in client.py file. Websocket methods haven't (yet) been covered. 8 | 9 | ### [Spot/Margin/Saving/Mining Endpoints](https://binance-docs.github.io/apidocs/spot/en/) 10 | - *Wallet Endpoints* 11 | - **GET /sapi/v1/system/status** (Fetch system status.) 12 | ```python 13 | client.get_system_status() 14 | ``` 15 | - **GET /sapi/v1/capital/config/getall (HMAC SHA256)** (Get information of coins (available for deposit and withdraw) for user.) 16 | ```python 17 | client.get_all_coins_info() 18 | ``` 19 | - **GET /sapi/v1/accountSnapshot (HMAC SHA256)** (Daily Account Snapshot (USER_DATA).) 20 | ```python 21 | client.get_account_snapshot(type='SPOT') 22 | ``` 23 | - **POST /sapi/v1/account/disableFastWithdrawSwitch (HMAC SHA256)** (Disable Fast Withdraw Switch (USER_DATA).) 24 | ```python 25 | client.disable_fast_withdraw_switch(type='SPOT') 26 | ``` 27 | - **POST /sapi/v1/account/enableFastWithdrawSwitch (HMAC SHA256)** (Enable Fast Withdraw Switch (USER_DATA).) 28 | ```python 29 | client.enable_fast_withdraw_switch(type='SPOT') 30 | ``` 31 | - **POST /sapi/v1/capital/withdraw/apply (HMAC SHA256)** (Withdraw: Submit a withdraw request.) 32 | ```python 33 | client.withdraw(coin, 34 | withdrawOrderId, 35 | network, 36 | address, 37 | addressTag, 38 | amount, 39 | transactionFeeFlag, 40 | name, 41 | recvWindow) 42 | ``` 43 | - **GET /sapi/v1/capital/deposit/hisrec (HMAC SHA256)** (Fetch Deposit History(supporting network) (USER_DATA).) 44 | ```python 45 | client.get_deposit_history(coin, status, startTime, endTime, recvWindow) 46 | ``` 47 | - **GET /sapi/v1/capital/withdraw/history (HMAC SHA256)** (Fetch Withdraw History (supporting network) (USER_DATA).) 48 | ```python 49 | client.get_withdraw_history(coin, status, startTime, endTime, recvWindow) 50 | ``` 51 | - **GET /sapi/v1/capital/deposit/address (HMAC SHA256)** (Fetch deposit address with network.) 52 | ```python 53 | client.get_deposit_address(coin, status, recvWindow) 54 | ``` 55 | - **GET /sapi/v1/account/status** (Fetch account status detail.) 56 | ```python 57 | client.get_account_status(recvWindow) 58 | ``` 59 | - **GET /sapi/account/apiTradingStatus** (Fetch account api trading status detail.) 60 | ```python 61 | client.get_account_api_trading_status(recvWindow) 62 | ``` 63 | - **GET /sapi/v1/asset/dribblet (HMAC SHA256)** (DustLog: Fetch small amounts of assets exchanged BNB records.) 64 | ```python 65 | client.get_dust_log(recvWindow) 66 | ``` 67 | - **Post /sapi/v1/asset/dust (HMAC SHA256)** (Dust Transfer: Convert dust assets to BNB.) 68 | ```python 69 | client.transfer_dust(asset, recvWindow) 70 | ``` 71 | - **Get /sapi/v1/asset/assetDividend (HMAC SHA256)** (Query asset dividend record.) 72 | ```python 73 | client.get_asset_dividend_history(asset, startTime, endTime, limit, recvWindow) 74 | ``` 75 | - **GET /sapi/v1/asset/assetDetail (HMAC SHA256)** (Fetch details of assets supported on Binance.) 76 | ```python 77 | client.get_asset_details(recvWindow) 78 | ``` 79 | - **GET /sapi/v1/asset/tradeFee (HMAC SHA256)** (Fetch trade fee, values in percentage.) 80 | ```python 81 | client.get_trade_fee(symbol, recvWindow) 82 | ``` 83 | - *Market Data Endpoints* 84 | - **GET /api/v3/ping** (Test connectivity to the Rest API.) 85 | ```python 86 | client.ping() 87 | ``` 88 | - **GET /api/v3/time** (Test connectivity to the Rest API and get the current server time.) 89 | ```python 90 | client.get_server_time() 91 | ``` 92 | - **GET /api/v3/exchangeInfo** (Current exchange trading rules and symbol information.) 93 | ```python 94 | client.get_exchange_info() 95 | ``` 96 | - **GET /api/v3/depth** (Get the Order Book for the market.) 97 | ```python 98 | client.get_order_book(symbol, limit) 99 | ``` 100 | - **GET /api/v3/trades** (Get recent trades (up to last 500)) 101 | ```python 102 | client.get_recent_trades(symbol, limit) 103 | ``` 104 | - **GET /api/v3/historicalTrades** (Get older market trades.) 105 | ```python 106 | client.get_historical_trades(symbol, limit, fromId) 107 | ``` 108 | - **GET /api/v3/aggTrades** (Get compressed, aggregate trades. Trades that fill at the time, from the same order, with the same price will have the quantity aggregated.) 109 | ```python 110 | client.get_aggregate_trades(symbol, fromId, startTime, endTime, limit) 111 | 112 | # Wrapper function: Iterate over aggregate trade data from (start_time or last_id) the end of the history so far: 113 | client.aggregate_trade_iter(symbol, start_str, last_id) 114 | ``` 115 | - **GET /api/v3/klines** (Kline/candlestick bars for a symbol. Klines are uniquely identified by their open time.) 116 | ```python 117 | client.get_klines(symbol, interval, startTime, endTime, limit) 118 | 119 | # Wrapper function: Iterate over klines data from client.get_klines() 120 | client.get_historical_klines(symbol, interval, start_str, end_str, limit) 121 | ``` 122 | - **GET /api/v3/avgPrice** (Current average price for a symbol.) 123 | ```python 124 | client.get_avg_price(symbol) 125 | ``` 126 | - **GET /api/v3/ticker/24hr** (24 hour rolling window price change statistics. **Careful** when accessing this with no symbol.) 127 | ```python 128 | client.get_ticker(symbol) 129 | ``` 130 | - **GET /api/v3/ticker/price** (Latest price for a symbol or symbols.) 131 | ```python 132 | client.get_symbol_ticker(symbol) 133 | ``` 134 | - **GET /api/v3/ticker/bookTicker** (Best price/qty on the order book for a symbol or symbols.) 135 | ```python 136 | client.get_orderbook_ticker(symbol) 137 | ``` 138 | - *Spot Account/Trade Endpoints* 139 | - **POST /api/v3/order/test (HMAC SHA256)** (Test new order creation and signature/recvWindow long. Creates and validates a new order but does not send it into the matching engine.) 140 | ```python 141 | client.create_test_order(symbol, 142 | side, 143 | type, 144 | timeInForce, 145 | quantity, 146 | quoteOrderQty, 147 | price, 148 | newClientOrderId, 149 | stopPrice, 150 | icebergQty, 151 | newOrderRespType, 152 | recvWindow) 153 | ``` 154 | - **POST /api/v3/order (HMAC SHA256)** (Send in a new order.) 155 | ```python 156 | client.create_order(symbol, 157 | side, 158 | type, 159 | timeInForce, 160 | quantity, 161 | quoteOrderQty, 162 | price, 163 | newClientOrderId, 164 | stopPrice, 165 | icebergQty, 166 | newOrderRespType, 167 | recvWindow) 168 | 169 | ## Wrapper functions: 170 | # Send in a new limit order. 171 | # Default parameters: timeInForce=Client.TIME_IN_FORCE_GTC, type=Client.ORDER_TYPE_LIMIT 172 | client.order_limit(symbol, 173 | side, 174 | quantity, 175 | price, 176 | newClientOrderId, 177 | stopPrice, 178 | icebergQty, 179 | newOrderRespType, 180 | recvWindow) 181 | 182 | # Send in a new limit buy order. 183 | # Default parameters: timeInForce=Client.TIME_IN_FORCE_GTC, type=Client.ORDER_TYPE_LIMIT, side=Client.SIDE_BUY 184 | client.order_limit_buy(symbol, 185 | quantity, 186 | price, 187 | newClientOrderId, 188 | stopPrice, 189 | icebergQty, 190 | newOrderRespType, 191 | recvWindow) 192 | 193 | # Send in a new limit sell order. 194 | # Default parameters: timeInForce=Client.TIME_IN_FORCE_GTC, type=Client.ORDER_TYPE_LIMIT, side= Client.SIDE_SELL 195 | client.order_limit_sell(symbol, 196 | quantity, 197 | price, 198 | newClientOrderId, 199 | stopPrice, 200 | icebergQty, 201 | newOrderRespType, 202 | recvWindow) 203 | 204 | # Send in a new market order. 205 | # Default parameters: type=Client.ORDER_TYPE_MARKET 206 | client.order_market(symbol, 207 | side, 208 | quantity, 209 | quoteOrderQty, 210 | newClientOrderId, 211 | newOrderRespType, 212 | recvWindow) 213 | 214 | # Send in a new market buy order. 215 | # Default parameters: type=Client.ORDER_TYPE_MARKET, side=Client.SIDE_BUY 216 | client.order_market_buy(symbol, 217 | quantity, 218 | quoteOrderQty, 219 | newClientOrderId, 220 | newOrderRespType, 221 | recvWindow) 222 | 223 | # Send in a new market sell order. 224 | # Default parameters: type=Client.ORDER_TYPE_MARKET, side=Client.SIDE_SELL 225 | client.order_market_sell(symbol, 226 | quantity, 227 | quoteOrderQty, 228 | newClientOrderId, 229 | newOrderRespType, 230 | recvWindow) 231 | ``` 232 | - **DELETE /api/v3/order (HMAC SHA256)** (Cancel an active order.) 233 | ```python 234 | client.cancel_order(symbol, orderId, origClientOrderId, newClientOrderId, recvWindow) 235 | ``` 236 | - **DELETE api/v3/openOrders** (Cancels all active orders on a symbol. This includes OCO orders.) 237 | 238 | > :warning: Not yet implemented 239 | - **GET /api/v3/order (HMAC SHA256)** (Check an order's status.) 240 | ```python 241 | client.get_order(symbol, orderId, origClientOrderId, recvWindow) 242 | ``` 243 | - **GET /api/v3/openOrders (HMAC SHA256)** (Get all open orders on a symbol. **Careful** when accessing this with no symbol.) 244 | ```python 245 | client.get_open_orders(symbol, recvWindow) 246 | ``` 247 | - **GET /api/v3/allOrders (HMAC SHA256)** (Get all account orders; active, canceled, or filled.) 248 | ```python 249 | client.get_all_orders(symbol, orderId, startTime, endTime, limit, recvWindow) 250 | ``` 251 | - **POST /api/v3/order/oco (HMAC SHA256)** (Send in a new OCO order) 252 | ```python 253 | client.create_oco_order(symbol, 254 | listClientOrderId, 255 | side, 256 | quantity, 257 | limitClientOrderId, 258 | price, 259 | limitIcebergQty, 260 | stopClientOrderId, 261 | stopPrice, 262 | stopLimitPrice, 263 | stopIcebergQty, 264 | stopLimitTimeInForce, 265 | newOrderRespType, 266 | recvWindow) 267 | 268 | ## Wrapper Functions: 269 | 270 | # Send in a new OCO buy order. Default parameter: type=Client.SIDE_BUY 271 | client.order_oco_buy(symbol, 272 | listClientOrderId, 273 | quantity, 274 | limitClientOrderId, 275 | price, 276 | limitIcebergQty, 277 | stopClientOrderId, 278 | stopPrice, 279 | stopLimitPrice, 280 | stopIcebergQty, 281 | stopLimitTimeInForce, 282 | newOrderRespType, 283 | recvWindow) 284 | 285 | # Send in a new OCO sell order. Default parameter: type=Client.SIDE_SELL 286 | client.order_oco_sell(symbol, 287 | listClientOrderId, 288 | quantity, 289 | limitClientOrderId, 290 | price, 291 | limitIcebergQty, 292 | stopClientOrderId, 293 | stopPrice, 294 | stopLimitPrice, 295 | stopIcebergQty, 296 | stopLimitTimeInForce, 297 | newOrderRespType, 298 | recvWindow) 299 | ``` 300 | - **DELETE /api/v3/orderList (HMAC SHA256)** (Cancel OCO: Cancel an entire Order List) 301 | 302 | > :warning: Not yet implemented 303 | - **GET /api/v3/orderList (HMAC SHA256)** (Query OCO: Retrieves a specific OCO based on provided optional parameters) 304 | 305 | > :warning: Not yet implemented 306 | - **GET /api/v3/allOrderList (HMAC SHA256)** (Retrieves all OCO based on provided optional parameters) 307 | 308 | > :warning: Not yet implemented 309 | - **GET /api/v3/openOrderList (HMAC SHA256)** (Query Open OCO (USER_DATA)) 310 | 311 | > :warning: Not yet implemented 312 | - **GET /api/v3/account (HMAC SHA256)** (Get current account information.) 313 | ```python 314 | client.get_account(recvWindow) 315 | ``` 316 | - **GET /api/v3/myTrades (HMAC SHA256)** (Get trades for a specific account and symbol.) 317 | ```python 318 | client.get_my_trades(symbol, startTime, endTime, fromId, limit, recvWindow) 319 | ``` 320 | - *Margin Account/Trade* 321 | - **POST /sapi/v1/margin/transfer (HMAC SHA256)** (Execute transfer between margin account and spot account(MARGIN).) 322 | ```python 323 | client.transfer_margin_to_spot(asset, amount, recvWindow) 324 | client.transfer_spot_to_margin(asset, amount, recvWindow) 325 | ``` 326 | - **POST /sapi/v1/margin/loan (HMAC SHA256)** (Apply for a loan(MARGIN).) 327 | ```python 328 | client.create_margin_loan(asset, isIsolated, symbol, amount, recvWindow) 329 | ``` 330 | - **POST /sapi/v1/margin/repay (HMAC SHA256)** (Repay loan for margin account (MARGIN).) 331 | ```python 332 | client.repay_margin_loan(asset, isIsolated, symbol, amount, recvWindow) 333 | ``` 334 | - **GET /sapi/v1/margin/asset** (Query Margin Asset (MARKET_DATA).) 335 | ```python 336 | client.get_margin_asset(asset) 337 | ``` 338 | - **GET /sapi/v1/margin/pair** (Query Cross Margin Pair (MARKET_DATA).) 339 | ```python 340 | client.get_margin_symbol(symbol) 341 | ``` 342 | - **GET /sapi/v1/margin/allAssets** (Get All Cross Margin Assets (MARKET_DATA).) 343 | ```python 344 | client.get_margin_all_assets() 345 | ``` 346 | - **GET /sapi/v1/margin/allPairs** (Get All Cross Margin Pairs (MARKET_DATA).) 347 | ```python 348 | client.get_margin_all_pairs() 349 | ``` 350 | - **GET /sapi/v1/margin/priceIndex** (Query Margin PriceIndex (MARKET_DATA).) 351 | ```python 352 | client.get_margin_price_index(symbol) 353 | ``` 354 | - **POST /sapi/v1/margin/order (HMAC SHA256)** (Post a new order for margin account.) 355 | ```python 356 | client.create_margin_order(symbol, 357 | isIsolated, 358 | side, 359 | type, 360 | quantity, 361 | price, 362 | stopPrice, 363 | newClientOrderId, 364 | icebergQty, 365 | newOrderRespType, 366 | sideEffectType, 367 | timeInForce, 368 | recvWindow) 369 | ``` 370 | - **DELETE /sapi/v1/margin/order (HMAC SHA256)** (Cancel an active order for margin account.) 371 | ```python 372 | client.cancel_margin_order(symbol, 373 | isIsolated, 374 | orderId, 375 | origClientOrderId, 376 | newClientOrderId, 377 | recvWindow) 378 | ``` 379 | - **GET /sapi/v1/margin/transfer (HMAC SHA256)** (Get Cross Margin Transfer History (USER_DATA).) 380 | ```python 381 | client.transfer_margin_to_spot(asset, amount, recvWindow) 382 | client.transfer_spot_to_margin(asset, amount, recvWindow) 383 | ``` 384 | - **GET /sapi/v1/margin/loan (HMAC SHA256)** (Query Loan Record (USER_DATA).) 385 | ```python 386 | client.get_margin_loan_details(asset, isolatedSymbol, txId, startTime, endTime, current, size, recvWindow) 387 | ``` 388 | - **GET /sapi/v1/margin/repay (HMAC SHA256)** (Query repay record (USER_DATA).) 389 | ```python 390 | client.get_margin_repay_details(asset, isolatedSymbol, txId, startTime, endTime, current, size, recvWindow) 391 | ``` 392 | - **GET /sapi/v1/margin/interestHistory (HMAC SHA256)** (Get Interest History (USER_DATA).) 393 | ```python 394 | client.get_margin_interest_history(asset, isolatedSymbol, startTime, endTime, current, size, archived, recvWindow) 395 | ``` 396 | - **GET /sapi/v1/margin/forceLiquidationRec (HMAC SHA256)** (Get Force Liquidation Record (USER_DATA).) 397 | ```python 398 | client.get_margin_force_liquidation_rec(isolatedSymbol, startTime, endTime, current, size, recvWindow) 399 | ``` 400 | - **GET /sapi/v1/margin/account (HMAC SHA256)** (Query Cross Margin Account Details (USER_DATA).) 401 | ```python 402 | client.get_margin_account(recvWindow) 403 | ``` 404 | - **GET /sapi/v1/margin/order (HMAC SHA256)** (Query Margin Account's Order (USER_DATA).) 405 | ```python 406 | client.get_margin_order(symbol, isIsolated, orderId, origClientOrderId, recvWindow) 407 | ``` 408 | - **GET /sapi/v1/margin/openOrders (HMAC SHA256)** (Query Margin Account's Open Order (USER_DATA).) 409 | ```python 410 | client.get_open_margin_orders(symbol, isIsolated, recvWindow) 411 | ``` 412 | - **GET /sapi/v1/margin/allOrders (HMAC SHA256)** (Query Margin Account's All Order (USER_DATA).) 413 | ```python 414 | client.get_all_margin_orders(symbol, isIsolated, orderId, startTime, endTime, limit, recvWindow) 415 | ``` 416 | - **GET /sapi/v1/margin/myTrades (HMAC SHA256)** (Query Margin Account's Trade List (USER_DATA).) 417 | ```python 418 | client.get_margin_trades(symbol, isIsolated, startTime, endTime, fromId, limit, recvWindow) 419 | ``` 420 | - **GET /sapi/v1/margin/maxBorrowable (HMAC SHA256)** (Query Max Borrow amount for an asset (USER_DATA).) 421 | ```python 422 | client.get_max_margin_loan(asset, isolatedSymbol, recvWindow) 423 | ``` 424 | - **GET /sapi/v1/margin/maxTransferable (HMAC SHA256)** (Query Max Transfer-Out Amount (USER_DATA).) 425 | ```python 426 | client.get_max_margin_transfer(asset, isolatedSymbol, recvWindow) 427 | ``` 428 | - **POST /sapi/v1/margin/isolated/create (HMAC SHA256)** (Create Isolated Margin Account (MARGIN).) 429 | ```python 430 | client.create_isolated_margin_account(base, quote, recvWindow) 431 | ``` 432 | - **POST /sapi/v1/margin/isolated/transfer (HMAC SHA256)** (Isolated Margin Account Transfer (MARGIN).) 433 | ```python 434 | client.transfer_spot_to_isolated_margin(asset, symbol, amount, recvWindow) 435 | client.transfer_isolated_margin_to_spot(asset, symbol, amount, recvWindow) 436 | ``` 437 | - **GET /sapi/v1/margin/isolated/transfer (HMAC SHA256)** (Get Isolated Margin Transfer History (USER_DATA).) 438 | 439 | > :warning: Not yet implemented 440 | - **GET /sapi/v1/margin/isolated/account (HMAC SHA256)** (Query Isolated Margin Account Info (USER_DATA).) 441 | ```python 442 | client.get_isolated_margin_account(symbols, recvWindow) 443 | ``` 444 | - **GET /sapi/v1/margin/isolated/pair (HMAC SHA256)** (Query Isolated Margin Symbol (USER_DATA).) 445 | ```python 446 | client.get_isolated_margin_symbol(symbol, recvWindow) 447 | ``` 448 | - **GET /sapi/v1/margin/isolated/allPairs (HMAC SHA256)** (Get All Isolated Margin Symbol (USER_DATA).) 449 | ```python 450 | client.get_all_isolated_margin_symbols(recvWindow) 451 | ``` 452 | - *User Data Streams* 453 | - **POST /api/v3/userDataStream** (Create a ListenKey (Spot) (USER_STREAM): Start a new user data stream.) 454 | ```python 455 | client.stream_get_listen_key() 456 | ``` 457 | - **PUT /api/v3/userDataStream** (Ping/Keep-alive a ListenKey (Spot) (USER_STREAM).) 458 | ```python 459 | client.stream_keepalive(listenKey) 460 | ``` 461 | - **DELETE /api/v3/userDataStream** (Close a ListenKey (Spot) (USER_STREAM).) 462 | ```python 463 | client.stream_close(listenKey) 464 | ``` 465 | - **POST /sapi/v1/userDataStream** (Create a ListenKey (Margin).) 466 | ```python 467 | client.margin_stream_get_listen_key() 468 | ``` 469 | - **PUT /sapi/v1/userDataStream** (Ping/Keep-alive a ListenKey (Margin).) 470 | ```python 471 | client.margin_stream_keepalive(listenKey) 472 | ``` 473 | - **DELETE /sapi/v1/userDataStream** (Close a ListenKey (Margin).) 474 | ```python 475 | client.margin_stream_close(listenKey) 476 | ``` 477 | - **POST /sapi/v1/userDataStream/isolated** (Create a ListenKey (Isolated).) 478 | ```python 479 | client.isolated_margin_stream_get_listen_key(symbol) 480 | ``` 481 | - **PUT /sapi/v1/userDataStream/isolated** (Ping/Keep-alive a ListenKey (Isolated).) 482 | ```python 483 | client.isolated_margin_stream_keepalive(symbol, listenKey) 484 | ``` 485 | - **DELETE /sapi/v1/userDataStream/isolated** (Close a ListenKey (Isolated).) 486 | ```python 487 | client.isolated_margin_stream_close(symbol, listenKey) 488 | ``` 489 | - *Savings Endpoints* 490 | - **GET /sapi/v1/lending/daily/product/list (HMAC SHA256)** (Get Flexible Product List (USER_DATA).) 491 | ```python 492 | client.get_lending_product_list(status, featured, recvWindow) 493 | ``` 494 | - **GET /sapi/v1/lending/daily/userLeftQuota (HMAC SHA256)** (Get Left Daily Purchase Quota of Flexible Product (USER_DATA).) 495 | ```python 496 | client.get_lending_daily_quota_left(productId, recvWindow) 497 | ``` 498 | - **POST /sapi/v1/lending/daily/purchase (HMAC SHA256)** (Purchase Flexible Product (USER_DATA).) 499 | ```python 500 | client.purchase_lending_product(productId, amount, recvWindow) 501 | ``` 502 | - **GET /sapi/v1/lending/daily/userRedemptionQuota (HMAC SHA256)** (Get Left Daily Redemption Quota of Flexible Product (USER_DATA).) 503 | ```python 504 | client.get_lending_daily_redemption_quota(productId, type, recvWindow) 505 | ``` 506 | - **POST /sapi/v1/lending/daily/redeem (HMAC SHA256)** (Redeem Flexible Product (USER_DATA).) 507 | ```python 508 | client.redeem_lending_product(productId, amount, type, recvWindow) 509 | ``` 510 | - **GET /sapi/v1/lending/daily/token/position (HMAC SHA256)** (Get Flexible Product Position (USER_DATA).) 511 | ```python 512 | client.get_lending_position(asset, recvWindow) 513 | ``` 514 | - **GET /sapi/v1/lending/project/list (HMAC SHA256)** (Get Fixed and Activity Project List (USER_DATA).) 515 | ```python 516 | client.get_fixed_activity_project_list(asset, type, status, isSortAsc, sortBy, current, size, recvWindow) 517 | ``` 518 | - **POST /sapi/v1/lending/customizedFixed/purchase (HMAC SHA256)** (Purchase Fixed/Activity Project (USER_DATA).) 519 | 520 | > :warning: Not yet implemented 521 | - **GET /sapi/v1/lending/project/position/list (HMAC SHA256)** (Get Fixed/Activity Project Position (USER_DATA).) 522 | 523 | > :warning: Not yet implemented 524 | - **GET /sapi/v1/lending/union/account (HMAC SHA256)** (Lending Account (USER_DATA).) 525 | ```python 526 | client.get_lending_account(recvWindow) 527 | ``` 528 | - **GET /sapi/v1/lending/union/purchaseRecord (HMAC SHA256)** (Get Purchase Record (USER_DATA).) 529 | ```python 530 | client.get_lending_purchase_history(lendingType, asset, startTime, endTime, current, size, recvWindow) 531 | ``` 532 | - **GET /sapi/v1/lending/union/redemptionRecord (HMAC SHA256)** (Get Redemption Record (USER_DATA).) 533 | ```python 534 | client.get_lending_redemption_history(lendingType, asset, startTime, endTime, current, size, recvWindow) 535 | ``` 536 | - **GET /sapi/v1/lending/union/interestHistory (HMAC SHA256)** (Get Interest History (USER_DATA).) 537 | ```python 538 | client.get_lending_interest_history(lendingType, asset, startTime, endTime, current, size, recvWindow) 539 | ``` 540 | - **POST /sapi/v1/lending/positionChanged (HMAC SHA256)** (Change Fixed/Activity Position to Daily Position (USER_DATA).) 541 | ```python 542 | client.change_fixed_activity_to_daily_position(projectId, lot, positionId, recvWindow) 543 | ``` 544 | - *Mining Endpoints* 545 | > :warning: Not yet implemented 546 | - *Sub-Account Endpoints* 547 | - **GET /sapi/v1/sub-account/list (HMAC SHA256)** (Query Sub-account List (For Master Account).) 548 | ```python 549 | client.get_sub_account_list(email, isFreeze, page, limit, recvWindow) 550 | ``` 551 | - **GET /sapi/v1/sub-account/sub/transfer/history (HMAC SHA256)** (Query Sub-account Spot Asset Transfer History (For Master Account).) 552 | ```python 553 | client.get_sub_account_transfer_history(fromEmail, toEmail, startTime, endTime, page, limit, recvWindow) 554 | ``` 555 | - **GET /sapi/v1/sub-account/assets (HMAC SHA256)** (Query Sub-account Assets (For Master Account).) 556 | ```python 557 | client.get_sub_account_assets(email, recvWindow) 558 | ``` 559 | > :warning: The rest of methods for Sub-Account Endpoints are not yet implemented 560 | - *BLVT Endpoints* 561 | > :warning: Not yet implemented 562 | - *BSwap Endpoints* 563 | > :warning: Not yet implemented 564 | ### [USDT-M Futures](https://binance-docs.github.io/apidocs/futures/en/) 565 | - *Market Data Endpoints* 566 | - **GET /fapi/v1/ping** (Test connectivity to the Rest API.) 567 | ```python 568 | client.futures_ping() 569 | ``` 570 | - **GET /fapi/v1/time** (Test connectivity to the Rest API and get the current server time.) 571 | ```python 572 | client.futures_time() 573 | ``` 574 | - **GET /fapi/v1/exchangeInfo** (Current exchange trading rules and symbol information.) 575 | ```python 576 | client.futures_exchange_info() 577 | ``` 578 | - **GET /fapi/v1/depth** (Get the Order Book for the market.) 579 | ```python 580 | client.futures_order_book(symbol, limit) 581 | ``` 582 | - **GET /fapi/v1/trades** (Get recent trades.) 583 | ```python 584 | client.futures_recent_trades(symbol, limit) 585 | ``` 586 | - **GET /fapi/v1/historicalTrades** (Get older market historical trades (MARKET_DATA).) 587 | ```python 588 | client.futures_historical_trades(symbol, limit, fromId) 589 | ``` 590 | - **GET /fapi/v1/aggTrades** (Get compressed, aggregate trades. Trades that fill at the time, from the same order, with the same price will have the quantity aggregated.) 591 | ```python 592 | client.futures_aggregate_trades(symbol, fromId, startTime, endTime, limit) 593 | ``` 594 | - **GET /fapi/v1/klines** (Kline/candlestick bars for a symbol. Klines are uniquely identified by their open time.) 595 | ```python 596 | client.futures_klines(symbol, interval, startTime, endTime, limit) 597 | ``` 598 | - **GET /fapi/v1/premiumIndex** (Get Mark Price and Funding Rate.) 599 | ```python 600 | client.futures_mark_price(symbol) 601 | ``` 602 | - **GET /fapi/v1/fundingRate** (Get Funding Rate History.) 603 | ```python 604 | client.futures_funding_rate(symbol, startTime, endTime, limit) 605 | ``` 606 | - **GET /fapi/v1/ticker/24hr** (24 hour rolling window price change statistics. **Careful** when accessing this with no symbol.) 607 | ```python 608 | client.futures_ticker(symbol) 609 | ``` 610 | - **GET /fapi/v1/ticker/price** (Latest price for a symbol or symbols.) 611 | ```python 612 | client.futures_symbol_ticker(symbol) 613 | ``` 614 | - **GET /fapi/v1/ticker/bookTicker** (Best price/qty on the order book for a symbol or symbols.) 615 | ```python 616 | client.futures_orderbook_ticker(symbol) 617 | ``` 618 | - **GET /fapi/v1/allForceOrders** (Get all Liquidation Orders.) 619 | > :warning: Probably broken, python code below is implemented on v1/ticker/allForceOrders endpoint. 620 | ```python 621 | client.futures_liquidation_orders(symbol, startTime, endTime, limit) 622 | ``` 623 | - **GET /fapi/v1/openInterest** (Get present open interest of a specific symbol.) 624 | ```python 625 | client.futures_open_interest(symbol) 626 | ``` 627 | - **GET /futures/data/openInterestHist** (Open Interest Statistics.) 628 | 629 | > :warning: Not yet implemented 630 | - **GET /futures/data/topLongShortAccountRatio** (Top Trader Long/Short Ratio (Accounts) (MARKET_DATA).) 631 | 632 | > :warning: Not yet implemented 633 | - **GET /futures/data/topLongShortPositionRatio** (Top Trader Long/Short Ratio (Positions).) 634 | 635 | > :warning: Not yet implemented 636 | - **GET /futures/data/globalLongShortAccountRatio** (Long/Short Ratio.) 637 | 638 | > :warning: Not yet implemented 639 | - **GET /futures/data/takerlongshortRatio** (Taker Buy/Sell Volume.) 640 | 641 | > :warning: Not yet implemented 642 | - **GET /fapi/v1/lvtKlines** (Historical BLVT NAV Kline/Candlestick.) 643 | 644 | > :warning: Not yet implemented 645 | - **GET /fapi/v1/indexInfo** (Composite Index Symbol Information.) 646 | 647 | > :warning: Not yet implemented 648 | - *Account/trades Endpoints* 649 | - **POST /sapi/v1/futures/transfer (HMAC SHA256)** (New Future Account Transfer (FUTURES): Execute transfer between spot account and futures account.) 650 | ```python 651 | client.futures_account_transfer(asset, amount, type, recvWindow) 652 | ``` 653 | - **GET /sapi/v1/futures/transfer (HMAC SHA256)** (Get Future Account Transaction History List (USER_DATA).) 654 | ```python 655 | client.transfer_history(asset, startTime, endTime, current, size, recvWindow) 656 | ``` 657 | - **POST /fapi/v1/positionSide/dual (HMAC SHA256)** (Change user's position mode (Hedge Mode or One-way Mode ) on _**EVERY symbol**_.) 658 | ```python 659 | client.futures_change_position_mode(dualSidePosition, recvWindow) 660 | ``` 661 | - **GET /fapi/v1/positionSide/dual (HMAC SHA256)** (Get user's position mode (Hedge Mode or One-way Mode ) on _**EVERY symbol**_.) 662 | ```python 663 | client.futures_get_position_mode(recvWindow) 664 | ``` 665 | - **POST /fapi/v1/order (HMAC SHA256)** (Send in a new order (TRADE).) 666 | ```python 667 | client.futures_create_order(symbol, 668 | side, 669 | positionSide, 670 | type, 671 | timeInForce, 672 | quantity, 673 | reduceOnly, 674 | price, 675 | newClientOrderId, 676 | stopPrice, 677 | closePosition, 678 | activationPrice, 679 | callbackRate, 680 | workingType, 681 | priceProtect, 682 | newOrderRespType, 683 | recvWindow) 684 | ``` 685 | - **POST /fapi/v1/batchOrders (HMAC SHA256)** (Place Multiple Orders (TRADE).) 686 | 687 | > :warning: Not yet implemented 688 | - **GET /fapi/v1/order (HMAC SHA256)** (Query Order (USER_DATA): Check an order's status.) 689 | ```python 690 | client.futures_get_order(symbol, orderId, origClientOrderId, recvWindow) 691 | ``` 692 | - **DELETE /fapi/v1/order (HMAC SHA256)** (Cancel an active order (TRADE).) 693 | ```python 694 | client.futures_cancel_order(symbol, orderId, origClientOrderId, recvWindow) 695 | ``` 696 | - **DELETE /fapi/v1/allOpenOrders (HMAC SHA256)** (Cancel All Open Orders (TRADE).) 697 | ```python 698 | client.futures_cancel_all_open_orders(symbol, recvWindow) 699 | ``` 700 | - **DELETE /fapi/v1/batchOrders (HMAC SHA256)** (Cancel Multiple Orders (TRADE).) 701 | ```python 702 | client.futures_cancel_orders(symbol, orderIdList, origClientOrderIdList, recvWindow) 703 | ``` 704 | - **POST /fapi/v1/countdownCancelAll (HMAC SHA256)** (Cancel all open orders of the specified symbol at the end of the specified countdown (TRADE).) 705 | 706 | > :warning: Not yet implemented 707 | - **GET /fapi/v1/openOrder (HMAC SHA256)** (Query Current Open Order (USER_DATA).) 708 | 709 | > :warning: Not yet implemented 710 | - **GET /fapi/v1/openOrders (HMAC SHA256)** (Get all open orders on a symbol. **Careful** when accessing this with no symbol (USER_DATA).) 711 | ```python 712 | client.futures_get_open_orders(symbol, recvWindow) 713 | ``` 714 | - **GET /fapi/v1/allOrders (HMAC SHA256)** (Get all account orders; active, canceled, or filled (USER_DATA).) 715 | ```python 716 | client.futures_get_all_orders(symbol, orderId, startTime, endTime, limit, recvWindow) 717 | ``` 718 | - **GET /fapi/v2/balance (HMAC SHA256)** (Futures Account Balance V2 (USER_DATA).) 719 | > :warning: Probably broken, python code below is implemented on v1 endpoint. 720 | ```python 721 | client.futures_account_balance(recvWindow) 722 | ``` 723 | - **GET /fapi/v2/account (HMAC SHA256)** (Account Information V2: Get current account information (USER_DATA).) 724 | > :warning: Probably broken, python code below is implemented on v1 endpoint. 725 | ```python 726 | client.futures_account(recvWindow) 727 | ``` 728 | - **POST /fapi/v1/leverage (HMAC SHA256)** (Change user's initial leverage of specific symbol market (TRADE).) 729 | ```python 730 | client.futures_change_leverage(symbol, leverage, recvWindow) 731 | ``` 732 | - **POST /fapi/v1/marginType (HMAC SHA256)** (Change the margin type for a symbol (TRADE).) 733 | ```python 734 | client.futures_change_margin_type(symbol, marginType, recvWindow) 735 | ``` 736 | - **POST /fapi/v1/positionMargin (HMAC SHA256)** (Modify Isolated Position Margin (TRADE).) 737 | ```python 738 | client.futures_change_position_margin(symbol, positionSide, amount, type, recvWindow) 739 | ``` 740 | - **GET /fapi/v1/positionMargin/history (HMAC SHA256)** (Get Position Margin Change History (TRADE).) 741 | ```python 742 | client.futures_position_margin_history(symbol, type, startTime, endTime, limit, recvWindow) 743 | ``` 744 | - **GET /fapi/v2/positionRisk (HMAC SHA256)** (Position Information V2: Get current position information (USER_DATA).) 745 | > :warning: Probably broken, python code below is implemented on v1 endpoint. 746 | ```python 747 | client.futures_position_information(symbol, recvWindow) 748 | ``` 749 | - **GET /fapi/v1/userTrades (HMAC SHA256)** (Account Trade List: Get trades for a specific account and symbol (USER_DATA).) 750 | ```python 751 | client.futures_account_trades(symbol, startTime, endTime, fromId, limit, recvWindow) 752 | ``` 753 | - **GET /fapi/v1/income (HMAC SHA256)** (Get Income History (USER_DATA).) 754 | ```python 755 | client.futures_income_history(symbol, incomeType, startTime, endTime, limit, recvWindow) 756 | ``` 757 | - **GET /fapi/v1/leverageBracket** (Notional and Leverage Brackets (USER_DATA).) 758 | > :warning: Probably broken, python code below is implemented on ticker/leverageBracket endpoint. 759 | ```python 760 | client.futures_leverage_bracket(symbol, recvWindow) 761 | ``` 762 | - **GET /fapi/v1/adlQuantile** (Position ADL Quantile Estimation (USER_DATA).) 763 | 764 | > :warning: Not yet implemented 765 | - **GET /fapi/v1/forceOrders** (User's Force Orders (USER_DATA).) 766 | 767 | > :warning: Not yet implemented 768 | - **GET /fapi/v1/apiTradingStatus** (User API Trading Quantitative Rules Indicators (USER_DATA).) 769 | 770 | > :warning: Not yet implemented 771 | - *User Data Streams* 772 | > :warning: Not yet implemented 773 | ### [Vanilla Options](https://binance-docs.github.io/apidocs/voptions/en/) 774 | - *Quoting interface* 775 | - **GET /vapi/v1/ping** (Test connectivity) 776 | ```python 777 | client.options_ping() 778 | ``` 779 | - **GET /vapi/v1/time** (Get server time) 780 | ```python 781 | client.options_time() 782 | ``` 783 | - **GET /vapi/v1/optionInfo** (Get current trading pair info) 784 | ```python 785 | client.options_info() 786 | ``` 787 | - **GET /vapi/v1/exchangeInfo** (Get current limit info and trading pair info) 788 | ```python 789 | client.options_exchange_info() 790 | ``` 791 | - **GET /vapi/v1/index** (Get the spot index price) 792 | ```python 793 | client.options_index_price(underlying) 794 | ``` 795 | - **GET /vapi/v1/ticker** (Get the latest price) 796 | ```python 797 | client.options_price(symbol) 798 | ``` 799 | - **GET /vapi/v1/mark** (Get the latest mark price) 800 | ```python 801 | client.options_mark_price(symbol) 802 | ``` 803 | - **GET /vapi/v1/depth** (Depth information) 804 | ```python 805 | client.options_order_book(symbol, limit) 806 | ``` 807 | - **GET /vapi/v1/klines** (Candle data) 808 | ```python 809 | client.options_klines(symbol, interval, startTime, endTime, limit) 810 | ``` 811 | - **GET /vapi/v1/trades** (Recently completed Option trades) 812 | ```python 813 | client.options_recent_trades(symbol, limit) 814 | ``` 815 | - **GET /vapi/v1/historicalTrades** (Query trade history) 816 | ```python 817 | client.options_historical_trades(symbol, fromId, limit) 818 | ``` 819 | - *Account and trading interface* 820 | - **GET /vapi/v1/account (HMAC SHA256)** (Account asset info (USER_DATA)) 821 | ```python 822 | client.options_account_info(recvWindow) 823 | ``` 824 | - **POST /vapi/v1/transfer (HMAC SHA256)** (Funds transfer (USER_DATA)) 825 | ```python 826 | client.options_funds_transfer(currency, type, amount, recvWindow) 827 | ``` 828 | - **GET /vapi/v1/position (HMAC SHA256)** (Option holdings info (USER_DATA)) 829 | ```python 830 | client.options_positions(symbol, recvWindow) 831 | ``` 832 | - **POST /vapi/v1/bill (HMAC SHA256)** (Account funding flow (USER_DATA)) 833 | ```python 834 | client.options_bill(currency, recordId, startTime, endTime, limit, recvWindow) 835 | ``` 836 | - **POST /vapi/v1/order (HMAC SHA256)** (Option order (TRADE)) 837 | ```python 838 | client.options_place_order(symbol, side, type, quantity, price, timeInForce, reduceOnly, postOnly, \ 839 | newOrderRespType, clientOrderId, recvWindow, recvWindow) 840 | ``` 841 | - **POST /vapi/v1/batchOrders (HMAC SHA256)** (Place Multiple Option orders (TRADE)) 842 | ```python 843 | client.options_place_batch_order(orders, recvWindow) 844 | ``` 845 | - **DELETE /vapi/v1/order (HMAC SHA256)** (Cancel Option order (TRADE)) 846 | ```python 847 | client.options_cancel_order(symbol, orderId, clientOrderId, recvWindow) 848 | ``` 849 | - **DELETE /vapi/v1/batchOrders (HMAC SHA256)** (Cancel Multiple Option orders (TRADE)) 850 | ```python 851 | client.options_cancel_batch_order(symbol, orderIds, clientOrderIds, recvWindow) 852 | ``` 853 | - **DELETE /vapi/v1/allOpenOrders (HMAC SHA256)** (Cancel all Option orders (TRADE)) 854 | ```python 855 | client.options_cancel_all_orders(symbol, recvWindow) 856 | ``` 857 | - **GET /vapi/v1/order (HMAC SHA256)** (Query Option order (TRADE)) 858 | ```python 859 | client.options_query_order(symbol, orderId, clientOrderId, recvWindow) 860 | ``` 861 | - **GET /vapi/v1/openOrders (HMAC SHA256)** (Query current pending Option orders (TRADE)) 862 | ```python 863 | client.options_query_pending_orders(symbol, orderId, startTime, endTime, limit, recvWindow) 864 | ``` 865 | - **GET /vapi/v1/historyOrders (HMAC SHA256)** (Query Option order history (TRADE)) 866 | ```python 867 | client.options_query_order_history(symbol, orderId, startTime, endTime, limit, recvWindow) 868 | ``` 869 | - **GET /vapi/v1/userTrades (HMAC SHA256)** (Option Trade List (USER_DATA)) 870 | ```python 871 | client.options_user_trades(symbol, fromId, startTime, endTime, limit, recvWindow) 872 | ``` 873 | ### [COIN-M Futures](https://binance-docs.github.io/apidocs/delivery/en/) 874 | > :warning: Not yet implemented 875 | ### [USDT-M Futures testnet](https://binance-docs.github.io/apidocs/testnet/en/) 876 | > :warning: Not yet implemented 877 | ### [COIN-M Futures testnet](https://binance-docs.github.io/apidocs/delivery_testnet/en/) 878 | > :warning: Not yet implemented 879 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 sammchardy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PYPIREADME.rst: -------------------------------------------------------------------------------- 1 | ================================= 2 | Welcome to python-binance v1.0.15 3 | ================================= 4 | 5 | Updated 27th Sept 2021 6 | 7 | .. image:: https://img.shields.io/pypi/v/python-binance.svg 8 | :target: https://pypi.python.org/pypi/python-binance 9 | 10 | .. image:: https://img.shields.io/pypi/l/python-binance.svg 11 | :target: https://pypi.python.org/pypi/python-binance 12 | 13 | .. image:: https://img.shields.io/travis/sammchardy/python-binance.svg 14 | :target: https://travis-ci.org/sammchardy/python-binance 15 | 16 | .. image:: https://img.shields.io/coveralls/sammchardy/python-binance.svg 17 | :target: https://coveralls.io/github/sammchardy/python-binance 18 | 19 | .. image:: https://img.shields.io/pypi/wheel/python-binance.svg 20 | :target: https://pypi.python.org/pypi/python-binance 21 | 22 | .. image:: https://img.shields.io/pypi/pyversions/python-binance.svg 23 | :target: https://pypi.python.org/pypi/python-binance 24 | 25 | This is an unofficial Python wrapper for the `Binance exchange REST API v3 `_. I am in no way affiliated with Binance, use at your own risk. 26 | 27 | If you came here looking for the `Binance exchange `_ to purchase cryptocurrencies, then `go here `_. 28 | If you want to automate interactions with Binance stick around. 29 | 30 | If you're interested in Binance's new DEX Binance Chain see my `python-binance-chain library `_ 31 | 32 | Source code 33 | https://github.com/sammchardy/python-binance 34 | 35 | Documentation 36 | https://python-binance.readthedocs.io/en/latest/ 37 | 38 | Binance API Telegram 39 | https://t.me/binance_api_english 40 | 41 | Blog with examples including async 42 | https://sammchardy.github.io 43 | 44 | - `Async basics for Binance `_ 45 | - `Understanding Binance Order Filters `_ 46 | 47 | Make sure you update often and check the `Changelog `_ for new features and bug fixes. 48 | 49 | Features 50 | -------- 51 | 52 | - Implementation of all General, Market Data and Account endpoints. 53 | - Asyncio implementation 54 | - Testnet support for Spot, Futures and Vanilla Options 55 | - Simple handling of authentication 56 | - No need to generate timestamps yourself, the wrapper does it for you 57 | - Response exception handling 58 | - Websocket handling with reconnection and multiplexed connections 59 | - Symbol Depth Cache 60 | - Historical Kline/Candle fetching function 61 | - Withdraw functionality 62 | - Deposit addresses 63 | - Margin Trading 64 | - Futures Trading 65 | - Vanilla Options 66 | - Support other domains (.us, .jp, etc) 67 | 68 | Upgrading to v1.0.0+ 69 | -------------------- 70 | 71 | The breaking changes include the migration from wapi to sapi endpoints which related to the 72 | wallet endpoints detailed in the `Binance Docs `_ 73 | 74 | The other breaking change is for websocket streams and the Depth Cache Manager which have been 75 | converted to use Asynchronous Context Managers. See examples in the Async section below or view the 76 | `websockets `_ and 77 | `depth cache `_ docs. 78 | 79 | Quick Start 80 | ----------- 81 | 82 | `Register an account with Binance `_. 83 | 84 | `Generate an API Key `_ and assign relevant permissions. 85 | 86 | If you are using an exchange from the US, Japan or other TLD then make sure pass `tld='us'` when creating the 87 | client. 88 | 89 | To use the `Spot `_ or `Vanilla Options `_ Testnet, 90 | pass `testnet=True` when creating the client. 91 | 92 | 93 | .. code:: bash 94 | 95 | pip install python-binance 96 | 97 | 98 | .. code:: python 99 | 100 | from binance import Client, ThreadedWebsocketManager, ThreadedDepthCacheManager 101 | client = Client(api_key, api_secret) 102 | 103 | # get market depth 104 | depth = client.get_order_book(symbol='BNBBTC') 105 | 106 | # place a test market buy order, to place an actual order use the create_order function 107 | order = client.create_test_order( 108 | symbol='BNBBTC', 109 | side=Client.SIDE_BUY, 110 | type=Client.ORDER_TYPE_MARKET, 111 | quantity=100) 112 | 113 | # get all symbol prices 114 | prices = client.get_all_tickers() 115 | 116 | # withdraw 100 ETH 117 | # check docs for assumptions around withdrawals 118 | from binance.exceptions import BinanceAPIException 119 | try: 120 | result = client.withdraw( 121 | asset='ETH', 122 | address='', 123 | amount=100) 124 | except BinanceAPIException as e: 125 | print(e) 126 | else: 127 | print("Success") 128 | 129 | # fetch list of withdrawals 130 | withdraws = client.get_withdraw_history() 131 | 132 | # fetch list of ETH withdrawals 133 | eth_withdraws = client.get_withdraw_history(coin='ETH') 134 | 135 | # get a deposit address for BTC 136 | address = client.get_deposit_address(coin='BTC') 137 | 138 | # get historical kline data from any date range 139 | 140 | # fetch 1 minute klines for the last day up until now 141 | klines = client.get_historical_klines("BNBBTC", Client.KLINE_INTERVAL_1MINUTE, "1 day ago UTC") 142 | 143 | # fetch 30 minute klines for the last month of 2017 144 | klines = client.get_historical_klines("ETHBTC", Client.KLINE_INTERVAL_30MINUTE, "1 Dec, 2017", "1 Jan, 2018") 145 | 146 | # fetch weekly klines since it listed 147 | klines = client.get_historical_klines("NEOBTC", Client.KLINE_INTERVAL_1WEEK, "1 Jan, 2017") 148 | 149 | # socket manager using threads 150 | twm = ThreadedWebsocketManager() 151 | twm.start() 152 | 153 | # depth cache manager using threads 154 | dcm = ThreadedDepthCacheManager() 155 | dcm.start() 156 | 157 | def handle_socket_message(msg): 158 | print(f"message type: {msg['e']}") 159 | print(msg) 160 | 161 | def handle_dcm_message(depth_cache): 162 | print(f"symbol {depth_cache.symbol}") 163 | print("top 5 bids") 164 | print(depth_cache.get_bids()[:5]) 165 | print("top 5 asks") 166 | print(depth_cache.get_asks()[:5]) 167 | print("last update time {}".format(depth_cache.update_time)) 168 | 169 | twm.start_kline_socket(callback=handle_socket_message, symbol='BNBBTC') 170 | 171 | dcm.start_depth_cache(callback=handle_dcm_message, symbol='ETHBTC') 172 | 173 | # replace with a current options symbol 174 | options_symbol = 'BTC-210430-36000-C' 175 | dcm.start_options_depth_cache(callback=handle_dcm_message, symbol=options_symbol) 176 | 177 | 178 | For more `check out the documentation `_. 179 | 180 | Async Example 181 | ------------- 182 | 183 | Read `Async basics for Binance `_ 184 | for more information. 185 | 186 | .. code:: python 187 | 188 | import asyncio 189 | import json 190 | 191 | from binance import AsyncClient, DepthCacheManager, BinanceSocketManager 192 | 193 | async def main(): 194 | 195 | # initialise the client 196 | client = await AsyncClient.create() 197 | 198 | # run some simple requests 199 | print(json.dumps(await client.get_exchange_info(), indent=2)) 200 | 201 | print(json.dumps(await client.get_symbol_ticker(symbol="BTCUSDT"), indent=2)) 202 | 203 | # initialise websocket factory manager 204 | bsm = BinanceSocketManager(client) 205 | 206 | # create listener using async with 207 | # this will exit and close the connection after 5 messages 208 | async with bsm.trade_socket('ETHBTC') as ts: 209 | for _ in range(5): 210 | res = await ts.recv() 211 | print(f'recv {res}') 212 | 213 | # get historical kline data from any date range 214 | 215 | # fetch 1 minute klines for the last day up until now 216 | klines = client.get_historical_klines("BNBBTC", AsyncClient.KLINE_INTERVAL_1MINUTE, "1 day ago UTC") 217 | 218 | # use generator to fetch 1 minute klines for the last day up until now 219 | async for kline in await client.get_historical_klines_generator("BNBBTC", AsyncClient.KLINE_INTERVAL_1MINUTE, "1 day ago UTC"): 220 | print(kline) 221 | 222 | # fetch 30 minute klines for the last month of 2017 223 | klines = client.get_historical_klines("ETHBTC", Client.KLINE_INTERVAL_30MINUTE, "1 Dec, 2017", "1 Jan, 2018") 224 | 225 | # fetch weekly klines since it listed 226 | klines = client.get_historical_klines("NEOBTC", Client.KLINE_INTERVAL_1WEEK, "1 Jan, 2017") 227 | 228 | # setup an async context the Depth Cache and exit after 5 messages 229 | async with DepthCacheManager(client, symbol='ETHBTC') as dcm_socket: 230 | for _ in range(5): 231 | depth_cache = await dcm_socket.recv() 232 | print(f"symbol {depth_cache.symbol} updated:{depth_cache.update_time}") 233 | print("Top 5 asks:") 234 | print(depth_cache.get_asks()[:5]) 235 | print("Top 5 bids:") 236 | print(depth_cache.get_bids()[:5]) 237 | 238 | # Vanilla options Depth Cache works the same, update the symbol to a current one 239 | options_symbol = 'BTC-210430-36000-C' 240 | async with OptionsDepthCacheManager(client, symbol=options_symbol) as dcm_socket: 241 | for _ in range(5): 242 | depth_cache = await dcm_socket.recv() 243 | count += 1 244 | print(f"symbol {depth_cache.symbol} updated:{depth_cache.update_time}") 245 | print("Top 5 asks:") 246 | print(depth_cache.get_asks()[:5]) 247 | print("Top 5 bids:") 248 | print(depth_cache.get_bids()[:5]) 249 | 250 | await client.close_connection() 251 | 252 | if __name__ == "__main__": 253 | 254 | loop = asyncio.get_event_loop() 255 | loop.run_until_complete(main()) 256 | 257 | 258 | Donate 259 | ------ 260 | 261 | If this library helped you out feel free to donate. 262 | 263 | - ETH: 0xD7a7fDdCfA687073d7cC93E9E51829a727f9fE70 264 | - LTC: LPC5vw9ajR1YndE1hYVeo3kJ9LdHjcRCUZ 265 | - NEO: AVJB4ZgN7VgSUtArCt94y7ZYT6d5NDfpBo 266 | - BTC: 1Dknp6L6oRZrHDECRedihPzx2sSfmvEBys 267 | 268 | Other Exchanges 269 | --------------- 270 | 271 | If you use `Binance Chain `_ check out my `python-binance-chain `_ library. 272 | 273 | If you use `Kucoin `_ check out my `python-kucoin `_ library. 274 | 275 | If you use `IDEX `_ check out my `python-idex `_ library. 276 | 277 | .. image:: https://ga-beacon.appspot.com/UA-111417213-1/github/python-binance?pixel&useReferer 278 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ================================= 2 | Welcome to python-binance v1.0.15 3 | ================================= 4 | 5 | Updated 27th Sept 2021 6 | 7 | .. image:: https://img.shields.io/pypi/v/python-binance.svg 8 | :target: https://pypi.python.org/pypi/python-binance 9 | 10 | .. image:: https://img.shields.io/pypi/l/python-binance.svg 11 | :target: https://pypi.python.org/pypi/python-binance 12 | 13 | .. image:: https://img.shields.io/travis/sammchardy/python-binance.svg 14 | :target: https://travis-ci.org/sammchardy/python-binance 15 | 16 | .. image:: https://img.shields.io/coveralls/sammchardy/python-binance.svg 17 | :target: https://coveralls.io/github/sammchardy/python-binance 18 | 19 | .. image:: https://img.shields.io/pypi/wheel/python-binance.svg 20 | :target: https://pypi.python.org/pypi/python-binance 21 | 22 | .. image:: https://img.shields.io/pypi/pyversions/python-binance.svg 23 | :target: https://pypi.python.org/pypi/python-binance 24 | 25 | This is an unofficial Python wrapper for the `Binance exchange REST API v3 `_. I am in no way affiliated with Binance, use at your own risk. 26 | 27 | If you came here looking for the `Binance exchange `_ to purchase cryptocurrencies, then `go here `_. 28 | If you want to automate interactions with Binance stick around. 29 | 30 | If you're interested in Binance's new DEX Binance Chain see my `python-binance-chain library `_ 31 | 32 | Source code 33 | https://github.com/sammchardy/python-binance 34 | 35 | Documentation 36 | https://python-binance.readthedocs.io/en/latest/ 37 | 38 | Binance API Telegram 39 | https://t.me/binance_api_english 40 | 41 | Blog with examples including async 42 | https://sammchardy.github.io 43 | 44 | - `Async basics for Binance `_ 45 | - `Understanding Binance Order Filters `_ 46 | 47 | Make sure you update often and check the `Changelog `_ for new features and bug fixes. 48 | 49 | Features 50 | -------- 51 | 52 | - Implementation of all General, Market Data and Account endpoints. 53 | - Asyncio implementation 54 | - Testnet support for Spot, Futures and Vanilla Options 55 | - Simple handling of authentication 56 | - No need to generate timestamps yourself, the wrapper does it for you 57 | - Response exception handling 58 | - Websocket handling with reconnection and multiplexed connections 59 | - Symbol Depth Cache 60 | - Historical Kline/Candle fetching function 61 | - Withdraw functionality 62 | - Deposit addresses 63 | - Margin Trading 64 | - Futures Trading 65 | - Vanilla Options 66 | - Support other domains (.us, .jp, etc) 67 | 68 | Upgrading to v1.0.0+ 69 | -------------------- 70 | 71 | The breaking changes include the migration from wapi to sapi endpoints which related to the 72 | wallet endpoints detailed in the `Binance Docs `_ 73 | 74 | The other breaking change is for websocket streams and the Depth Cache Manager which have been 75 | converted to use Asynchronous Context Managers. See examples in the Async section below or view the 76 | `websockets `_ and 77 | `depth cache `_ docs. 78 | 79 | Quick Start 80 | ----------- 81 | 82 | `Register an account with Binance `_. 83 | 84 | `Generate an API Key `_ and assign relevant permissions. 85 | 86 | If you are using an exchange from the US, Japan or other TLD then make sure pass `tld='us'` when creating the 87 | client. 88 | 89 | To use the `Spot `_ or `Vanilla Options `_ Testnet, 90 | pass `testnet=True` when creating the client. 91 | 92 | 93 | .. code:: bash 94 | 95 | pip install python-binance 96 | 97 | 98 | .. code:: python 99 | 100 | from binance import Client, ThreadedWebsocketManager, ThreadedDepthCacheManager 101 | client = Client(api_key, api_secret) 102 | 103 | # get market depth 104 | depth = client.get_order_book(symbol='BNBBTC') 105 | 106 | # place a test market buy order, to place an actual order use the create_order function 107 | order = client.create_test_order( 108 | symbol='BNBBTC', 109 | side=Client.SIDE_BUY, 110 | type=Client.ORDER_TYPE_MARKET, 111 | quantity=100) 112 | 113 | # get all symbol prices 114 | prices = client.get_all_tickers() 115 | 116 | # withdraw 100 ETH 117 | # check docs for assumptions around withdrawals 118 | from binance.exceptions import BinanceAPIException 119 | try: 120 | result = client.withdraw( 121 | asset='ETH', 122 | address='', 123 | amount=100) 124 | except BinanceAPIException as e: 125 | print(e) 126 | else: 127 | print("Success") 128 | 129 | # fetch list of withdrawals 130 | withdraws = client.get_withdraw_history() 131 | 132 | # fetch list of ETH withdrawals 133 | eth_withdraws = client.get_withdraw_history(coin='ETH') 134 | 135 | # get a deposit address for BTC 136 | address = client.get_deposit_address(coin='BTC') 137 | 138 | # get historical kline data from any date range 139 | 140 | # fetch 1 minute klines for the last day up until now 141 | klines = client.get_historical_klines("BNBBTC", Client.KLINE_INTERVAL_1MINUTE, "1 day ago UTC") 142 | 143 | # fetch 30 minute klines for the last month of 2017 144 | klines = client.get_historical_klines("ETHBTC", Client.KLINE_INTERVAL_30MINUTE, "1 Dec, 2017", "1 Jan, 2018") 145 | 146 | # fetch weekly klines since it listed 147 | klines = client.get_historical_klines("NEOBTC", Client.KLINE_INTERVAL_1WEEK, "1 Jan, 2017") 148 | 149 | # socket manager using threads 150 | twm = ThreadedWebsocketManager() 151 | twm.start() 152 | 153 | # depth cache manager using threads 154 | dcm = ThreadedDepthCacheManager() 155 | dcm.start() 156 | 157 | def handle_socket_message(msg): 158 | print(f"message type: {msg['e']}") 159 | print(msg) 160 | 161 | def handle_dcm_message(depth_cache): 162 | print(f"symbol {depth_cache.symbol}") 163 | print("top 5 bids") 164 | print(depth_cache.get_bids()[:5]) 165 | print("top 5 asks") 166 | print(depth_cache.get_asks()[:5]) 167 | print("last update time {}".format(depth_cache.update_time)) 168 | 169 | twm.start_kline_socket(callback=handle_socket_message, symbol='BNBBTC') 170 | 171 | dcm.start_depth_cache(callback=handle_dcm_message, symbol='ETHBTC') 172 | 173 | # replace with a current options symbol 174 | options_symbol = 'BTC-210430-36000-C' 175 | dcm.start_options_depth_cache(callback=handle_dcm_message, symbol=options_symbol) 176 | 177 | # join the threaded managers to the main thread 178 | twm.join() 179 | dcm.join() 180 | 181 | For more `check out the documentation `_. 182 | 183 | Async Example 184 | ------------- 185 | 186 | Read `Async basics for Binance `_ 187 | for more information. 188 | 189 | .. code:: python 190 | 191 | import asyncio 192 | import json 193 | 194 | from binance import AsyncClient, DepthCacheManager, BinanceSocketManager 195 | 196 | async def main(): 197 | 198 | # initialise the client 199 | client = await AsyncClient.create() 200 | 201 | # run some simple requests 202 | print(json.dumps(await client.get_exchange_info(), indent=2)) 203 | 204 | print(json.dumps(await client.get_symbol_ticker(symbol="BTCUSDT"), indent=2)) 205 | 206 | # initialise websocket factory manager 207 | bsm = BinanceSocketManager(client) 208 | 209 | # create listener using async with 210 | # this will exit and close the connection after 5 messages 211 | async with bsm.trade_socket('ETHBTC') as ts: 212 | for _ in range(5): 213 | res = await ts.recv() 214 | print(f'recv {res}') 215 | 216 | # get historical kline data from any date range 217 | 218 | # fetch 1 minute klines for the last day up until now 219 | klines = client.get_historical_klines("BNBBTC", AsyncClient.KLINE_INTERVAL_1MINUTE, "1 day ago UTC") 220 | 221 | # use generator to fetch 1 minute klines for the last day up until now 222 | async for kline in await client.get_historical_klines_generator("BNBBTC", AsyncClient.KLINE_INTERVAL_1MINUTE, "1 day ago UTC"): 223 | print(kline) 224 | 225 | # fetch 30 minute klines for the last month of 2017 226 | klines = client.get_historical_klines("ETHBTC", Client.KLINE_INTERVAL_30MINUTE, "1 Dec, 2017", "1 Jan, 2018") 227 | 228 | # fetch weekly klines since it listed 229 | klines = client.get_historical_klines("NEOBTC", Client.KLINE_INTERVAL_1WEEK, "1 Jan, 2017") 230 | 231 | # setup an async context the Depth Cache and exit after 5 messages 232 | async with DepthCacheManager(client, symbol='ETHBTC') as dcm_socket: 233 | for _ in range(5): 234 | depth_cache = await dcm_socket.recv() 235 | print(f"symbol {depth_cache.symbol} updated:{depth_cache.update_time}") 236 | print("Top 5 asks:") 237 | print(depth_cache.get_asks()[:5]) 238 | print("Top 5 bids:") 239 | print(depth_cache.get_bids()[:5]) 240 | 241 | # Vanilla options Depth Cache works the same, update the symbol to a current one 242 | options_symbol = 'BTC-210430-36000-C' 243 | async with OptionsDepthCacheManager(client, symbol=options_symbol) as dcm_socket: 244 | for _ in range(5): 245 | depth_cache = await dcm_socket.recv() 246 | count += 1 247 | print(f"symbol {depth_cache.symbol} updated:{depth_cache.update_time}") 248 | print("Top 5 asks:") 249 | print(depth_cache.get_asks()[:5]) 250 | print("Top 5 bids:") 251 | print(depth_cache.get_bids()[:5]) 252 | 253 | await client.close_connection() 254 | 255 | if __name__ == "__main__": 256 | 257 | loop = asyncio.get_event_loop() 258 | loop.run_until_complete(main()) 259 | 260 | 261 | Donate 262 | ------ 263 | 264 | If this library helped you out feel free to donate. 265 | 266 | - ETH: 0xD7a7fDdCfA687073d7cC93E9E51829a727f9fE70 267 | - LTC: LPC5vw9ajR1YndE1hYVeo3kJ9LdHjcRCUZ 268 | - NEO: AVJB4ZgN7VgSUtArCt94y7ZYT6d5NDfpBo 269 | - BTC: 1Dknp6L6oRZrHDECRedihPzx2sSfmvEBys 270 | 271 | Other Exchanges 272 | --------------- 273 | 274 | If you use `Binance Chain `_ check out my `python-binance-chain `_ library. 275 | 276 | If you use `Kucoin `_ check out my `python-kucoin `_ library. 277 | 278 | If you use `IDEX `_ check out my `python-idex `_ library. 279 | 280 | .. image:: https://ga-beacon.appspot.com/UA-111417213-1/github/python-binance?pixel&useReferer 281 | -------------------------------------------------------------------------------- /binance/__init__.py: -------------------------------------------------------------------------------- 1 | """An unofficial Python wrapper for the Binance exchange API v3 2 | 3 | .. moduleauthor:: Sam McHardy 4 | 5 | """ 6 | 7 | __version__ = '1.0.15' 8 | 9 | from binance.client import Client, AsyncClient # noqa 10 | from binance.depthcache import DepthCacheManager, OptionsDepthCacheManager, ThreadedDepthCacheManager # noqa 11 | from binance.streams import BinanceSocketManager, ThreadedWebsocketManager # noqa 12 | -------------------------------------------------------------------------------- /binance/depthcache.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from operator import itemgetter 3 | import asyncio 4 | import time 5 | from typing import Optional, Dict, Callable 6 | 7 | from .streams import BinanceSocketManager 8 | from .threaded_stream import ThreadedApiManager 9 | 10 | 11 | class DepthCache(object): 12 | 13 | def __init__(self, symbol, conv_type=float): 14 | """Initialise the DepthCache 15 | 16 | :param symbol: Symbol to create depth cache for 17 | :type symbol: string 18 | :param conv_type: Optional type to represent price, and amount, default is float. 19 | :type conv_type: function. 20 | 21 | """ 22 | self.symbol = symbol 23 | self._bids = {} 24 | self._asks = {} 25 | self.update_time = None 26 | self.conv_type = conv_type 27 | self._log = logging.getLogger(__name__) 28 | 29 | def add_bid(self, bid): 30 | """Add a bid to the cache 31 | 32 | :param bid: 33 | :return: 34 | 35 | """ 36 | self._bids[bid[0]] = self.conv_type(bid[1]) 37 | if bid[1] == "0.00000000": 38 | del self._bids[bid[0]] 39 | 40 | def add_ask(self, ask): 41 | """Add an ask to the cache 42 | 43 | :param ask: 44 | :return: 45 | 46 | """ 47 | self._asks[ask[0]] = self.conv_type(ask[1]) 48 | if ask[1] == "0.00000000": 49 | del self._asks[ask[0]] 50 | 51 | def get_bids(self): 52 | """Get the current bids 53 | 54 | :return: list of bids with price and quantity as conv_type 55 | 56 | .. code-block:: python 57 | 58 | [ 59 | [ 60 | 0.0001946, # Price 61 | 45.0 # Quantity 62 | ], 63 | [ 64 | 0.00019459, 65 | 2384.0 66 | ], 67 | [ 68 | 0.00019158, 69 | 5219.0 70 | ], 71 | [ 72 | 0.00019157, 73 | 1180.0 74 | ], 75 | [ 76 | 0.00019082, 77 | 287.0 78 | ] 79 | ] 80 | 81 | """ 82 | return DepthCache.sort_depth(self._bids, reverse=True, conv_type=self.conv_type) 83 | 84 | def get_asks(self): 85 | """Get the current asks 86 | 87 | :return: list of asks with price and quantity as conv_type. 88 | 89 | .. code-block:: python 90 | 91 | [ 92 | [ 93 | 0.0001955, # Price 94 | 57.0' # Quantity 95 | ], 96 | [ 97 | 0.00019699, 98 | 778.0 99 | ], 100 | [ 101 | 0.000197, 102 | 64.0 103 | ], 104 | [ 105 | 0.00019709, 106 | 1130.0 107 | ], 108 | [ 109 | 0.0001971, 110 | 385.0 111 | ] 112 | ] 113 | 114 | """ 115 | return DepthCache.sort_depth(self._asks, reverse=False, conv_type=self.conv_type) 116 | 117 | @staticmethod 118 | def sort_depth(vals, reverse=False, conv_type=float): 119 | """Sort bids or asks by price 120 | """ 121 | if isinstance(vals, dict): 122 | lst = [[conv_type(price), conv_type(quantity)] for price, quantity in vals.items()] 123 | elif isinstance(vals, list): 124 | lst = [[conv_type(price), conv_type(quantity)] for price, quantity in vals] 125 | else: 126 | raise ValueError(f'Unknown order book depth data type: {type(vals)}') 127 | lst = sorted(lst, key=itemgetter(0), reverse=reverse) 128 | return lst 129 | 130 | 131 | class BaseDepthCacheManager: 132 | DEFAULT_REFRESH = 60 * 30 # 30 minutes 133 | TIMEOUT = 60 134 | 135 | def __init__(self, client, symbol, loop=None, refresh_interval=None, bm=None, limit=10, conv_type=float): 136 | """Create a DepthCacheManager instance 137 | 138 | :param client: Binance API client 139 | :type client: binance.Client 140 | :param loop: 141 | :type loop: 142 | :param symbol: Symbol to create depth cache for 143 | :type symbol: string 144 | :param refresh_interval: Optional number of seconds between cache refresh, use 0 or None to disable 145 | :type refresh_interval: int 146 | :param bm: Optional BinanceSocketManager 147 | :type bm: BinanceSocketManager 148 | :param limit: Optional number of orders to get from orderbook 149 | :type limit: int 150 | :param conv_type: Optional type to represent price, and amount, default is float. 151 | :type conv_type: function. 152 | 153 | """ 154 | 155 | self._client = client 156 | self._depth_cache = None 157 | self._loop = loop or asyncio.get_event_loop() 158 | self._symbol = symbol 159 | self._limit = limit 160 | self._last_update_id = None 161 | self._bm = bm or BinanceSocketManager(self._client, self._loop) 162 | self._refresh_interval = refresh_interval or self.DEFAULT_REFRESH 163 | self._conn_key = None 164 | self._conv_type = conv_type 165 | self._log = logging.getLogger(__name__) 166 | 167 | async def __aenter__(self): 168 | await asyncio.gather( 169 | self._init_cache(), 170 | self._start_socket() 171 | ) 172 | await self._socket.__aenter__() 173 | return self 174 | 175 | async def __aexit__(self, *args, **kwargs): 176 | await self._socket.__aexit__(*args, **kwargs) 177 | 178 | async def recv(self): 179 | dc = None 180 | while not dc: 181 | try: 182 | res = await asyncio.wait_for(self._socket.recv(), timeout=self.TIMEOUT) 183 | except Exception as e: 184 | self._log.warning(e) 185 | else: 186 | dc = await self._depth_event(res) 187 | return dc 188 | 189 | async def _init_cache(self): 190 | """Initialise the depth cache calling REST endpoint 191 | 192 | :return: 193 | """ 194 | 195 | # initialise or clear depth cache 196 | self._depth_cache = DepthCache(self._symbol, conv_type=self._conv_type) 197 | 198 | # set a time to refresh the depth cache 199 | if self._refresh_interval: 200 | self._refresh_time = int(time.time()) + self._refresh_interval 201 | 202 | async def _start_socket(self): 203 | """Start the depth cache socket 204 | 205 | :return: 206 | """ 207 | self._socket = self._get_socket() 208 | 209 | def _get_socket(self): 210 | raise NotImplementedError 211 | 212 | async def _depth_event(self, msg): 213 | """Handle a depth event 214 | 215 | :param msg: 216 | :return: 217 | 218 | """ 219 | 220 | if not msg: 221 | return None 222 | 223 | if 'e' in msg and msg['e'] == 'error': 224 | # close the socket 225 | await self.close() 226 | 227 | # notify the user by returning a None value 228 | return None 229 | 230 | return await self._process_depth_message(msg) 231 | 232 | async def _process_depth_message(self, msg): 233 | """Process a depth event message. 234 | 235 | :param msg: Depth event message. 236 | :return: 237 | 238 | """ 239 | 240 | # add any bid or ask values 241 | self._apply_orders(msg) 242 | 243 | # call the callback with the updated depth cache 244 | res = self._depth_cache 245 | 246 | # after processing event see if we need to refresh the depth cache 247 | if self._refresh_interval and int(time.time()) > self._refresh_time: 248 | await self._init_cache() 249 | 250 | return res 251 | 252 | def _apply_orders(self, msg): 253 | for bid in msg.get('b', []) + msg.get('bids', []): 254 | self._depth_cache.add_bid(bid) 255 | for ask in msg.get('a', []) + msg.get('asks', []): 256 | self._depth_cache.add_ask(ask) 257 | 258 | # keeping update time 259 | self._depth_cache.update_time = msg.get('E') or msg.get('lastUpdateId') 260 | 261 | def get_depth_cache(self): 262 | """Get the current depth cache 263 | 264 | :return: DepthCache object 265 | 266 | """ 267 | return self._depth_cache 268 | 269 | async def close(self): 270 | """Close the open socket for this manager 271 | 272 | :return: 273 | """ 274 | self._depth_cache = None 275 | 276 | def get_symbol(self): 277 | """Get the symbol 278 | 279 | :return: symbol 280 | """ 281 | return self._symbol 282 | 283 | 284 | class DepthCacheManager(BaseDepthCacheManager): 285 | 286 | def __init__( 287 | self, client, symbol, loop=None, refresh_interval=None, bm=None, limit=500, conv_type=float, ws_interval=None 288 | ): 289 | """Initialise the DepthCacheManager 290 | 291 | :param client: Binance API client 292 | :type client: binance.Client 293 | :param loop: asyncio loop 294 | :param symbol: Symbol to create depth cache for 295 | :type symbol: string 296 | :param refresh_interval: Optional number of seconds between cache refresh, use 0 or None to disable 297 | :type refresh_interval: int 298 | :param limit: Optional number of orders to get from orderbook 299 | :type limit: int 300 | :param conv_type: Optional type to represent price, and amount, default is float. 301 | :type conv_type: function. 302 | :param ws_interval: Optional interval for updates on websocket, default None. If not set, updates happen every second. Must be 0, None (1s) or 100 (100ms). 303 | :type ws_interval: int 304 | 305 | """ 306 | super().__init__(client, symbol, loop, refresh_interval, bm, limit, conv_type) 307 | self._ws_interval = ws_interval 308 | 309 | async def _init_cache(self): 310 | """Initialise the depth cache calling REST endpoint 311 | 312 | :return: 313 | """ 314 | self._last_update_id = None 315 | self._depth_message_buffer = [] 316 | 317 | res = await self._client.get_order_book(symbol=self._symbol, limit=self._limit) 318 | 319 | # initialise or clear depth cache 320 | await super()._init_cache() 321 | 322 | # process bid and asks from the order book 323 | self._apply_orders(res) 324 | for bid in res['bids']: 325 | self._depth_cache.add_bid(bid) 326 | for ask in res['asks']: 327 | self._depth_cache.add_ask(ask) 328 | 329 | # set first update id 330 | self._last_update_id = res['lastUpdateId'] 331 | 332 | # Apply any updates from the websocket 333 | for msg in self._depth_message_buffer: 334 | await self._process_depth_message(msg) 335 | 336 | # clear the depth buffer 337 | self._depth_message_buffer = [] 338 | 339 | async def _start_socket(self): 340 | """Start the depth cache socket 341 | 342 | :return: 343 | """ 344 | if not getattr(self, '_depth_message_buffer', None): 345 | self._depth_message_buffer = [] 346 | 347 | await super()._start_socket() 348 | 349 | def _get_socket(self): 350 | return self._bm.depth_socket(self._symbol, interval=self._ws_interval) 351 | 352 | async def _process_depth_message(self, msg): 353 | """Process a depth event message. 354 | 355 | :param msg: Depth event message. 356 | :return: 357 | 358 | """ 359 | 360 | if self._last_update_id is None: 361 | # Initial depth snapshot fetch not yet performed, buffer messages 362 | self._depth_message_buffer.append(msg) 363 | return 364 | 365 | if msg['u'] <= self._last_update_id: 366 | # ignore any updates before the initial update id 367 | return 368 | elif msg['U'] != self._last_update_id + 1: 369 | # if not buffered check we get sequential updates 370 | # otherwise init cache again 371 | await self._init_cache() 372 | 373 | # add any bid or ask values 374 | self._apply_orders(msg) 375 | 376 | # call the callback with the updated depth cache 377 | res = self._depth_cache 378 | 379 | self._last_update_id = msg['u'] 380 | 381 | # after processing event see if we need to refresh the depth cache 382 | if self._refresh_interval and int(time.time()) > self._refresh_time: 383 | await self._init_cache() 384 | 385 | return res 386 | 387 | 388 | class FuturesDepthCacheManager(BaseDepthCacheManager): 389 | async def _process_depth_message(self, msg): 390 | """Process a depth event message. 391 | 392 | :param msg: Depth event message. 393 | :return: 394 | 395 | """ 396 | msg = msg.get('data') 397 | return await super()._process_depth_message(msg) 398 | 399 | def _apply_orders(self, msg): 400 | self._depth_cache._bids = msg.get('b', []) 401 | self._depth_cache._asks = msg.get('a', []) 402 | 403 | # keeping update time 404 | self._depth_cache.update_time = msg.get('E') or msg.get('lastUpdateId') 405 | 406 | def _get_socket(self): 407 | sock = self._bm.futures_depth_socket(self._symbol) 408 | return sock 409 | 410 | 411 | class OptionsDepthCacheManager(BaseDepthCacheManager): 412 | 413 | def _get_socket(self): 414 | return self._bm.options_depth_socket(self._symbol) 415 | 416 | 417 | class ThreadedDepthCacheManager(ThreadedApiManager): 418 | 419 | def __init__( 420 | self, api_key: Optional[str] = None, api_secret: Optional[str] = None, 421 | requests_params: Dict[str, str] = None, tld: str = 'com', 422 | testnet: bool = False 423 | ): 424 | super().__init__(api_key, api_secret, requests_params, tld, testnet) 425 | 426 | def _start_depth_cache( 427 | self, dcm_class, callback: Callable, symbol: str, 428 | refresh_interval=None, bm=None, limit=10, conv_type=float, **kwargs 429 | ) -> str: 430 | dcm = dcm_class( 431 | client=self._client, 432 | symbol=symbol, 433 | loop=self._loop, 434 | refresh_interval=refresh_interval, 435 | bm=bm, 436 | limit=limit, 437 | conv_type=conv_type, 438 | **kwargs 439 | ) 440 | path = symbol.lower() + '@depth' + str(limit) 441 | self._socket_running[path] = True 442 | self._loop.call_soon(asyncio.create_task, self.start_listener(dcm, path, callback)) 443 | return path 444 | 445 | def start_depth_cache( 446 | self, callback: Callable, symbol: str, refresh_interval=None, bm=None, limit=10, conv_type=float, ws_interval=0 447 | ) -> str: 448 | return self._start_depth_cache( 449 | dcm_class=DepthCacheManager, 450 | callback=callback, 451 | symbol=symbol, 452 | refresh_interval=refresh_interval, 453 | bm=bm, 454 | limit=limit, 455 | conv_type=conv_type, 456 | ws_interval=ws_interval 457 | ) 458 | 459 | def start_futures_depth_socket( 460 | self, callback: Callable, symbol: str, refresh_interval=None, bm=None, limit=10, conv_type=float 461 | ) -> str: 462 | return self._start_depth_cache( 463 | dcm_class=FuturesDepthCacheManager, 464 | callback=callback, 465 | symbol=symbol, 466 | refresh_interval=refresh_interval, 467 | bm=bm, 468 | limit=limit, 469 | conv_type=conv_type 470 | ) 471 | 472 | def start_options_depth_socket( 473 | self, callback: Callable, symbol: str, refresh_interval=None, bm=None, limit=10, conv_type=float 474 | ) -> str: 475 | return self._start_depth_cache( 476 | dcm_class=OptionsDepthCacheManager, 477 | callback=callback, 478 | symbol=symbol, 479 | refresh_interval=refresh_interval, 480 | bm=bm, 481 | limit=limit, 482 | conv_type=conv_type 483 | ) 484 | -------------------------------------------------------------------------------- /binance/enums.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | SYMBOL_TYPE_SPOT = 'SPOT' 4 | 5 | ORDER_STATUS_NEW = 'NEW' 6 | ORDER_STATUS_PARTIALLY_FILLED = 'PARTIALLY_FILLED' 7 | ORDER_STATUS_FILLED = 'FILLED' 8 | ORDER_STATUS_CANCELED = 'CANCELED' 9 | ORDER_STATUS_PENDING_CANCEL = 'PENDING_CANCEL' 10 | ORDER_STATUS_REJECTED = 'REJECTED' 11 | ORDER_STATUS_EXPIRED = 'EXPIRED' 12 | 13 | KLINE_INTERVAL_1MINUTE = '1m' 14 | KLINE_INTERVAL_3MINUTE = '3m' 15 | KLINE_INTERVAL_5MINUTE = '5m' 16 | KLINE_INTERVAL_15MINUTE = '15m' 17 | KLINE_INTERVAL_30MINUTE = '30m' 18 | KLINE_INTERVAL_1HOUR = '1h' 19 | KLINE_INTERVAL_2HOUR = '2h' 20 | KLINE_INTERVAL_4HOUR = '4h' 21 | KLINE_INTERVAL_6HOUR = '6h' 22 | KLINE_INTERVAL_8HOUR = '8h' 23 | KLINE_INTERVAL_12HOUR = '12h' 24 | KLINE_INTERVAL_1DAY = '1d' 25 | KLINE_INTERVAL_3DAY = '3d' 26 | KLINE_INTERVAL_1WEEK = '1w' 27 | KLINE_INTERVAL_1MONTH = '1M' 28 | 29 | SIDE_BUY = 'BUY' 30 | SIDE_SELL = 'SELL' 31 | 32 | ORDER_TYPE_LIMIT = 'LIMIT' 33 | ORDER_TYPE_MARKET = 'MARKET' 34 | ORDER_TYPE_STOP_LOSS = 'STOP_LOSS' 35 | ORDER_TYPE_STOP_LOSS_LIMIT = 'STOP_LOSS_LIMIT' 36 | ORDER_TYPE_TAKE_PROFIT = 'TAKE_PROFIT' 37 | ORDER_TYPE_TAKE_PROFIT_LIMIT = 'TAKE_PROFIT_LIMIT' 38 | ORDER_TYPE_LIMIT_MAKER = 'LIMIT_MAKER' 39 | 40 | FUTURE_ORDER_TYPE_LIMIT = 'LIMIT' 41 | FUTURE_ORDER_TYPE_MARKET = 'MARKET' 42 | FUTURE_ORDER_TYPE_STOP = 'STOP' 43 | FUTURE_ORDER_TYPE_STOP_MARKET = 'STOP_MARKET' 44 | FUTURE_ORDER_TYPE_TAKE_PROFIT = 'TAKE_PROFIT' 45 | FUTURE_ORDER_TYPE_TAKE_PROFIT_MARKET = 'TAKE_PROFIT_MARKET' 46 | FUTURE_ORDER_TYPE_LIMIT_MAKER = 'LIMIT_MAKER' 47 | 48 | TIME_IN_FORCE_GTC = 'GTC' # Good till cancelled 49 | TIME_IN_FORCE_IOC = 'IOC' # Immediate or cancel 50 | TIME_IN_FORCE_FOK = 'FOK' # Fill or kill 51 | TIME_IN_FORCE_GTX = 'GTX' # Post only order 52 | 53 | ORDER_RESP_TYPE_ACK = 'ACK' 54 | ORDER_RESP_TYPE_RESULT = 'RESULT' 55 | ORDER_RESP_TYPE_FULL = 'FULL' 56 | 57 | WEBSOCKET_DEPTH_5 = '5' 58 | WEBSOCKET_DEPTH_10 = '10' 59 | WEBSOCKET_DEPTH_20 = '20' 60 | 61 | NO_SIDE_EFFECT_TYPE = 'NO_SIDE_EFFECT' 62 | MARGIN_BUY_TYPE = 'MARGIN_BUY' 63 | AUTO_REPAY_TYPE = 'AUTO_REPAY' 64 | 65 | 66 | class HistoricalKlinesType(Enum): 67 | SPOT = 1 68 | FUTURES = 2 69 | 70 | 71 | class FuturesType(Enum): 72 | USD_M = 1 73 | COIN_M = 2 74 | 75 | 76 | class ContractType(Enum): 77 | PERPETUAL = "perpetual" 78 | CURRENT_QUARTER = "current_quarter" 79 | NEXT_QUARTER = "next_quarter" 80 | -------------------------------------------------------------------------------- /binance/exceptions.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import json 3 | 4 | 5 | class BinanceAPIException(Exception): 6 | 7 | def __init__(self, response, status_code, text): 8 | self.code = 0 9 | try: 10 | json_res = json.loads(text) 11 | except ValueError: 12 | self.message = 'Invalid JSON error message from Binance: {}'.format(response.text) 13 | else: 14 | self.code = json_res['code'] 15 | self.message = json_res['msg'] 16 | self.status_code = status_code 17 | self.response = response 18 | self.request = getattr(response, 'request', None) 19 | 20 | def __str__(self): # pragma: no cover 21 | return 'APIError(code=%s): %s' % (self.code, self.message) 22 | 23 | 24 | class BinanceRequestException(Exception): 25 | def __init__(self, message): 26 | self.message = message 27 | 28 | def __str__(self): 29 | return 'BinanceRequestException: %s' % self.message 30 | 31 | 32 | class BinanceOrderException(Exception): 33 | 34 | def __init__(self, code, message): 35 | self.code = code 36 | self.message = message 37 | 38 | def __str__(self): 39 | return 'BinanceOrderException(code=%s): %s' % (self.code, self.message) 40 | 41 | 42 | class BinanceOrderMinAmountException(BinanceOrderException): 43 | 44 | def __init__(self, value): 45 | message = "Amount must be a multiple of %s" % value 46 | super().__init__(-1013, message) 47 | 48 | 49 | class BinanceOrderMinPriceException(BinanceOrderException): 50 | 51 | def __init__(self, value): 52 | message = "Price must be at least %s" % value 53 | super().__init__(-1013, message) 54 | 55 | 56 | class BinanceOrderMinTotalException(BinanceOrderException): 57 | 58 | def __init__(self, value): 59 | message = "Total must be at least %s" % value 60 | super().__init__(-1013, message) 61 | 62 | 63 | class BinanceOrderUnknownSymbolException(BinanceOrderException): 64 | 65 | def __init__(self, value): 66 | message = "Unknown symbol %s" % value 67 | super().__init__(-1013, message) 68 | 69 | 70 | class BinanceOrderInactiveSymbolException(BinanceOrderException): 71 | 72 | def __init__(self, value): 73 | message = "Attempting to trade an inactive symbol %s" % value 74 | super().__init__(-1013, message) 75 | 76 | 77 | class BinanceWebsocketUnableToConnect(Exception): 78 | pass 79 | 80 | 81 | class NotImplementedException(Exception): 82 | def __init__(self, value): 83 | message = f'Not implemented: {value}' 84 | super().__init__(message) 85 | -------------------------------------------------------------------------------- /binance/helpers.py: -------------------------------------------------------------------------------- 1 | from decimal import Decimal 2 | from typing import Union, Optional, Dict 3 | 4 | import dateparser 5 | import math 6 | import pytz 7 | 8 | from datetime import datetime 9 | 10 | 11 | def date_to_milliseconds(date_str: str) -> int: 12 | """Convert UTC date to milliseconds 13 | 14 | If using offset strings add "UTC" to date string e.g. "now UTC", "11 hours ago UTC" 15 | 16 | See dateparse docs for formats http://dateparser.readthedocs.io/en/latest/ 17 | 18 | :param date_str: date in readable format, i.e. "January 01, 2018", "11 hours ago UTC", "now UTC" 19 | """ 20 | # get epoch value in UTC 21 | epoch: datetime = datetime.utcfromtimestamp(0).replace(tzinfo=pytz.utc) 22 | # parse our date string 23 | d: Optional[datetime] = dateparser.parse(date_str, settings={'TIMEZONE': "UTC"}) 24 | # if the date is not timezone aware apply UTC timezone 25 | if d.tzinfo is None or d.tzinfo.utcoffset(d) is None: 26 | d = d.replace(tzinfo=pytz.utc) 27 | 28 | # return the difference in time 29 | return int((d - epoch).total_seconds() * 1000.0) 30 | 31 | 32 | def interval_to_milliseconds(interval: str) -> Optional[int]: 33 | """Convert a Binance interval string to milliseconds 34 | 35 | :param interval: Binance interval string, e.g.: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w 36 | 37 | :return: 38 | int value of interval in milliseconds 39 | None if interval prefix is not a decimal integer 40 | None if interval suffix is not one of m, h, d, w 41 | 42 | """ 43 | seconds_per_unit: Dict[str, int] = { 44 | "m": 60, 45 | "h": 60 * 60, 46 | "d": 24 * 60 * 60, 47 | "w": 7 * 24 * 60 * 60, 48 | } 49 | try: 50 | return int(interval[:-1]) * seconds_per_unit[interval[-1]] * 1000 51 | except (ValueError, KeyError): 52 | return None 53 | 54 | 55 | def round_step_size(quantity: Union[float, Decimal], step_size: Union[float, Decimal]) -> float: 56 | """Rounds a given quantity to a specific step size 57 | 58 | :param quantity: required 59 | :param step_size: required 60 | 61 | :return: decimal 62 | """ 63 | precision: int = int(round(-math.log(step_size, 10), 0)) 64 | return float(round(quantity, precision)) 65 | 66 | 67 | def convert_ts_str(ts_str): 68 | if ts_str is None: 69 | return ts_str 70 | if type(ts_str) == int: 71 | return ts_str 72 | return date_to_milliseconds(ts_str) 73 | -------------------------------------------------------------------------------- /binance/threaded_stream.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import threading 3 | from typing import Optional, Dict 4 | 5 | from .client import AsyncClient 6 | 7 | 8 | class ThreadedApiManager(threading.Thread): 9 | 10 | def __init__( 11 | self, api_key: Optional[str] = None, api_secret: Optional[str] = None, 12 | requests_params: Dict[str, str] = None, tld: str = 'com', 13 | testnet: bool = False 14 | ): 15 | """Initialise the BinanceSocketManager 16 | 17 | """ 18 | super().__init__() 19 | self._loop: asyncio.AbstractEventLoop = asyncio.new_event_loop() 20 | self._client: Optional[AsyncClient] = None 21 | self._running: bool = True 22 | self._socket_running: Dict[str, bool] = {} 23 | self._client_params = { 24 | 'api_key': api_key, 25 | 'api_secret': api_secret, 26 | 'requests_params': requests_params, 27 | 'tld': tld, 28 | 'testnet': testnet 29 | } 30 | 31 | async def _before_socket_listener_start(self): 32 | ... 33 | 34 | async def socket_listener(self): 35 | self._client = await AsyncClient.create(loop=self._loop, **self._client_params) 36 | await self._before_socket_listener_start() 37 | while self._running: 38 | await asyncio.sleep(0.2) 39 | while self._socket_running: 40 | await asyncio.sleep(0.2) 41 | 42 | async def start_listener(self, socket, path: str, callback): 43 | async with socket as s: 44 | while self._socket_running[path]: 45 | try: 46 | msg = await asyncio.wait_for(s.recv(), 3) 47 | except asyncio.TimeoutError: 48 | ... 49 | continue 50 | if not msg: 51 | continue 52 | callback(msg) 53 | del self._socket_running[path] 54 | 55 | def run(self): 56 | self._loop.run_until_complete(self.socket_listener()) 57 | 58 | def stop_socket(self, socket_name): 59 | if socket_name in self._socket_running: 60 | self._socket_running[socket_name] = False 61 | 62 | async def stop_client(self): 63 | await self._client.close_connection() 64 | 65 | def stop(self): 66 | if not self._running: 67 | return 68 | self._running = False 69 | self._loop.call_soon(asyncio.create_task, self.stop_client()) 70 | for socket_name in self._socket_running.keys(): 71 | self._socket_running[socket_name] = False 72 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = python-binance 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | 22 | rst: 23 | sphinx-apidoc -f -o ./ ../ 24 | -------------------------------------------------------------------------------- /docs/account.rst: -------------------------------------------------------------------------------- 1 | Account Endpoints 2 | ================= 3 | 4 | Orders 5 | ------ 6 | 7 | Order Validation 8 | ^^^^^^^^^^^^^^^^ 9 | 10 | Binance has a number of rules around symbol pair orders with validation on minimum price, quantity and total order value. 11 | 12 | Read more about their specifics in the `Filters `_ 13 | section of the official API. 14 | 15 | Read `Understanding Binance Order Filters `_ 16 | for more information about price and quantity filters on `Binance `_. 17 | 18 | It can be helpful to format the output using formatting 19 | 20 | .. code:: python 21 | 22 | amount = 0.000234234 23 | precision = 5 24 | amt_str = "{:0.0{}f}".format(amount, precision) 25 | 26 | Or if you have the tickSize or stepSize then use the helper to round to step size 27 | 28 | .. code:: python 29 | 30 | from binance.helpers import round_step_size 31 | 32 | amount = 0.000234234 33 | tick_size = 0.00001 34 | rounded_amount = round_step_size(amount, tick_size) 35 | 36 | 37 | `Fetch all orders `_ 38 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 39 | 40 | .. code:: python 41 | 42 | orders = client.get_all_orders(symbol='BNBBTC', limit=10) 43 | 44 | 45 | `Place an order `_ 46 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 47 | 48 | **Place an order** 49 | 50 | Use the `create_order` function to have full control over creating an order 51 | 52 | .. code:: python 53 | 54 | from binance.enums import * 55 | order = client.create_order( 56 | symbol='BNBBTC', 57 | side=SIDE_BUY, 58 | type=ORDER_TYPE_LIMIT, 59 | timeInForce=TIME_IN_FORCE_GTC, 60 | quantity=100, 61 | price='0.00001') 62 | 63 | **Place a limit order** 64 | 65 | Use the helper functions to easily place a limit buy or sell order 66 | 67 | .. code:: python 68 | 69 | order = client.order_limit_buy( 70 | symbol='BNBBTC', 71 | quantity=100, 72 | price='0.00001') 73 | 74 | order = client.order_limit_sell( 75 | symbol='BNBBTC', 76 | quantity=100, 77 | price='0.00001') 78 | 79 | 80 | **Place a market order** 81 | 82 | Use the helper functions to easily place a market buy or sell order 83 | 84 | .. code:: python 85 | 86 | order = client.order_market_buy( 87 | symbol='BNBBTC', 88 | quantity=100) 89 | 90 | order = client.order_market_sell( 91 | symbol='BNBBTC', 92 | quantity=100) 93 | 94 | **Place an OCO order** 95 | 96 | Use the `create_oco_order` function to have full control over creating an OCO order 97 | 98 | .. code:: python 99 | 100 | from binance.enums import * 101 | order = client.create_oco_order( 102 | symbol='BNBBTC', 103 | side=SIDE_SELL, 104 | stopLimitTimeInForce=TIME_IN_FORCE_GTC, 105 | quantity=100, 106 | stopPrice='0.00001', 107 | price='0.00002') 108 | 109 | 110 | `Place a test order `_ 111 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 112 | 113 | Creates and validates a new order but does not send it into the exchange. 114 | 115 | .. code:: python 116 | 117 | from binance.enums import * 118 | order = client.create_test_order( 119 | symbol='BNBBTC', 120 | side=SIDE_BUY, 121 | type=ORDER_TYPE_LIMIT, 122 | timeInForce=TIME_IN_FORCE_GTC, 123 | quantity=100, 124 | price='0.00001') 125 | 126 | `Check order status `_ 127 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 128 | 129 | .. code:: python 130 | 131 | order = client.get_order( 132 | symbol='BNBBTC', 133 | orderId='orderId') 134 | 135 | 136 | `Cancel an order `_ 137 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 138 | 139 | .. code:: python 140 | 141 | result = client.cancel_order( 142 | symbol='BNBBTC', 143 | orderId='orderId') 144 | 145 | 146 | `Get all open orders `_ 147 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 148 | 149 | .. code:: python 150 | 151 | orders = client.get_open_orders(symbol='BNBBTC') 152 | 153 | `Get all orders `_ 154 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 155 | 156 | .. code:: python 157 | 158 | orders = client.get_all_orders(symbol='BNBBTC') 159 | 160 | 161 | Account 162 | ------- 163 | 164 | `Get account info `_ 165 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 166 | 167 | .. code:: python 168 | 169 | info = client.get_account() 170 | 171 | `Get asset balance `_ 172 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 173 | 174 | .. code:: python 175 | 176 | balance = client.get_asset_balance(asset='BTC') 177 | 178 | `Get account status `_ 179 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 180 | 181 | .. code:: python 182 | 183 | status = client.get_account_status() 184 | 185 | `Get account API trading status `_ 186 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 187 | 188 | .. code:: python 189 | 190 | status = client.get_account_api_trading_status() 191 | 192 | `Get trades `_ 193 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 194 | 195 | .. code:: python 196 | 197 | trades = client.get_my_trades(symbol='BNBBTC') 198 | 199 | `Get trade fees `_ 200 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 201 | 202 | .. code:: python 203 | 204 | # get fees for all symbols 205 | fees = client.get_trade_fee() 206 | 207 | # get fee for one symbol 208 | fees = client.get_trade_fee(symbol='BNBBTC') 209 | 210 | `Get asset details `_ 211 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 212 | 213 | .. code:: python 214 | 215 | details = client.get_asset_details() 216 | 217 | `Get dust log `_ 218 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 219 | 220 | .. code:: python 221 | 222 | log = client.get_dust_log() 223 | 224 | `Transfer dust `_ 225 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 226 | 227 | .. code:: python 228 | 229 | transfer = client.transfer_dust(asset='BNZ') 230 | 231 | 232 | `Get Asset Dividend History `_ 233 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 234 | 235 | .. code:: python 236 | 237 | history = client.get_asset_dividend_history() 238 | 239 | 240 | `Disable Fast Withdraw Switch `_ 241 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 242 | 243 | .. code:: python 244 | 245 | client.disable_fast_withdraw_switch() 246 | 247 | 248 | `Enable Fast Withdraw Switch `_ 249 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 250 | 251 | .. code:: python 252 | 253 | client.enable_fast_withdraw_switch() 254 | -------------------------------------------------------------------------------- /docs/binance.rst: -------------------------------------------------------------------------------- 1 | Binance API 2 | =========== 3 | 4 | client module 5 | ------------- 6 | 7 | .. automodule:: binance.client 8 | :members: 9 | :undoc-members: 10 | :show-inheritance: 11 | 12 | depthcache module 13 | ----------------- 14 | 15 | .. automodule:: binance.depthcache 16 | :members: 17 | :undoc-members: 18 | :show-inheritance: 19 | 20 | exceptions module 21 | ----------------- 22 | 23 | .. automodule:: binance.exceptions 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | 28 | helpers module 29 | -------------- 30 | 31 | .. automodule:: binance.helpers 32 | :members: 33 | :undoc-members: 34 | :show-inheritance: 35 | 36 | websockets module 37 | ----------------- 38 | 39 | .. automodule:: binance.streams 40 | :members: 41 | :undoc-members: 42 | :show-inheritance: 43 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | v1.0.15 - 2021-09-27 5 | ^^^^^^^^^^^^^^^^^^^^ 6 | 7 | **Added** 8 | 9 | - Enable/disable margin account for symbol endpoints 10 | - Top trader long/short positions endpoint 11 | - Global long/short ratio endpoint 12 | 13 | **Fixed** 14 | 15 | - fix websockets to 9.1 16 | - websocket reconnect updates 17 | - fix futures kline sockets 18 | 19 | 20 | v1.0.14 - 2021-09-08 21 | ^^^^^^^^^^^^^^^^^^^^ 22 | 23 | **Fixed** 24 | 25 | - websocket reconnecting 26 | 27 | v1.0.13 - 2021-09-08 28 | ^^^^^^^^^^^^^^^^^^^^ 29 | 30 | **Added** 31 | 32 | - Futures Depth Cache Manager 33 | - Futures kline websocket stream 34 | - Coin Futures User websocket stream 35 | - New Margin endpoints 36 | - Margin OCO order endpoints 37 | - Fiat endpoints 38 | - C2C endpoints 39 | - Account API permissions endpoint 40 | 41 | **Fixed** 42 | 43 | - changed `asset` to `coin` in withdraw endpoint 44 | 45 | 46 | v1.0.12 - 2021-06-03 47 | ^^^^^^^^^^^^^^^^^^^^ 48 | 49 | **Added** 50 | 51 | - coin futures batch order function 52 | 53 | **Fixed** 54 | 55 | - threaded websockets on python3.9 56 | - filter out None params in request kwargs 57 | - deconflict streams with same name on different websocket urls 58 | - reduce close timeout on websocket close to short time to reduce waiting 59 | 60 | 61 | v1.0.10 - 2021-05-13 62 | ^^^^^^^^^^^^^^^^^^^^ 63 | 64 | **Added** 65 | 66 | - futures multi-asset margin mode endpoints 67 | - optional symbol param to get_all_tickers 68 | 69 | **Fixed** 70 | 71 | - start_multiplex_socket remove lower case filter on stream names 72 | 73 | v1.0.9 - 2021-05-12 74 | ^^^^^^^^^^^^^^^^^^^ 75 | 76 | **Fixed** 77 | 78 | - start_book_ticker_socket and start_multiplex_socket to call correct async function 79 | 80 | v1.0.8 - 2021-05-11 81 | ^^^^^^^^^^^^^^^^^^^ 82 | 83 | **Added** 84 | 85 | - old style websocket and depth cache managers as option without interacting with asyncio 86 | 87 | **Fixed** 88 | 89 | - fixed issue with get_historical_klines in Client 90 | - remove print debug line 91 | 92 | v1.0.7 93 | ^^^^^^ 94 | 95 | **Fixed** 96 | 97 | - remove version param from get_sub_account_assets 98 | 99 | v1.0.6 100 | ^^^^^^ 101 | 102 | **Fixed** 103 | 104 | - fix time for authenticated stream keepalive 105 | 106 | v1.0.5 107 | ^^^^^^ 108 | 109 | **Fixed** 110 | 111 | - Restored access to last response on client 112 | 113 | v1.0.4 114 | ^^^^^^ 115 | 116 | **Added** 117 | 118 | - Futures Testnet support 119 | - Kline type for fetching historical klines 120 | 121 | **Fixed** 122 | 123 | - Spot Testnet websocket URL 124 | 125 | v1.0.3 126 | ^^^^^^ 127 | 128 | **Added** 129 | 130 | - Spot Testnet support 131 | 132 | v1.0.2 133 | ^^^^^^ 134 | 135 | **Added** 136 | 137 | - start of typing to client and websockets 138 | 139 | **Fixed** 140 | 141 | - end_str, limit, spot params in kline fetching 142 | - drop None values in params passed 143 | 144 | **Updated** 145 | 146 | - more examples in docs 147 | 148 | v1.0.1 149 | ^^^^^^ 150 | 151 | **Fixed** 152 | 153 | - restored params for Client and AsyncClient classes 154 | 155 | v1.0.0 156 | ^^^^^^ 157 | 158 | **Added** 159 | 160 | - Async support for all REST endpoints 161 | - USDⓈ-M and Coin-M Futures websocket streams 162 | - Websockets use same tld as Client 163 | - convert type option for DepthCache 164 | 165 | **Breaking Changes** 166 | 167 | - Supports only py3.6+ 168 | - All wapi calls changed to sapi 169 | - Websockets have changed to use Asynchronous context managers 170 | 171 | **Fixed** 172 | 173 | - get_historical_klines params 174 | 175 | v0.7.11 176 | ^^^^^^^ 177 | 178 | **Added** 179 | - Vanilla Options REST endpoints 180 | - Vanilla Options websockets 181 | - Futures order type enums 182 | 183 | **Updated** 184 | 185 | - websocket keep-alive functions for different socket types 186 | - dependencies 187 | 188 | **Fixed** 189 | 190 | - change to User-Agent to avoid connection issues 191 | 192 | v0.7.5.dev 193 | ^^^^^^^^^^ 194 | **Changed** 195 | - Stock json lib to ujson (https://github.com/sammchardy/python-binance/pull/383) 196 | 197 | v0.7.5 - 2020-02-06 198 | ^^^^^^^^^^^^^^^^^^^ 199 | 200 | **Added** 201 | 202 | - Futures REST endpoints 203 | - Lending REST endpoints 204 | - OCO Orders function `create_oco_order`, `order_oco_buy`, `order_oco_sell` 205 | - Average Price function `get_avg_price` 206 | - Support for other domains (.us, .jp, etc) 207 | 208 | **Updated** 209 | 210 | - dependencies 211 | 212 | **Fixed** 213 | 214 | - websocket keepalive callback not found 215 | 216 | v0.7.4 - 2019-09-22 217 | ^^^^^^^^^^^^^^^^^^^ 218 | 219 | **Added** 220 | 221 | - symbol book ticker websocket streams 222 | - margin websocket stream 223 | 224 | **Updated** 225 | 226 | - can call Client without any params 227 | - make response a property of the Client class so you can access response properties after a request 228 | 229 | **Fixed** 230 | 231 | - issue with None value params causing errors 232 | 233 | v0.7.3 - 2019-08-12 234 | ^^^^^^^^^^^^^^^^^^^ 235 | 236 | **Added** 237 | 238 | - sub account endpoints 239 | - dust transfer endpoint 240 | - asset divident history endpoint 241 | 242 | **Removed** 243 | 244 | - deprecated withdraw fee endpoint 245 | 246 | v0.7.2 - 2019-08-01 247 | ^^^^^^^^^^^^^^^^^^^ 248 | 249 | **Added** 250 | 251 | - margin trading endpoints 252 | 253 | **Fixed** 254 | 255 | - depth cache clearing bug 256 | 257 | v0.7.1 - 2019-01-23 258 | ^^^^^^^^^^^^^^^^^^^ 259 | 260 | **Added** 261 | 262 | - limit param to DepthCacheManager 263 | - limit param to get_historical_klines 264 | - update_time to DepthCache class 265 | 266 | **Updated** 267 | 268 | - test coverage 269 | 270 | **Fixed** 271 | 272 | - super init in Websocket class 273 | - removal of request params from signature 274 | - empty set issue in aggregate_trade_iter 275 | 276 | 277 | v0.7.0 - 2018-08-08 278 | ^^^^^^^^^^^^^^^^^^^ 279 | 280 | **Added** 281 | 282 | - get_asset_details endpoint 283 | - get_dust_log endpoint 284 | - get_trade_fee endpoint 285 | - ability for multiple DepthCacheManagers to share a BinanceSocketManager 286 | - get_historial_klines_generator function 287 | - custom socket timeout param for BinanceSocketManager 288 | 289 | **Updated** 290 | 291 | - general dependency version 292 | - removed support for python3.3 293 | 294 | **Fixed** 295 | 296 | - add a super init on BinanceClientProtocol 297 | 298 | v0.6.9 - 2018-04-27 299 | ^^^^^^^^^^^^^^^^^^^ 300 | 301 | **Added** 302 | 303 | - timestamp in milliseconds to `get_historical_klines` function 304 | - timestamp in milliseconds to `aggregate_trade_iter` function 305 | 306 | **Fixed** 307 | 308 | - Don't close user stream listen key on socket close 309 | 310 | v0.6.8 - 2018-03-29 311 | ^^^^^^^^^^^^^^^^^^^ 312 | 313 | **Added** 314 | 315 | - `get_withdraw_fee` function 316 | 317 | **Fixed** 318 | 319 | - Remove unused LISTENKEY_NOT_EXISTS 320 | - Optimise the historical klines function to reduce requests 321 | - Issue with end_time in aggregate trade iterator 322 | 323 | v0.6.7 - 2018-03-14 324 | ^^^^^^^^^^^^^^^^^^^ 325 | 326 | **Fixed** 327 | 328 | - Issue with `get_historical_klines` when response had exactly 500 results 329 | - Changed BinanceResponseException to BinanceRequestException 330 | - Set default code value in BinanceApiException properly 331 | 332 | v0.6.6 - 2018-02-17 333 | ^^^^^^^^^^^^^^^^^^^ 334 | 335 | **Fixed** 336 | 337 | - User stream websocket keep alive strategy updated 338 | 339 | v0.6.5 - 2018-02-13 340 | ^^^^^^^^^^^^^^^^^^^ 341 | 342 | **Fixed** 343 | 344 | - `get_historical_klines` response for month interval 345 | 346 | v0.6.4 - 2018-02-09 347 | ^^^^^^^^^^^^^^^^^^^ 348 | 349 | **Added** 350 | 351 | - system status endpoint `get_system_status` 352 | 353 | v0.6.3 - 2018-01-29 354 | ^^^^^^^^^^^^^^^^^^^ 355 | 356 | **Added** 357 | 358 | - mini ticker socket function `start_miniticker_socket` 359 | - aggregate trade iterator `aggregate_trade_iter` 360 | 361 | **Fixes** 362 | 363 | - clean up `interval_to_milliseconds` logic 364 | - general doc and file cleanups 365 | 366 | v0.6.2 - 2018-01-12 367 | ^^^^^^^^^^^^^^^^^^^ 368 | 369 | **Fixes** 370 | 371 | - fixed handling Binance errors that aren't JSON objects 372 | 373 | v0.6.1 - 2018-01-10 374 | ^^^^^^^^^^^^^^^^^^^ 375 | 376 | **Fixes** 377 | 378 | - added missing dateparser dependency to setup.py 379 | - documentation fixes 380 | 381 | v0.6.0 - 2018-01-09 382 | ^^^^^^^^^^^^^^^^^^^ 383 | 384 | New version because why not. 385 | 386 | **Added** 387 | 388 | - get_historical_klines function to fetch klines for any date range 389 | - ability to override requests parameters globally 390 | - error on websocket disconnect 391 | - example related to blog post 392 | 393 | **Fixes** 394 | 395 | - documentation fixes 396 | 397 | v0.5.17 - 2018-01-08 398 | ^^^^^^^^^^^^^^^^^^^^ 399 | 400 | **Added** 401 | 402 | - check for name parameter in withdraw, set to asset parameter if not passed 403 | 404 | **Update** 405 | 406 | - Windows install error documentation 407 | 408 | **Removed** 409 | 410 | - reference to disable_validation in documentation 411 | 412 | v0.5.16 - 2018-01-06 413 | ^^^^^^^^^^^^^^^^^^^^ 414 | 415 | **Added** 416 | 417 | - addressTag documentation to withdraw function 418 | - documentation about requests proxy environment variables 419 | 420 | **Update** 421 | 422 | - FAQ for signature error with solution to regenerate API key 423 | - change create_order to create_test_order in example 424 | 425 | **Fixed** 426 | 427 | - reference to BinanceAPIException in documentation 428 | 429 | v0.5.15 - 2018-01-03 430 | ^^^^^^^^^^^^^^^^^^^^ 431 | 432 | **Fixed** 433 | 434 | - removed all references to WEBSOCKET_DEPTH_1 enum 435 | 436 | v0.5.14 - 2018-01-02 437 | ^^^^^^^^^^^^^^^^^^^^ 438 | 439 | **Added** 440 | 441 | - Wait for depth cache socket to start 442 | - check for sequential depth cache messages 443 | 444 | **Updated** 445 | 446 | - documentation around depth websocket and diff and partial responses 447 | 448 | **Removed** 449 | 450 | - Removed unused WEBSOCKET_DEPTH_1 enum 451 | - removed unused libraries and imports 452 | 453 | v0.5.13 - 2018-01-01 454 | ^^^^^^^^^^^^^^^^^^^^ 455 | 456 | **Fixed** 457 | 458 | - Signature invalid error 459 | 460 | v0.5.12 - 2017-12-29 461 | ^^^^^^^^^^^^^^^^^^^^ 462 | 463 | **Added** 464 | 465 | - get_asset_balance helper function to fetch an individual asset's balance 466 | 467 | **Fixed** 468 | 469 | - added timeout to requests call to prevent hanging 470 | - changed variable type to str for price parameter when creating an order 471 | - documentation fixes 472 | 473 | v0.5.11 - 2017-12-28 474 | ^^^^^^^^^^^^^^^^^^^^ 475 | 476 | **Added** 477 | 478 | - refresh interval parameter to depth cache to keep it fresh, set default at 30 minutes 479 | 480 | **Fixed** 481 | 482 | - watch depth cache socket before fetching order book to replay any messages 483 | 484 | v0.5.10 - 2017-12-28 485 | ^^^^^^^^^^^^^^^^^^^^ 486 | 487 | **Updated** 488 | 489 | - updated dependencies certifi and cryptography to help resolve signature error 490 | 491 | v0.5.9 - 2017-12-26 492 | ^^^^^^^^^^^^^^^^^^^ 493 | 494 | **Fixed** 495 | 496 | - fixed websocket reconnecting, was no distinction between manual close or network error 497 | 498 | v0.5.8 - 2017-12-25 499 | ^^^^^^^^^^^^^^^^^^^ 500 | 501 | **Changed** 502 | 503 | - change symbol parameter to optional for get_open_orders function 504 | - added listenKey parameter to stream_close function 505 | 506 | **Added** 507 | 508 | - get_account_status function that was missed 509 | 510 | v0.5.7 - 2017-12-24 511 | ^^^^^^^^^^^^^^^^^^^ 512 | 513 | **Changed** 514 | 515 | - change depth cache callback parameter to optional 516 | 517 | **Added** 518 | 519 | - note about stopping Twisted reactor loop to exit program 520 | 521 | v0.5.6 - 2017-12-20 522 | ^^^^^^^^^^^^^^^^^^^ 523 | 524 | **Added** 525 | 526 | - get_symbol_info function to simplify getting info about a particular symbol 527 | 528 | v0.5.5 - 2017-12-19 529 | ^^^^^^^^^^^^^^^^^^^ 530 | 531 | **Changed** 532 | 533 | - Increased default limit for order book on depth cache from 10 to 500 534 | 535 | v0.5.4 - 2017-12-14 536 | ^^^^^^^^^^^^^^^^^^^ 537 | 538 | **Added** 539 | 540 | - symbol property made public on DepthCache class 541 | 542 | **Changed** 543 | 544 | - Enums now also accessible from binance.client.Client and binance.websockets.BinanceSocketManager 545 | 546 | v0.5.3 - 2017-12-09 547 | ^^^^^^^^^^^^^^^^^^^ 548 | 549 | **Changed** 550 | 551 | - User stream refresh timeout from 50 minutes to 30 minutes 552 | - User stream socket listen key change check simplified 553 | 554 | v0.5.2 - 2017-12-08 555 | ^^^^^^^^^^^^^^^^^^^ 556 | 557 | **Added** 558 | 559 | - start_multiplex_socket function to BinanceSocketManager to create multiplexed streams 560 | 561 | v0.5.1 - 2017-12-06 562 | ^^^^^^^^^^^^^^^^^^^ 563 | 564 | **Added** 565 | 566 | - Close method for DepthCacheManager 567 | 568 | **Fixes** 569 | 570 | - Fixed modifying array error message when closing the BinanceSocketManager 571 | 572 | v0.5.0 - 2017-12-05 573 | ^^^^^^^^^^^^^^^^^^^ 574 | 575 | Updating to match new API documentation 576 | 577 | **Added** 578 | 579 | - Recent trades endpoint 580 | - Historical trades endpoint 581 | - Order response type option 582 | - Check for invalid user stream listen key in socket to keep connected 583 | 584 | **Fixes** 585 | 586 | - Fixed exchange info endpoint as it was renamed slightly 587 | 588 | v0.4.3 - 2017-12-04 589 | ^^^^^^^^^^^^^^^^^^^ 590 | 591 | **Fixes** 592 | 593 | - Fixed stopping sockets where they were reconnecting 594 | - Fixed websockets unable to be restarted after close 595 | - Exception in parsing non-JSON websocket message 596 | 597 | v0.4.2 - 2017-11-30 598 | ^^^^^^^^^^^^^^^^^^^ 599 | 600 | **Removed** 601 | 602 | - Removed websocket update time as 0ms option is not available 603 | 604 | v0.4.1 - 2017-11-24 605 | ^^^^^^^^^^^^^^^^^^^ 606 | 607 | **Added** 608 | 609 | - Reconnecting websockets, automatic retry on disconnect 610 | 611 | v0.4.0 - 2017-11-19 612 | ^^^^^^^^^^^^^^^^^^^ 613 | 614 | **Added** 615 | 616 | - Get deposit address endpoint 617 | - Upgraded withdraw endpoints to v3 618 | - New exchange info endpoint with rate limits and full symbol info 619 | 620 | **Removed** 621 | 622 | - Order validation to return at a later date 623 | 624 | v0.3.8 - 2017-11-17 625 | ^^^^^^^^^^^^^^^^^^^ 626 | 627 | **Fixes** 628 | 629 | - Fix order validation for market orders 630 | - WEBSOCKET_DEPTH_20 value, 20 instead of 5 631 | - General tidy up 632 | 633 | v0.3.7 - 2017-11-16 634 | ^^^^^^^^^^^^^^^^^^^ 635 | 636 | **Fixes** 637 | 638 | - Fix multiple depth caches sharing a cache by initialising bid and ask objects each time 639 | 640 | v0.3.6 - 2017-11-15 641 | ^^^^^^^^^^^^^^^^^^^ 642 | 643 | **Fixes** 644 | 645 | - check if Reactor is already running 646 | 647 | v0.3.5 - 2017-11-06 648 | ^^^^^^^^^^^^^^^^^^^ 649 | 650 | **Added** 651 | 652 | - support for BNB market 653 | 654 | **Fixes** 655 | 656 | - fixed error if new market type is created that we don't know about 657 | 658 | v0.3.4 - 2017-10-31 659 | ^^^^^^^^^^^^^^^^^^^ 660 | 661 | **Added** 662 | 663 | - depth parameter to depth socket 664 | - interval parameter to kline socket 665 | - update time parameter for compatible sockets 666 | - new enums for socket depth and update time values 667 | - better websocket documentation 668 | 669 | **Changed** 670 | 671 | - Depth Cache Manager uses 0ms socket update time 672 | - connection key returned when creating socket, this key is then used to stop it 673 | 674 | **Fixes** 675 | 676 | - General fixes 677 | 678 | v0.3.3 - 2017-10-31 679 | ^^^^^^^^^^^^^^^^^^^ 680 | 681 | **Fixes** 682 | 683 | - Fixes for broken tests 684 | 685 | v0.3.2 - 2017-10-30 686 | ^^^^^^^^^^^^^^^^^^^ 687 | 688 | **Added** 689 | 690 | - More test coverage of requests 691 | 692 | **Fixes** 693 | 694 | - Order quantity validation fix 695 | 696 | v0.3.1 - 2017-10-29 697 | ^^^^^^^^^^^^^^^^^^^ 698 | 699 | **Added** 700 | 701 | - Withdraw exception handler with translation of obscure error 702 | 703 | **Fixes** 704 | 705 | - Validation fixes 706 | 707 | v0.3.0 - 2017-10-29 708 | ^^^^^^^^^^^^^^^^^^^ 709 | 710 | **Added** 711 | 712 | - Withdraw endpoints 713 | - Order helper functions 714 | 715 | v0.2.0 - 2017-10-27 716 | ^^^^^^^^^^^^^^^^^^^ 717 | 718 | **Added** 719 | 720 | - Symbol Depth Cache 721 | 722 | v0.1.6 - 2017-10-25 723 | ^^^^^^^^^^^^^^^^^^^ 724 | 725 | **Changes** 726 | 727 | - Upgrade to v3 signed endpoints 728 | - Update function documentation 729 | 730 | 731 | v0.1.5 - 2017-09-12 732 | ^^^^^^^^^^^^^^^^^^^ 733 | 734 | **Changes** 735 | 736 | - Added get_all_tickers call 737 | - Added get_orderbook_tickers call 738 | - Added some FAQs 739 | 740 | **Fixes** 741 | 742 | - Fix error in enum value 743 | 744 | v0.1.4 - 2017-09-06 745 | ^^^^^^^^^^^^^^^^^^^ 746 | 747 | **Changes** 748 | 749 | - Added parameter to disable client side order validation 750 | 751 | v0.1.3 - 2017-08-26 752 | ^^^^^^^^^^^^^^^^^^^ 753 | 754 | **Changes** 755 | 756 | - Updated documentation 757 | 758 | **Fixes** 759 | 760 | - Small bugfix 761 | 762 | v0.1.2 - 2017-08-25 763 | ^^^^^^^^^^^^^^^^^^^ 764 | 765 | **Added** 766 | 767 | - Travis.CI and Coveralls support 768 | 769 | **Changes** 770 | 771 | - Validation for pairs using public endpoint 772 | 773 | v0.1.1 - 2017-08-17 774 | ^^^^^^^^^^^^^^^^^^^ 775 | 776 | **Added** 777 | 778 | - Validation for HSR/BTC pair 779 | 780 | v0.1.0 - 2017-08-16 781 | ^^^^^^^^^^^^^^^^^^^ 782 | 783 | Websocket release 784 | 785 | **Added** 786 | 787 | - Websocket manager 788 | - Order parameter validation 789 | - Order and Symbol enums 790 | - API Endpoints for Data Streams 791 | 792 | v0.0.2 - 2017-08-14 793 | ^^^^^^^^^^^^^^^^^^^ 794 | 795 | Initial version 796 | 797 | **Added** 798 | 799 | - General, Market Data and Account endpoints 800 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # python-binance documentation build configuration file, created by 5 | # sphinx-quickstart on Thu Sep 21 20:24:54 2017. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | # 20 | import os 21 | import sys 22 | sys.path.insert(0, os.path.abspath('..')) 23 | 24 | 25 | # -- General configuration ------------------------------------------------ 26 | 27 | # If your documentation needs a minimal Sphinx version, state it here. 28 | # 29 | # needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = ['sphinx.ext.autodoc', 35 | 'sphinx.ext.imgmath', 36 | 'sphinx.ext.viewcode', 37 | 'sphinx.ext.githubpages'] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ['_templates'] 41 | 42 | # The suffix(es) of source filenames. 43 | # You can specify multiple suffix as a list of string: 44 | # 45 | # source_suffix = ['.rst', '.md'] 46 | source_suffix = '.rst' 47 | 48 | # The master toctree document. 49 | master_doc = 'index' 50 | 51 | # General information about the project. 52 | project = 'python-binance' 53 | copyright = '2017, Sam McHardy' 54 | author = 'Sam McHardy' 55 | 56 | # The version info for the project you're documenting, acts as replacement for 57 | # |version| and |release|, also used in various other places throughout the 58 | # built documents. 59 | # 60 | # The short X.Y version. 61 | version = '0.2.0' 62 | # The full version, including alpha/beta/rc tags. 63 | release = '0.2.0' 64 | 65 | # The language for content autogenerated by Sphinx. Refer to documentation 66 | # for a list of supported languages. 67 | # 68 | # This is also used if you do content translation via gettext catalogs. 69 | # Usually you set "language" from the command line for these cases. 70 | language = None 71 | 72 | # List of patterns, relative to source directory, that match files and 73 | # directories to ignore when looking for source files. 74 | # This patterns also effect to html_static_path and html_extra_path 75 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 76 | 77 | # The name of the Pygments (syntax highlighting) style to use. 78 | pygments_style = 'sphinx' 79 | 80 | # If true, `todo` and `todoList` produce output, else they produce nothing. 81 | todo_include_todos = False 82 | 83 | 84 | # -- Options for HTML output ---------------------------------------------- 85 | 86 | # The theme to use for HTML and HTML Help pages. See the documentation for 87 | # a list of builtin themes. 88 | # 89 | #html_theme = 'alabaster' 90 | html_theme = 'sphinx_rtd_theme' 91 | 92 | # Theme options are theme-specific and customize the look and feel of a theme 93 | # further. For a list of options available for each theme, see the 94 | # documentation. 95 | # 96 | # html_theme_options = {} 97 | 98 | # Add any paths that contain custom static files (such as style sheets) here, 99 | # relative to this directory. They are copied after the builtin static files, 100 | # so a file named "default.css" will overwrite the builtin "default.css". 101 | html_static_path = ['_static'] 102 | 103 | # Custom sidebar templates, must be a dictionary that maps document names 104 | # to template names. 105 | # 106 | # This is required for the alabaster theme 107 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 108 | html_sidebars = { 109 | '**': [ 110 | 'about.html', 111 | 'navigation.html', 112 | 'relations.html', # needs 'show_related': True theme option to display 113 | 'searchbox.html', 114 | 'donate.html', 115 | ] 116 | } 117 | 118 | 119 | # -- Options for HTMLHelp output ------------------------------------------ 120 | 121 | # Output file base name for HTML help builder. 122 | htmlhelp_basename = 'python-binancedoc' 123 | 124 | 125 | # -- Options for LaTeX output --------------------------------------------- 126 | 127 | latex_elements = { 128 | # The paper size ('letterpaper' or 'a4paper'). 129 | # 130 | # 'papersize': 'letterpaper', 131 | 132 | # The font size ('10pt', '11pt' or '12pt'). 133 | # 134 | # 'pointsize': '10pt', 135 | 136 | # Additional stuff for the LaTeX preamble. 137 | # 138 | # 'preamble': '', 139 | 140 | # Latex figure (float) alignment 141 | # 142 | # 'figure_align': 'htbp', 143 | } 144 | 145 | # Grouping the document tree into LaTeX files. List of tuples 146 | # (source start file, target name, title, 147 | # author, documentclass [howto, manual, or own class]). 148 | latex_documents = [ 149 | (master_doc, 'python-binance.tex', 'python-binance Documentation', 150 | 'Sam McHardy', 'manual'), 151 | ] 152 | 153 | 154 | # -- Options for manual page output --------------------------------------- 155 | 156 | # One entry per manual page. List of tuples 157 | # (source start file, name, description, authors, manual section). 158 | man_pages = [ 159 | (master_doc, 'python-binance', 'python-binance Documentation', 160 | [author], 1) 161 | ] 162 | 163 | 164 | # -- Options for Texinfo output ------------------------------------------- 165 | 166 | # Grouping the document tree into Texinfo files. List of tuples 167 | # (source start file, target name, title, author, 168 | # dir menu entry, description, category) 169 | texinfo_documents = [ 170 | (master_doc, 'python-binance', 'python-binance Documentation', 171 | author, 'python-binance', 'One line description of project.', 172 | 'Miscellaneous'), 173 | ] 174 | 175 | 176 | def skip(app, what, name, obj, skip, options): 177 | # Ensure that the __init__ method gets documented. 178 | if name == "__init__": 179 | return False 180 | return skip 181 | 182 | 183 | def setup(app): 184 | app.connect("autodoc-skip-member", skip) 185 | 186 | -------------------------------------------------------------------------------- /docs/constants.rst: -------------------------------------------------------------------------------- 1 | Binance Constants 2 | ================= 3 | 4 | Binance requires specific string constants for Order Types, Order Side, Time in Force, Order response and Kline intervals these are found on `binance.client.Client`. 5 | 6 | .. code:: python 7 | 8 | SYMBOL_TYPE_SPOT = 'SPOT' 9 | 10 | ORDER_STATUS_NEW = 'NEW' 11 | ORDER_STATUS_PARTIALLY_FILLED = 'PARTIALLY_FILLED' 12 | ORDER_STATUS_FILLED = 'FILLED' 13 | ORDER_STATUS_CANCELED = 'CANCELED' 14 | ORDER_STATUS_PENDING_CANCEL = 'PENDING_CANCEL' 15 | ORDER_STATUS_REJECTED = 'REJECTED' 16 | ORDER_STATUS_EXPIRED = 'EXPIRED' 17 | 18 | KLINE_INTERVAL_1MINUTE = '1m' 19 | KLINE_INTERVAL_3MINUTE = '3m' 20 | KLINE_INTERVAL_5MINUTE = '5m' 21 | KLINE_INTERVAL_15MINUTE = '15m' 22 | KLINE_INTERVAL_30MINUTE = '30m' 23 | KLINE_INTERVAL_1HOUR = '1h' 24 | KLINE_INTERVAL_2HOUR = '2h' 25 | KLINE_INTERVAL_4HOUR = '4h' 26 | KLINE_INTERVAL_6HOUR = '6h' 27 | KLINE_INTERVAL_8HOUR = '8h' 28 | KLINE_INTERVAL_12HOUR = '12h' 29 | KLINE_INTERVAL_1DAY = '1d' 30 | KLINE_INTERVAL_3DAY = '3d' 31 | KLINE_INTERVAL_1WEEK = '1w' 32 | KLINE_INTERVAL_1MONTH = '1M' 33 | 34 | SIDE_BUY = 'BUY' 35 | SIDE_SELL = 'SELL' 36 | 37 | ORDER_TYPE_LIMIT = 'LIMIT' 38 | ORDER_TYPE_MARKET = 'MARKET' 39 | ORDER_TYPE_STOP_LOSS = 'STOP_LOSS' 40 | ORDER_TYPE_STOP_LOSS_LIMIT = 'STOP_LOSS_LIMIT' 41 | ORDER_TYPE_TAKE_PROFIT = 'TAKE_PROFIT' 42 | ORDER_TYPE_TAKE_PROFIT_LIMIT = 'TAKE_PROFIT_LIMIT' 43 | ORDER_TYPE_LIMIT_MAKER = 'LIMIT_MAKER' 44 | 45 | TIME_IN_FORCE_GTC = 'GTC' 46 | TIME_IN_FORCE_IOC = 'IOC' 47 | TIME_IN_FORCE_FOK = 'FOK' 48 | 49 | ORDER_RESP_TYPE_ACK = 'ACK' 50 | ORDER_RESP_TYPE_RESULT = 'RESULT' 51 | ORDER_RESP_TYPE_FULL = 'FULL' 52 | 53 | # For accessing the data returned by Client.aggregate_trades(). 54 | AGG_ID = 'a' 55 | AGG_PRICE = 'p' 56 | AGG_QUANTITY = 'q' 57 | AGG_FIRST_TRADE_ID = 'f' 58 | AGG_LAST_TRADE_ID = 'l' 59 | AGG_TIME = 'T' 60 | AGG_BUYER_MAKES = 'm' 61 | AGG_BEST_MATCH = 'M' 62 | 63 | 64 | For Websocket Depth these are found on `binance.websockets.BinanceSocketManager` 65 | 66 | .. code:: python 67 | 68 | WEBSOCKET_DEPTH_5 = '5' 69 | WEBSOCKET_DEPTH_10 = '10' 70 | WEBSOCKET_DEPTH_20 = '20' 71 | 72 | To use in your code reference either binance.client.Client or binance.websockets.BinanceSocketManager 73 | 74 | .. code:: python 75 | 76 | from binance.client import Client 77 | from binance.websockets import BinanceSocketManager 78 | 79 | side = Client.SIDE_BUY 80 | -------------------------------------------------------------------------------- /docs/depth_cache.rst: -------------------------------------------------------------------------------- 1 | Depth Cache 2 | =========== 3 | 4 | To follow the depth cache updates for a symbol there are 2 options similar to websockets. 5 | 6 | Use the `DepthCacheManager `_ 7 | (or `OptionsDepthCacheManager `_ for vanilla options) or 8 | use the `ThreadedDepthCacheManager `_ 9 | if you don't want to interact with asyncio. 10 | 11 | ThreadedDepthCacheManager Websocket Usage 12 | ----------------------------------------- 13 | 14 | Starting sockets on the ThreadedDepthCacheManager requires a callback parameter, similar to old implementations of 15 | depth cache on python-binance pre v1 16 | 17 | ThreadedDepthCacheManager takes similar parameters to the `Client `_ class 18 | as it creates an AsyncClient internally. 19 | 20 | As these use threads `start()` is required to be called before starting any depth cache streams. 21 | 22 | To keep the ThreadedDepthCacheManager running using `join()` to join it to the main thread. 23 | 24 | .. code:: python 25 | 26 | from binance import ThreadedDepthCacheManager 27 | 28 | def main(): 29 | 30 | dcm = ThreadedDepthCacheManager() 31 | # start is required to initialise its internal loop 32 | dcm.start() 33 | 34 | def handle_depth_cache(depth_cache): 35 | print(f"symbol {depth_cache.symbol}") 36 | print("top 5 bids") 37 | print(depth_cache.get_bids()[:5]) 38 | print("top 5 asks") 39 | print(depth_cache.get_asks()[:5]) 40 | print("last update time {}".format(depth_cache.update_time)) 41 | 42 | dcm_name = dcm.start_depth_cache(handle_depth_cache, symbol='BNBBTC') 43 | 44 | # multiple depth caches can be started 45 | dcm_name = dcm.start_depth_cache(handle_depth_cache, symbol='ETHBTC') 46 | 47 | dcm.join() 48 | 49 | 50 | if __name__ == "__main__": 51 | main() 52 | 53 | 54 | **Stop Individual Depth Cache** 55 | 56 | When starting a stream, a name for that stream will be returned. This can be used to stop that individual stream 57 | 58 | .. code:: python 59 | 60 | from binance import ThreadedDepthCacheManager 61 | 62 | symbol = 'BNBBTC' 63 | 64 | dcm = ThreadedDepthCacheManager() 65 | dcm.start() 66 | 67 | def handle_depth_cache(depth_cache): 68 | print(f"message type: {msg['e']}") 69 | print(msg) 70 | 71 | dcm_name = dcm.start_depth_cache(handle_depth_cache, symbol='BNBBTC') 72 | 73 | # some time later 74 | 75 | dcm.stop_socket(dcm_name) 76 | 77 | **Stop All Depth Cache streams** 78 | 79 | .. code:: python 80 | 81 | from binance import ThreadedDepthCacheManager 82 | 83 | symbol = 'BNBBTC' 84 | 85 | dcm = ThreadedDepthCacheManager() 86 | dcm.start() 87 | 88 | def handle_depth_cache(depth_cache): 89 | print(f"message type: {msg['e']}") 90 | print(msg) 91 | 92 | dcm_name = dcm.start_depth_cache(handle_depth_cache, symbol='BNBBTC') 93 | 94 | # some time later 95 | 96 | dcm.stop() 97 | 98 | Attempting to start a stream after `stop` is called will not work. 99 | 100 | 101 | DepthCacheManager or OptionsDepthCacheManager Usage 102 | --------------------------------------------------- 103 | 104 | Create the manager like so, passing the async api client, symbol and an optional callback function. 105 | 106 | .. code:: python 107 | 108 | import asyncio 109 | 110 | from binance import AsyncClient, DepthCacheManager 111 | 112 | 113 | async def main(): 114 | client = await AsyncClient.create() 115 | dcm = DepthCacheManager(client, 'BNBBTC') 116 | 117 | async with dcm as dcm_socket: 118 | while True: 119 | depth_cache = await dcm_socket.recv() 120 | print("symbol {}".format(depth_cache.symbol)) 121 | print("top 5 bids") 122 | print(depth_cache.get_bids()[:5]) 123 | print("top 5 asks") 124 | print(depth_cache.get_asks()[:5]) 125 | print("last update time {}".format(depth_cache.update_time)) 126 | 127 | if __name__ == "__main__": 128 | 129 | loop = asyncio.get_event_loop() 130 | loop.run_until_complete(main()) 131 | 132 | The `DepthCacheManager` returns an Asynchronous Context Manager which can be used with `async for` 133 | or by interacting with the `__aenter__` and `__aexit__` functions 134 | 135 | By default the depth cache will fetch the order book via REST request every 30 minutes. 136 | This duration can be changed by using the `refresh_interval` parameter. To disable the refresh pass 0 or None. 137 | The socket connection will stay open receiving updates to be replayed once the full order book is received. 138 | 139 | Share a Socket Manager 140 | ---------------------- 141 | 142 | Here dcm1 and dcm2 share the same instance of BinanceSocketManager 143 | 144 | .. code:: python 145 | 146 | from binance.websockets import BinanceSocketManager 147 | from binance.depthcache import DepthCacheManager 148 | bm = BinanceSocketManager(client) 149 | dcm1 = DepthCacheManager(client, 'BNBBTC', bm=bm) 150 | dcm2 = DepthCacheManager(client, 'ETHBTC', bm=bm) 151 | 152 | Websocket Errors 153 | ---------------- 154 | 155 | If the underlying websocket is disconnected and is unable to reconnect None is returned for the depth_cache parameter. 156 | 157 | Examples 158 | -------- 159 | 160 | .. code:: python 161 | 162 | # 1 hour interval refresh 163 | dcm = DepthCacheManager(client, 'BNBBTC', refresh_interval=60*60) 164 | 165 | # disable refreshing 166 | dcm = DepthCacheManager(client, 'BNBBTC', refresh_interval=0) 167 | 168 | .. code:: python 169 | 170 | async with dcm as dcm_socket: 171 | while True: 172 | depth_cache = await dcm_socket.recv() 173 | print("symbol {}".format(depth_cache.symbol)) 174 | print("top 5 bids") 175 | print(depth_cache.get_bids()[:5]) 176 | print("top 5 asks") 177 | print(depth_cache.get_asks()[:5]) 178 | print("last update time {}".format(depth_cache.update_time)) 179 | 180 | To use the magic `__aenter__` and `__aexit__` functions to use this class without the `async with` 181 | 182 | .. code:: python 183 | 184 | dcm = DepthCacheManager(client, 'BNBBTC') 185 | 186 | await dcm.__aenter__() 187 | depth_cache = await dcm.recv() 188 | print("symbol {}".format(depth_cache.symbol)) 189 | print("top 5 bids") 190 | print(depth_cache.get_bids()[:5]) 191 | print("top 5 asks") 192 | print(depth_cache.get_asks()[:5]) 193 | print("last update time {}".format(depth_cache.update_time)) 194 | 195 | # exit the context manager 196 | await dcm.__aexit__(None, None, None) 197 | -------------------------------------------------------------------------------- /docs/exceptions.rst: -------------------------------------------------------------------------------- 1 | Exceptions 2 | ========== 3 | 4 | BinanceRequestException 5 | ------------------------ 6 | 7 | Raised if a non JSON response is returned 8 | 9 | BinanceAPIException 10 | ------------------- 11 | 12 | On an API call error a binance.exceptions.BinanceAPIException will be raised. 13 | 14 | The exception provides access to the 15 | 16 | - `status_code` - response status code 17 | - `response` - response object 18 | - `code` - Binance error code 19 | - `message` - Binance error message 20 | - `request` - request object if available 21 | 22 | .. code:: python 23 | 24 | try: 25 | client.get_all_orders() 26 | except BinanceAPIException as e: 27 | print e.status_code 28 | print e.message 29 | -------------------------------------------------------------------------------- /docs/faqs.rst: -------------------------------------------------------------------------------- 1 | FAQ 2 | ======= 3 | 4 | *Q: Why do I get "Timestamp for this request is not valid"* 5 | 6 | *A*: This occurs in 2 different cases. 7 | 8 | The timestamp sent is outside of the serverTime - recvWindow value 9 | The timestamp sent is more than 1000ms ahead of the server time 10 | 11 | Check that your system time is in sync. See `this issue `_ for some sample code to check the difference between your local 12 | time and the Binance server time. 13 | 14 | *Q: Why do I get "Signature for this request is not valid"* 15 | 16 | *A1*: One of your parameters may not be in the correct format. 17 | 18 | Check recvWindow is an integer and not a string. 19 | 20 | *A2*: You may need to regenerate your API Key and Secret 21 | 22 | *A3*: You may be attempting to access the API from a Chinese IP address, these are now restricted by Binance. 23 | -------------------------------------------------------------------------------- /docs/general.rst: -------------------------------------------------------------------------------- 1 | General Endpoints 2 | ================= 3 | 4 | `Ping the server `_ 5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | .. code:: python 8 | 9 | client.ping() 10 | 11 | `Get the server time `_ 12 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 13 | 14 | .. code:: python 15 | 16 | time_res = client.get_server_time() 17 | 18 | `Get system status `_ 19 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 20 | 21 | .. code:: python 22 | 23 | status = client.get_system_status() 24 | 25 | Returns 26 | 27 | .. code-block:: python 28 | 29 | { 30 | "status": 0, # 0: normal,1:system maintenance 31 | "msg": "normal" # normal or System maintenance. 32 | } 33 | 34 | `Get Exchange Info `_ 35 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 36 | 37 | .. code:: python 38 | 39 | info = client.get_exchange_info() 40 | 41 | `Get Symbol Info `_ 42 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 43 | 44 | Get the exchange info for a particular symbol 45 | 46 | .. code:: python 47 | 48 | info = client.get_symbol_info('BNBBTC') 49 | 50 | `Get All Coins Info `_ 51 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 52 | 53 | Get information of coins (available for deposit and withdraw) for user 54 | 55 | .. code:: python 56 | 57 | info = client.get_all_tickers() 58 | 59 | `Get Get Daily Account Snapshot `_ 60 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 61 | 62 | Get daily account snapshot of specific type. Valid types: SPOT/MARGIN/FUTURES. 63 | 64 | .. code:: python 65 | 66 | info = client.get_account_snapshot(type='SPOT') 67 | 68 | `Get Current Products `_ 69 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 70 | 71 | This call is deprecated, use the above Exchange Info call 72 | 73 | .. code:: python 74 | 75 | products = client.get_products() 76 | -------------------------------------------------------------------------------- /docs/helpers.rst: -------------------------------------------------------------------------------- 1 | Helper Functions 2 | ================ 3 | 4 | .. autoclass:: binance.helpers 5 | :members: date_to_milliseconds, interval_to_milliseconds, round_step_size 6 | :noindex: 7 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. python-binance documentation master file, created by 2 | sphinx-quickstart on Thu Sep 21 20:24:54 2017. 3 | 4 | .. include:: ../README.rst 5 | 6 | Contents 7 | ======== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | overview 13 | constants 14 | general 15 | market_data 16 | account 17 | sub_accounts 18 | margin 19 | websockets 20 | depth_cache 21 | withdraw 22 | helpers 23 | exceptions 24 | faqs 25 | changelog 26 | 27 | binance 28 | 29 | Index 30 | ================== 31 | 32 | * :ref:`genindex` 33 | -------------------------------------------------------------------------------- /docs/margin.rst: -------------------------------------------------------------------------------- 1 | Margin Trading Endpoints 2 | ======================== 3 | 4 | .. note :: 5 | 6 | **Cross-margin vs isolated margin trading** 7 | 8 | Binance offers both *cross-margin* trading (where all margin is in one account) and *isolated margin* trading (where each pair is a separate margin account). Make sure you are interacting with the right one. 9 | 10 | Some of the API endpoints apply to the cross-margin or isolated margin accounts only. Other endpoints, such as the trade execution endpoints, are used for the cross-margin account trades by default, but you can use your isolated margin accounts by using the ``isIsolated`` or ``isolatedSymbol`` parameters. See the documentation below. 11 | 12 | Market Data 13 | ----------- 14 | 15 | `Get cross-margin asset info `_ 16 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 17 | 18 | .. code:: python 19 | 20 | info = client.get_margin_asset(asset='BNB') 21 | 22 | `Get cross-margin symbol info `_ 23 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 24 | 25 | .. code:: python 26 | 27 | info = client.get_margin_symbol(symbol='BTCUSDT') 28 | 29 | `Get isolated margin symbol info `_ 30 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 31 | 32 | .. code:: python 33 | 34 | info = client.get_isolated_margin_symbol(symbol='BTCUSDT') 35 | 36 | `Get all isolated margin symbols `_ 37 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 38 | 39 | .. code:: python 40 | 41 | info = client.get_all_isolated_margin_symbols() 42 | 43 | `Get margin price index `_ 44 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 45 | 46 | .. code:: python 47 | 48 | info = client.get_margin_price_index(symbol='BTCUSDT') 49 | 50 | Orders 51 | ------ 52 | 53 | Cross-margin vs isolated margin orders 54 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 55 | 56 | By default, these trade execution endpoints will create an order using the *cross-margin* account. 57 | 58 | To use the *isolated margin* account for the ``symbol`` you have specified, simply add the ``isIsolated='TRUE'`` parameter to the API calls below in this 'Orders' section. 59 | 60 | Order Validation 61 | ^^^^^^^^^^^^^^^^ 62 | 63 | Binance has a number of rules around symbol pair orders with validation on minimum price, quantity and total order value. 64 | 65 | Read more about their specifics in the `Filters `_ 66 | section of the official API. 67 | 68 | It can be helpful to format the output using the following snippet 69 | 70 | .. code:: python 71 | 72 | amount = 0.000234234 73 | precision = 5 74 | amt_str = "{:0.0{}f}".format(amount, precision) 75 | 76 | 77 | `Fetch all margin_orders `_ 78 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 79 | 80 | .. code:: python 81 | 82 | orders = client.get_all_margin_orders(symbol='BNBBTC', limit=10) 83 | 84 | 85 | `Place a margin order `_ 86 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 87 | 88 | Use the `create_margin_order` function to have full control over creating an order 89 | 90 | .. code:: python 91 | 92 | from binance.enums import * 93 | order = client.create_margin_order( 94 | symbol='BNBBTC', 95 | side=SIDE_BUY, 96 | type=ORDER_TYPE_LIMIT, 97 | timeInForce=TIME_IN_FORCE_GTC, 98 | quantity=100, 99 | price='0.00001') 100 | 101 | 102 | `Check order status `_ 103 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 104 | 105 | .. code:: python 106 | 107 | order = client.get_margin_order( 108 | symbol='BNBBTC', 109 | orderId='orderId') 110 | 111 | 112 | `Cancel a margin order `_ 113 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 114 | 115 | .. code:: python 116 | 117 | result = client.cancel_margin_order( 118 | symbol='BNBBTC', 119 | orderId='orderId') 120 | 121 | 122 | `Get all open margin orders `_ 123 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 124 | 125 | .. code:: python 126 | 127 | orders = client.get_open_margin_orders(symbol='BNBBTC') 128 | 129 | For isolated margin, add the ``isIsolated='TRUE'`` parameter. 130 | 131 | `Get all margin orders `_ 132 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 133 | 134 | .. code:: python 135 | 136 | orders = client.get_all_margin_orders(symbol='BNBBTC') 137 | 138 | For isolated margin, add the ``isIsolated='TRUE'`` parameter. 139 | 140 | Account 141 | ------- 142 | 143 | `Get cross-margin account info `_ 144 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 145 | 146 | .. code:: python 147 | 148 | info = client.get_margin_account() 149 | 150 | `Create isolated margin account `_ 151 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 152 | 153 | .. code:: python 154 | 155 | account = client.create_isolated_margin_account(base='BTC', quote='ETH') 156 | 157 | `Get isolated margin account info `_ 158 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 159 | 160 | .. code:: python 161 | 162 | info = client.get_isolated_margin_account() 163 | 164 | `Transfer spot to cross-margin account `_ 165 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 166 | 167 | .. code:: python 168 | 169 | transaction = client.transfer_spot_to_margin(asset='BTC', amount='1.1') 170 | 171 | `Transfer cross-margin account to spot `_ 172 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 173 | 174 | .. code:: python 175 | 176 | transaction = client.transfer_margin_to_spot(asset='BTC', amount='1.1') 177 | 178 | `Transfer spot to isolated margin account `_ 179 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 180 | 181 | .. code:: python 182 | 183 | transaction = client.transfer_spot_to_isolated_margin(asset='BTC', 184 | symbol='ETHBTC', amount='1.1') 185 | 186 | `Transfer isolated margin account to spot `_ 187 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 188 | 189 | .. code:: python 190 | 191 | transaction = client.transfer_isolated_margin_to_spot(asset='BTC', 192 | symbol='ETHBTC', amount='1.1') 193 | 194 | `Get max transfer amount `_ 195 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 196 | 197 | .. code:: python 198 | 199 | details = client.get_max_margin_transfer(asset='BTC') 200 | 201 | This max transfer is for the cross-margin account by default. For isolated margin records, add the ``isolatedSymbol=symbol_name`` parameter. 202 | 203 | Trades 204 | ----- 205 | 206 | `Get all margin trades `_ 207 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 208 | 209 | .. code:: python 210 | 211 | trades = client.get_margin_trades(symbol='BNBBTC') 212 | 213 | For isolated margin trades, add the ``isIsolated='TRUE'`` parameter. 214 | 215 | 216 | Loans 217 | ----- 218 | 219 | `Create loan `_ 220 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 221 | 222 | .. code:: python 223 | 224 | transaction = client.create_margin_loan(asset='BTC', amount='1.1') 225 | 226 | This for the cross-margin account by default. For isolated margin, add the ``isIsolated='TRUE'`` and the ``symbol=symbol_name`` parameters. 227 | 228 | `Repay loan `_ 229 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 230 | 231 | .. code:: python 232 | 233 | transaction = client.repay_margin_loan(asset='BTC', amount='1.1') 234 | 235 | This for the cross-margin account by default. For isolated margin, add the ``isIsolated='TRUE'`` and the ``symbol=symbol_name`` parameters. 236 | 237 | `Get loan details `_ 238 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 239 | 240 | .. code:: python 241 | 242 | details = client.get_margin_loan_details(asset='BTC', txId='100001') 243 | 244 | This for the cross-margin account by default. For isolated margin records, add the ``isolatedSymbol=symbol_name`` parameter. 245 | 246 | `Get repay details `_ 247 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 248 | 249 | .. code:: python 250 | 251 | details = client.get_margin_repay_details(asset='BTC', txId='100001') 252 | 253 | This for the cross-margin account by default. For isolated margin records, add the ``isolatedSymbol=symbol_name`` parameter. 254 | 255 | `Get max loan amount `_ 256 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 257 | 258 | .. code:: python 259 | 260 | details = client.get_max_margin_loan(asset='BTC') 261 | 262 | The max loan is for the cross-margin account by default. For isolated margin records, add the ``isolatedSymbol=symbol_name`` parameter. 263 | -------------------------------------------------------------------------------- /docs/market_data.rst: -------------------------------------------------------------------------------- 1 | Market Data Endpoints 2 | ===================== 3 | 4 | 5 | `Get Market Depth `_ 6 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 7 | 8 | .. code:: python 9 | 10 | depth = client.get_order_book(symbol='BNBBTC') 11 | 12 | `Get Recent Trades `_ 13 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 14 | 15 | .. code:: python 16 | 17 | trades = client.get_recent_trades(symbol='BNBBTC') 18 | 19 | `Get Historical Trades `_ 20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21 | 22 | .. code:: python 23 | 24 | trades = client.get_historical_trades(symbol='BNBBTC') 25 | 26 | `Get Aggregate Trades `_ 27 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 28 | 29 | .. code:: python 30 | 31 | trades = client.get_aggregate_trades(symbol='BNBBTC') 32 | 33 | `Aggregate Trade Iterator `_ 34 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 35 | 36 | Iterate over aggregate trades for a symbol from a given date or a given order id. 37 | 38 | .. code:: python 39 | 40 | agg_trades = client.aggregate_trade_iter(symbol='ETHBTC', start_str='30 minutes ago UTC') 41 | 42 | # iterate over the trade iterator 43 | for trade in agg_trades: 44 | print(trade) 45 | # do something with the trade data 46 | 47 | # convert the iterator to a list 48 | # note: generators can only be iterated over once so we need to call it again 49 | agg_trades = client.aggregate_trade_iter(symbol='ETHBTC', '30 minutes ago UTC') 50 | agg_trade_list = list(agg_trades) 51 | 52 | # example using last_id value 53 | agg_trades = client.aggregate_trade_iter(symbol='ETHBTC', last_id=23380478) 54 | agg_trade_list = list(agg_trades) 55 | 56 | 57 | `Get Kline/Candlesticks `_ 58 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 59 | 60 | .. code:: python 61 | 62 | candles = client.get_klines(symbol='BNBBTC', interval=Client.KLINE_INTERVAL_30MINUTE) 63 | 64 | `Get Historical Kline/Candlesticks `_ 65 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 66 | 67 | Fetch klines for any date range and interval 68 | 69 | .. code:: python 70 | 71 | # fetch 1 minute klines for the last day up until now 72 | klines = client.get_historical_klines("BNBBTC", Client.KLINE_INTERVAL_1MINUTE, "1 day ago UTC") 73 | 74 | # fetch 30 minute klines for the last month of 2017 75 | klines = client.get_historical_klines("ETHBTC", Client.KLINE_INTERVAL_30MINUTE, "1 Dec, 2017", "1 Jan, 2018") 76 | 77 | # fetch weekly klines since it listed 78 | klines = client.get_historical_klines("NEOBTC", Client.KLINE_INTERVAL_1WEEK, "1 Jan, 2017") 79 | 80 | 81 | `Get Historical Kline/Candlesticks using a generator `_ 82 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 83 | 84 | Fetch klines using a generator 85 | 86 | .. code:: python 87 | 88 | for kline in client.get_historical_klines_generator("BNBBTC", Client.KLINE_INTERVAL_1MINUTE, "1 day ago UTC") 89 | print(kline) 90 | # do something with the kline 91 | 92 | `Get average price for a symbol `_ 93 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 94 | 95 | .. code:: python 96 | 97 | avg_price = client.get_avg_price(symbol='BNBBTC') 98 | 99 | `Get 24hr Ticker `_ 100 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 101 | 102 | .. code:: python 103 | 104 | tickers = client.get_ticker() 105 | 106 | `Get All Prices `_ 107 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 108 | 109 | Get last price for all markets. 110 | 111 | .. code:: python 112 | 113 | prices = client.get_all_tickers() 114 | 115 | `Get Orderbook Tickers `_ 116 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 117 | 118 | Get first bid and ask entry in the order book for all markets. 119 | 120 | .. code:: python 121 | 122 | tickers = client.get_orderbook_tickers() 123 | -------------------------------------------------------------------------------- /docs/overview.rst: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | 4 | Installation 5 | ------------ 6 | 7 | ``python-binance`` is available on `PYPI `_. 8 | Install with ``pip``: 9 | 10 | .. code:: bash 11 | 12 | pip install python-binance 13 | 14 | Register on Binance 15 | ------------------- 16 | 17 | Firstly `register an account with Binance `_. 18 | 19 | Generate an API Key 20 | ------------------- 21 | 22 | To use signed account methods you are required to `create an API Key `_. 23 | 24 | Initialise the client 25 | --------------------- 26 | 27 | Pass your API Key and Secret 28 | 29 | .. code:: python 30 | 31 | from binance.client import Client 32 | client = Client(api_key, api_secret) 33 | 34 | or for Asynchronous client 35 | 36 | .. code:: python 37 | 38 | async def main(): 39 | 40 | # initialise the client 41 | client = await AsyncClient.create(api_key, api_secret) 42 | 43 | if __name__ == "__main__": 44 | 45 | loop = asyncio.get_event_loop() 46 | loop.run_until_complete(main()) 47 | 48 | Using the Spot, Futures or Vanilla Options Testnet 49 | -------------------------------------------------- 50 | 51 | Binance offers a `Spot `_, 52 | `Futures `_ 53 | and `Vanilla Options `_ Testnet, 54 | to test interacting with the exchange. 55 | 56 | To enable this set the `testnet` parameter passed to the Client to True. 57 | 58 | The testnet parameter will also be used by any websocket streams when the client is passed to the BinanceSocketManager. 59 | 60 | .. code:: python 61 | 62 | client = Client(api_key, api_secret, testnet=True) 63 | 64 | or for Asynchronous client 65 | 66 | .. code:: python 67 | 68 | client = await AsyncClient.create(api_key, api_secret, testnet=True) 69 | 70 | Using a different TLD 71 | --------------------- 72 | 73 | If you are interacting with a regional version of Binance which has a different TLD such as `.us` or `.jp' then you 74 | will need to pass this when creating the client, see examples below. 75 | 76 | This tld will also be used by any websocket streams when the client is passed to the BinanceSocketManager. 77 | 78 | .. code:: python 79 | 80 | client = Client(api_key, api_secret, tld='us') 81 | 82 | or for Asynchronous client 83 | 84 | .. code:: python 85 | 86 | client = await AsyncClient.create(api_key, api_secret, tld='us') 87 | 88 | 89 | Making API Calls 90 | ---------------- 91 | 92 | Every method supports the passing of arbitrary parameters via keyword matching those in the `Binance API documentation `_. 93 | These keyword arguments will be sent directly to the relevant endpoint. 94 | 95 | Each API method returns a dictionary of the JSON response as per the `Binance API documentation `_. 96 | The docstring of each method in the code references the endpoint it implements. 97 | 98 | The Binance API documentation references a `timestamp` parameter, this is generated for you where required. 99 | 100 | Some methods have a `recvWindow` parameter for `timing security, see Binance documentation `_. 101 | 102 | API Endpoints are rate limited by Binance at 20 requests per second, ask them if you require more. 103 | 104 | Async API Calls 105 | --------------- 106 | 107 | aiohttp is used to handle asyncio REST requests. 108 | 109 | Each function available in the normal client is available in the AsyncClient class. 110 | 111 | The only difference is to run within an asyncio event loop and await the function like below. 112 | 113 | .. code:: python 114 | 115 | import asyncio 116 | from binance import AsyncClient 117 | 118 | async def main(): 119 | client = await AsyncClient.create() 120 | 121 | # fetch exchange info 122 | res = await client.get_exchange_info() 123 | print(json.dumps(res, indent=2)) 124 | 125 | await client.close_connection() 126 | 127 | if __name__ == "__main__": 128 | 129 | loop = asyncio.get_event_loop() 130 | loop.run_until_complete(main()) 131 | 132 | Read `Async basics for Binance `_ 133 | for more information about asynchronous patterns. 134 | 135 | API Rate Limit 136 | -------------- 137 | 138 | Check the `get_exchange_info() `_ call for up to date rate limits. 139 | 140 | At the current time Binance rate limits are: 141 | 142 | - 1200 requests per minute 143 | - 10 orders per second 144 | - 100,000 orders per 24hrs 145 | 146 | Some calls have a higher weight than others especially if a call returns information about all symbols. 147 | Read the `official Binance documentation `_ for specific information. 148 | 149 | On each request Binance returns `X-MBX-USED-WEIGHT-(intervalNum)(intervalLetter)` and `X-MBX-ORDER-COUNT-(intervalNum)` 150 | headers. 151 | 152 | Here are examples to access these 153 | 154 | Asynchronous example 155 | 156 | .. code:: python 157 | 158 | import asyncio 159 | from binance import AsyncClient 160 | 161 | api_key = '' 162 | api_secret = '' 163 | 164 | async def main(): 165 | client = await AsyncClient.create(api_key, api_secret) 166 | 167 | res = await client.get_exchange_info() 168 | print(client.response.headers) 169 | 170 | await client.close_connection() 171 | 172 | if __name__ == "__main__": 173 | 174 | loop = asyncio.get_event_loop() 175 | loop.run_until_complete(main()) 176 | 177 | Synchronous example 178 | 179 | 180 | .. code:: python 181 | 182 | from binance import Client 183 | 184 | api_key = '' 185 | api_secret = '' 186 | 187 | def main(): 188 | client = Client(api_key, api_secret) 189 | 190 | res = client.get_exchange_info() 191 | print(client.response.headers) 192 | 193 | if __name__ == "__main__": 194 | main() 195 | Requests Settings 196 | ----------------- 197 | 198 | `python-binance` uses the `requests `_ library. 199 | 200 | You can set custom requests parameters for all API calls when creating the client. 201 | 202 | .. code:: python 203 | 204 | client = Client("api-key", "api-secret", {"verify": False, "timeout": 20}) 205 | 206 | You may also pass custom requests parameters through any API call to override default settings or the above settingsspecify new ones like the example below. 207 | 208 | .. code:: python 209 | 210 | # this would result in verify: False and timeout: 5 for the get_all_orders call 211 | client = Client("api-key", "api-secret", {"verify": False, "timeout": 20}) 212 | client.get_all_orders(symbol='BNBBTC', requests_params={'timeout': 5}) 213 | 214 | Check out the `requests documentation `_ for all options. 215 | 216 | **Proxy Settings** 217 | 218 | You can use the Requests Settings method above 219 | 220 | .. code:: python 221 | 222 | proxies = { 223 | 'http': 'http://10.10.1.10:3128', 224 | 'https': 'http://10.10.1.10:1080' 225 | } 226 | 227 | # in the Client instantiation 228 | client = Client("api-key", "api-secret", {'proxies': proxies}) 229 | 230 | # or on an individual call 231 | client.get_all_orders(symbol='BNBBTC', requests_params={'proxies': proxies}) 232 | 233 | Or set an environment variable for your proxy if required to work across all requests. 234 | 235 | An example for Linux environments from the `requests Proxies documentation `_ is as follows. 236 | 237 | .. code-block:: bash 238 | 239 | $ export HTTP_PROXY="http://10.10.1.10:3128" 240 | $ export HTTPS_PROXY="http://10.10.1.10:1080" 241 | 242 | For Windows environments 243 | 244 | .. code-block:: bash 245 | 246 | C:\>set HTTP_PROXY=http://10.10.1.10:3128 247 | C:\>set HTTPS_PROXY=http://10.10.1.10:1080 248 | 249 | .. image:: https://analytics-pixel.appspot.com/UA-111417213-1/github/python-binance/docs/overview?pixel 250 | -------------------------------------------------------------------------------- /docs/sub_accounts.rst: -------------------------------------------------------------------------------- 1 | Sub Account Endpoints 2 | ===================== 3 | 4 | 5 | `Get Sub Account list `_ 6 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 7 | 8 | .. code:: python 9 | 10 | accounts = client.get_sub_account_list() 11 | 12 | `Get Sub Account Transfer History `_ 13 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 14 | 15 | .. code:: python 16 | 17 | history = client.get_sub_account_transfer_history(fromEmail='blah@gmail.com', toEmail='foo@gmail.com') 18 | 19 | `Get Sub Account Assets `_ 20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 21 | 22 | .. code:: python 23 | 24 | assets = client.get_sub_account_assets(email='blah@gmail.com') 25 | -------------------------------------------------------------------------------- /docs/websockets.rst: -------------------------------------------------------------------------------- 1 | Websockets 2 | ========== 3 | 4 | There are 2 ways to interact with websockets. 5 | 6 | with `ThreadedWebsocketManager `_ or `BinanceSocketManager `_. 7 | 8 | ThreadedWebsocketManager does not require asyncio programming, while BinanceSocketManager does. 9 | 10 | ThreadedWebsocketManager function begin with `start_`, e.g `start_ticker_socket` while BinanceSocketManager is simply `ticker_socket`. 11 | 12 | Multiple socket connections can be made through either manager. 13 | 14 | Only one instance of each socket type will be created, i.e. only one BNBBTC Depth socket can be created 15 | and there can be both a BNBBTC Depth and a BNBBTC Trade socket open at once. 16 | 17 | Messages are received as dictionary objects relating to the message formats defined in the `Binance WebSocket API documentation `_. 18 | 19 | Websockets are setup to reconnect with a maximum of 5 retries with an exponential backoff strategy. 20 | 21 | ThreadedWebsocketManager Websocket Usage 22 | ---------------------------------------- 23 | 24 | Starting sockets on the ThreadedWebsocketManager requires a callback parameter, similar to the old implementations of websockets on python-binance. 25 | 26 | ThreadedWebsocketManager takes similar parameters to the `Client `_ class as it 27 | creates an AsyncClient internally. 28 | 29 | For authenticated streams `api_key` and `api_stream` are required. 30 | 31 | As these use threads `start()` is required to be called before starting any sockets. 32 | 33 | To keep the ThreadedWebsocketManager running, use `join()` to join it to the main thread. 34 | 35 | .. code:: python 36 | 37 | import time 38 | 39 | from binance import ThreadedWebsocketManager 40 | 41 | api_key = ' 42 | api_secret = ' 43 | 44 | def main(): 45 | 46 | symbol = 'BNBBTC' 47 | 48 | twm = ThreadedWebsocketManager(api_key=api_key, api_secret=api_secret) 49 | # start is required to initialise its internal loop 50 | twm.start() 51 | 52 | def handle_socket_message(msg): 53 | print(f"message type: {msg['e']}") 54 | print(msg) 55 | 56 | twm.start_kline_socket(callback=handle_socket_message, symbol=symbol) 57 | 58 | # multiple sockets can be started 59 | twm.start_depth_socket(callback=handle_socket_message, symbol=symbol) 60 | 61 | # or a multiplex socket can be started like this 62 | # see Binance docs for stream names 63 | streams = ['bnbbtc@miniTicker', 'bnbbtc@bookTicker'] 64 | twm.start_multiplex_socket(callback=handle_socket_message, streams=streams) 65 | 66 | twm.join() 67 | 68 | 69 | if __name__ == "__main__": 70 | main() 71 | 72 | **Stop Individual Stream** 73 | 74 | When starting a stream, a name for that stream will be returned. This can be used to stop that individual stream. 75 | 76 | .. code:: python 77 | 78 | from binance import ThreadedWebsocketManager 79 | 80 | symbol = 'BNBBTC' 81 | 82 | twm = ThreadedWebsocketManager() 83 | # start is required to initialise its internal loop 84 | twm.start() 85 | 86 | def handle_socket_message(msg): 87 | print(f"message type: {msg['e']}") 88 | print(msg) 89 | 90 | twm.start_kline_socket(callback=handle_socket_message, symbol=symbol) 91 | depth_stream_name = twm.start_depth_socket(callback=handle_socket_message, symbol=symbol) 92 | 93 | # some time later 94 | 95 | twm.stop_socket(depth_stream_name) 96 | 97 | **Stop All Streams** 98 | 99 | .. code:: python 100 | 101 | from binance import ThreadedWebsocketManager 102 | 103 | twm = ThreadedWebsocketManager() 104 | # start is required to initialise its internal loop 105 | twm.start() 106 | 107 | def handle_socket_message(msg): 108 | print(f"message type: {msg['e']}") 109 | print(msg) 110 | 111 | depth_stream_name = twm.start_depth_socket(callback=handle_socket_message, symbol=symbol) 112 | 113 | twm.stop() 114 | 115 | Attempting to start a stream after `stop` is called will not work. 116 | 117 | 118 | BinanceSocketManager Websocket Usage 119 | ------------------------------------ 120 | 121 | Create the manager like so, passing an AsyncClient. 122 | 123 | .. code:: python 124 | 125 | import asyncio 126 | from binance import AsyncClient, BinanceSocketManager 127 | 128 | 129 | async def main(): 130 | client = await AsyncClient.create() 131 | bm = BinanceSocketManager(client) 132 | # start any sockets here, i.e a trade socket 133 | ts = bm.trade_socket('BNBBTC') 134 | # then start receiving messages 135 | async with ts as tscm: 136 | while True: 137 | res = await tscm.recv() 138 | print(res) 139 | 140 | await client.close_connection() 141 | 142 | if __name__ == "__main__": 143 | 144 | loop = asyncio.get_event_loop() 145 | loop.run_until_complete(main()) 146 | 147 | Set a custom timeout for the websocket connections 148 | 149 | .. code:: python 150 | 151 | # set a timeout of 60 seconds 152 | bm = BinanceSocketManager(client, user_timeout=60) 153 | 154 | Manually enter and exit the Asynchronous context manager 155 | 156 | .. code:: python 157 | 158 | ts = bm.trade_socket('BNBBTC') 159 | # enter the context manager 160 | await ts.__aenter__() 161 | # receive a message 162 | msg = await ts.recv() 163 | print(msg) 164 | # exit the context manager 165 | await ts.__aexit__(None, None, None) 166 | 167 | 168 | Using a different TLD 169 | --------------------- 170 | 171 | The ThreadedWebsocketManager can take the tld when created if required. 172 | 173 | .. code:: python 174 | 175 | from binance.streams import ThreadedWebsocketManager 176 | 177 | twm = ThreadedWebsocketManager(tld='us') 178 | 179 | The BinanceSocketManager uses the same tld value as the AsyncClient that is passed in. To use the 'us' tld we 180 | can do this. 181 | 182 | .. code:: python 183 | 184 | from binance import AsyncClient, BinanceSocketManager 185 | 186 | async def x(): 187 | client = await AsyncClient.create(tld='us') 188 | bm = BinanceSocketManager(client) 189 | 190 | # start a socket... 191 | 192 | await client.close_connection() 193 | 194 | 195 | Websocket Errors 196 | ---------------- 197 | 198 | If the websocket is disconnected and is unable to reconnect, a message is sent to the callback to indicate this. The format is 199 | 200 | .. code:: python 201 | 202 | { 203 | 'e': 'error', 204 | 'm': 'Max reconnect retries reached' 205 | } 206 | 207 | # check for it like so 208 | def process_message(msg): 209 | if msg['e'] == 'error': 210 | # close and restart the socket 211 | else: 212 | # process message normally 213 | 214 | 215 | `Multiplex Socket `_ 216 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 217 | 218 | Create a socket combining multiple streams. 219 | 220 | These streams can include the depth, kline, ticker and trade streams but not the user stream which requires extra authentication. 221 | 222 | Symbols in socket name must be lowercase i.e bnbbtc@aggTrade, neobtc@ticker 223 | 224 | See the `Binance Websocket Streams API documentation `_ for details on socket names. 225 | 226 | .. code:: python 227 | 228 | # pass a list of stream names 229 | ms = bm.multiplex_socket(['bnbbtc@aggTrade', 'neobtc@ticker']) 230 | 231 | `Depth Socket `_ 232 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 233 | 234 | Depth sockets have an optional depth parameter to receive partial book rather than a diff response. 235 | By default this the diff response is returned. 236 | Valid depth values are 5, 10 and 20 and `defined as enums `_. 237 | 238 | .. code:: python 239 | 240 | # depth diff response 241 | ds = bm.depth_socket('BNBBTC') 242 | 243 | # partial book response 244 | ds = bm.depth_socket('BNBBTC', depth=BinanceSocketManager.WEBSOCKET_DEPTH_5) 245 | 246 | 247 | `Kline Socket `_ 248 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 249 | 250 | Kline sockets have an optional interval parameter. By default this is set to 1 minute. 251 | Valid interval values are `defined as enums `_. 252 | 253 | .. code:: python 254 | 255 | from binance.enums import * 256 | ks = bm.kline_socket('BNBBTC', interval=KLINE_INTERVAL_30MINUTE) 257 | 258 | 259 | `Aggregated Trade Socket `_ 260 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 261 | 262 | .. code:: python 263 | 264 | ats = bm.aggtrade_socket('BNBBTC') 265 | 266 | 267 | `Trade Socket `_ 268 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 269 | 270 | .. code:: python 271 | 272 | ts = bm.trade_socket('BNBBTC') 273 | 274 | `Symbol Ticker Socket `_ 275 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 276 | 277 | .. code:: python 278 | 279 | sts = bm.symbol_ticker_socket('BNBBTC') 280 | 281 | `Ticker Socket `_ 282 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 283 | 284 | .. code:: python 285 | 286 | ts = bm.ticker_socket(process_message) 287 | 288 | `Mini Ticker Socket `_ 289 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 290 | 291 | .. code:: python 292 | 293 | # by default updates every second 294 | mts = bm.miniticker_socket() 295 | 296 | # this socket can take an update interval parameter 297 | # set as 5000 to receive updates every 5 seconds 298 | mts = bm.miniticker_socket(5000) 299 | 300 | User Socket 301 | +++++++++++ 302 | 303 | This watches for 3 different user events 304 | 305 | - Account Update Event 306 | - Order Update Event 307 | - Trade Update Event 308 | 309 | The Manager handles keeping the socket alive. 310 | 311 | There are separate sockets for Spot, Cross-margin and separate Isolated margin accounts. 312 | 313 | `Spot trading `_ 314 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 315 | 316 | .. code:: python 317 | 318 | bm.user_socket() 319 | 320 | 321 | `Cross-margin `_ 322 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 323 | 324 | .. code:: python 325 | 326 | bm.margin_socket() 327 | 328 | 329 | `Isolated margin `_ 330 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 331 | 332 | .. code:: python 333 | 334 | bm.isolated_margin_socket(symbol) 335 | 336 | -------------------------------------------------------------------------------- /docs/withdraw.rst: -------------------------------------------------------------------------------- 1 | Withdraw Endpoints 2 | ================== 3 | 4 | `Place a withdrawal `_ 5 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | Make sure you enable Withdrawal permissions for your API Key to use this call. 8 | 9 | You must have withdrawn to the address through the website and approved the withdrawal via email before you can withdraw using the API. 10 | 11 | .. code:: python 12 | 13 | from binance.exceptions import BinanceAPIException 14 | try: 15 | # name parameter will be set to the asset value by the client if not passed 16 | result = client.withdraw( 17 | coin='ETH', 18 | address='', 19 | amount=100) 20 | except BinanceAPIException as e: 21 | print(e) 22 | else: 23 | print("Success") 24 | 25 | # passing a name parameter 26 | result = client.withdraw( 27 | coin='ETH', 28 | address='', 29 | amount=100, 30 | name='Withdraw') 31 | 32 | # if the coin requires a extra tag or name such as XRP or XMR then pass an `addressTag` parameter. 33 | result = client.withdraw( 34 | coin='XRP', 35 | address='', 36 | addressTag='', 37 | amount=10000) 38 | 39 | `Fetch deposit history `_ 40 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 41 | 42 | .. code:: python 43 | 44 | deposits = client.get_deposit_history() 45 | btc_deposits = client.get_deposit_history(coin='BTC') 46 | 47 | 48 | `Fetch withdraw history `_ 49 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 50 | 51 | .. code:: python 52 | 53 | withdraws = client.get_withdraw_history() 54 | btc_withdraws = client.get_withdraw_history(coin='BTC') 55 | 56 | `Get deposit address `_ 57 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 58 | 59 | .. code:: python 60 | 61 | address = client.get_deposit_address(coin='BTC') 62 | -------------------------------------------------------------------------------- /examples/save_historical_data.py: -------------------------------------------------------------------------------- 1 | import time 2 | import dateparser 3 | import pytz 4 | import json 5 | 6 | from datetime import datetime 7 | from binance.client import Client 8 | 9 | 10 | def date_to_milliseconds(date_str): 11 | """Convert UTC date to milliseconds 12 | 13 | If using offset strings add "UTC" to date string e.g. "now UTC", "11 hours ago UTC" 14 | 15 | See dateparse docs for formats http://dateparser.readthedocs.io/en/latest/ 16 | 17 | :param date_str: date in readable format, i.e. "January 01, 2018", "11 hours ago UTC", "now UTC" 18 | :type date_str: str 19 | """ 20 | # get epoch value in UTC 21 | epoch = datetime.utcfromtimestamp(0).replace(tzinfo=pytz.utc) 22 | # parse our date string 23 | d = dateparser.parse(date_str) 24 | # if the date is not timezone aware apply UTC timezone 25 | if d.tzinfo is None or d.tzinfo.utcoffset(d) is None: 26 | d = d.replace(tzinfo=pytz.utc) 27 | 28 | # return the difference in time 29 | return int((d - epoch).total_seconds() * 1000.0) 30 | 31 | 32 | def interval_to_milliseconds(interval): 33 | """Convert a Binance interval string to milliseconds 34 | 35 | :param interval: Binance interval string 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w 36 | :type interval: str 37 | 38 | :return: 39 | None if unit not one of m, h, d or w 40 | None if string not in correct format 41 | int value of interval in milliseconds 42 | """ 43 | ms = None 44 | seconds_per_unit = { 45 | "m": 60, 46 | "h": 60 * 60, 47 | "d": 24 * 60 * 60, 48 | "w": 7 * 24 * 60 * 60 49 | } 50 | 51 | unit = interval[-1] 52 | if unit in seconds_per_unit: 53 | try: 54 | ms = int(interval[:-1]) * seconds_per_unit[unit] * 1000 55 | except ValueError: 56 | pass 57 | return ms 58 | 59 | 60 | def get_historical_klines(symbol, interval, start_str, end_str=None): 61 | """Get Historical Klines from Binance 62 | 63 | See dateparse docs for valid start and end string formats http://dateparser.readthedocs.io/en/latest/ 64 | 65 | If using offset strings for dates add "UTC" to date string e.g. "now UTC", "11 hours ago UTC" 66 | 67 | :param symbol: Name of symbol pair e.g BNBBTC 68 | :type symbol: str 69 | :param interval: Biannce Kline interval 70 | :type interval: str 71 | :param start_str: Start date string in UTC format 72 | :type start_str: str 73 | :param end_str: optional - end date string in UTC format 74 | :type end_str: str 75 | 76 | :return: list of OHLCV values 77 | 78 | """ 79 | # create the Binance client, no need for api key 80 | client = Client("", "") 81 | 82 | # init our list 83 | output_data = [] 84 | 85 | # setup the max limit 86 | limit = 500 87 | 88 | # convert interval to useful value in seconds 89 | timeframe = interval_to_milliseconds(interval) 90 | 91 | # convert our date strings to milliseconds 92 | start_ts = date_to_milliseconds(start_str) 93 | 94 | # if an end time was passed convert it 95 | end_ts = None 96 | if end_str: 97 | end_ts = date_to_milliseconds(end_str) 98 | 99 | idx = 0 100 | # it can be difficult to know when a symbol was listed on Binance so allow start time to be before list date 101 | symbol_existed = False 102 | while True: 103 | # fetch the klines from start_ts up to max 500 entries or the end_ts if set 104 | temp_data = client.get_klines( 105 | symbol=symbol, 106 | interval=interval, 107 | limit=limit, 108 | startTime=start_ts, 109 | endTime=end_ts 110 | ) 111 | 112 | # handle the case where our start date is before the symbol pair listed on Binance 113 | if not symbol_existed and len(temp_data): 114 | symbol_existed = True 115 | 116 | if symbol_existed: 117 | # append this loops data to our output data 118 | output_data += temp_data 119 | 120 | # update our start timestamp using the last value in the array and add the interval timeframe 121 | start_ts = temp_data[len(temp_data) - 1][0] + timeframe 122 | else: 123 | # it wasn't listed yet, increment our start date 124 | start_ts += timeframe 125 | 126 | idx += 1 127 | # check if we received less than the required limit and exit the loop 128 | if len(temp_data) < limit: 129 | # exit the while loop 130 | break 131 | 132 | # sleep after every 3rd call to be kind to the API 133 | if idx % 3 == 0: 134 | time.sleep(1) 135 | 136 | return output_data 137 | 138 | 139 | symbol = "ETHBTC" 140 | start = "1 Dec, 2017" 141 | end = "1 Jan, 2018" 142 | interval = Client.KLINE_INTERVAL_30MINUTE 143 | 144 | klines = get_historical_klines(symbol, interval, start, end) 145 | 146 | # open a file with filename including symbol, interval and start and end converted to milliseconds 147 | with open( 148 | "Binance_{}_{}_{}-{}.json".format( 149 | symbol, 150 | interval, 151 | date_to_milliseconds(start), 152 | date_to_milliseconds(end) 153 | ), 154 | 'w' # set file write mode 155 | ) as f: 156 | f.write(json.dumps(klines)) 157 | -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pro-WebTech/binance-py/45191bdc119a677b63e9bcf63f9512883a05035a/pytest.ini -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp 2 | dateparser 3 | requests 4 | ujson 5 | websockets==9.1 6 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 3 | 4 | [pep8] 5 | ignore = E501 6 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from setuptools import setup 3 | import codecs 4 | import os 5 | import re 6 | 7 | 8 | with codecs.open( 9 | os.path.join( 10 | os.path.abspath(os.path.dirname(__file__)), 11 | 'binance', 12 | '__init__.py' 13 | ), 'r', 'latin1') as fp: 14 | try: 15 | version = re.findall(r"^__version__ = '([^']+)'\r?$", fp.read(), re.M)[0] 16 | except IndexError: 17 | raise RuntimeError('Unable to determine version.') 18 | 19 | with open("README.rst", "r") as fh: 20 | long_description = fh.read() 21 | 22 | setup( 23 | name='python-binance', 24 | version=version, 25 | packages=['binance'], 26 | description='Binance REST API python implementation', 27 | long_description=long_description, 28 | long_description_content_type="text/x-rst", 29 | url='https://github.com/sammchardy/python-binance', 30 | author='Sam McHardy', 31 | license='MIT', 32 | author_email='', 33 | install_requires=[ 34 | 'requests', 'six', 'dateparser', 'aiohttp', 'ujson', 'websockets==9.1' 35 | ], 36 | keywords='binance exchange rest api bitcoin ethereum btc eth neo', 37 | classifiers=[ 38 | 'Intended Audience :: Developers', 39 | 'License :: OSI Approved :: MIT License', 40 | 'Operating System :: OS Independent', 41 | 'Programming Language :: Python :: 3', 42 | 'Programming Language :: Python :: 3.5', 43 | 'Programming Language :: Python :: 3.6', 44 | 'Programming Language :: Python :: 3.7', 45 | 'Programming Language :: Python', 46 | 'Topic :: Software Development :: Libraries :: Python Modules', 47 | ], 48 | ) 49 | -------------------------------------------------------------------------------- /test-requirements.txt: -------------------------------------------------------------------------------- 1 | coverage 2 | flake8 3 | pytest 4 | pytest-cov 5 | pytest-pep8 6 | python-coveralls 7 | requests-mock 8 | tox 9 | setuptools -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pro-WebTech/binance-py/45191bdc119a677b63e9bcf63f9512883a05035a/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_api_request.py: -------------------------------------------------------------------------------- 1 | from binance.client import Client 2 | from binance.exceptions import BinanceAPIException, BinanceRequestException 3 | import pytest 4 | import requests_mock 5 | 6 | 7 | client = Client("api_key", "api_secret") 8 | 9 | 10 | def test_invalid_json(): 11 | """Test Invalid response Exception""" 12 | 13 | with pytest.raises(BinanceRequestException): 14 | with requests_mock.mock() as m: 15 | m.get( 16 | "https://www.binance.com/exchange-api/v1/public/asset-service/product/get-products", 17 | text="", 18 | ) 19 | client.get_products() 20 | 21 | 22 | def test_api_exception(): 23 | """Test API response Exception""" 24 | 25 | with pytest.raises(BinanceAPIException): 26 | with requests_mock.mock() as m: 27 | json_obj = {"code": 1002, "msg": "Invalid API call"} 28 | m.get("https://api.binance.com/api/v3/time", json=json_obj, status_code=400) 29 | client.get_server_time() 30 | 31 | 32 | def test_api_exception_invalid_json(): 33 | """Test API response Exception""" 34 | 35 | with pytest.raises(BinanceAPIException): 36 | with requests_mock.mock() as m: 37 | not_json_str = "Error" 38 | m.get("https://api.binance.com/api/v3/time", text=not_json_str, status_code=400) 39 | client.get_server_time() 40 | -------------------------------------------------------------------------------- /tests/test_depth_cache.py: -------------------------------------------------------------------------------- 1 | from binance.depthcache import DepthCache 2 | from decimal import Decimal 3 | import pytest 4 | 5 | TEST_SYMBOL = "BNBBTC" 6 | 7 | 8 | @pytest.fixture 9 | def fresh_cache(): 10 | return DepthCache(TEST_SYMBOL, Decimal) 11 | 12 | 13 | def test_add_bids(fresh_cache): 14 | """Verify basic functionality for adding a bid to the cache""" 15 | high_bid = [0.111, 489] 16 | mid_bid = [0.018, 300] 17 | low_bid = [0.001, 100] 18 | for bid in [high_bid, low_bid, mid_bid]: 19 | fresh_cache.add_bid(bid) 20 | 21 | bids = fresh_cache.get_bids() 22 | 23 | assert len(bids) == 3 24 | 25 | assert bids == sorted(bids, reverse=True) 26 | 27 | assert isinstance(bids[0][0], Decimal) 28 | assert isinstance(bids[0][1], Decimal) 29 | 30 | 31 | def test_add_asks(fresh_cache): 32 | """Verify basic functionality for adding an ask to the cache""" 33 | high_ask = [0.111, 489] 34 | mid_ask = [0.018, 300] 35 | low_ask = [0.001, 100] 36 | 37 | for ask in [high_ask, low_ask, mid_ask]: 38 | fresh_cache.add_ask(ask) 39 | 40 | asks = fresh_cache.get_asks() 41 | 42 | # Three asks should be in the cache 43 | assert len(asks) == 3 44 | 45 | # Lowest ask price should be first (ascending order) 46 | assert asks == sorted(asks) 47 | 48 | assert isinstance(asks[0][0], Decimal) 49 | assert isinstance(asks[0][1], Decimal) 50 | -------------------------------------------------------------------------------- /tests/test_historical_klines.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | from binance.client import Client 5 | import pytest 6 | import requests_mock 7 | 8 | 9 | client = Client("api_key", "api_secret") 10 | 11 | 12 | def test_exact_amount(): 13 | """Test Exact amount returned""" 14 | 15 | first_available_res = [ 16 | [ 17 | 1500004800000, 18 | "0.00005000", 19 | "0.00005300", 20 | "0.00001000", 21 | "0.00004790", 22 | "663152.00000000", 23 | 1500004859999, 24 | "30.55108144", 25 | 43, 26 | "559224.00000000", 27 | "25.65468144", 28 | "83431971.04346950", 29 | ] 30 | ] 31 | 32 | first_res = [] 33 | row = [ 34 | 1519892340000, 35 | "0.00099400", 36 | "0.00099810", 37 | "0.00099400", 38 | "0.00099810", 39 | "4806.04000000", 40 | 1519892399999, 41 | "4.78553253", 42 | 154, 43 | "1785.14000000", 44 | "1.77837524", 45 | "0", 46 | ] 47 | 48 | for i in range(0, 500): 49 | first_res.append(row) 50 | 51 | second_res = [] 52 | 53 | with requests_mock.mock() as m: 54 | m.get( 55 | "https://api.binance.com/api/v3/klines?interval=1m&limit=1&startTime=0&symbol=BNBBTC", 56 | json=first_available_res, 57 | ) 58 | m.get( 59 | "https://api.binance.com/api/v3/klines?interval=1m&limit=500&startTime=1519862400000&symbol=BNBBTC", 60 | json=first_res, 61 | ) 62 | m.get( 63 | "https://api.binance.com/api/v3/klines?interval=1m&limit=500&startTime=1519892400000&symbol=BNBBTC", 64 | json=second_res, 65 | ) 66 | klines = client.get_historical_klines( 67 | symbol="BNBBTC", interval=Client.KLINE_INTERVAL_1MINUTE, start_str="1st March 2018" 68 | ) 69 | assert len(klines) == 500 70 | 71 | 72 | def test_start_and_end_str(): 73 | """Test start_str and end_str work correctly with string""" 74 | 75 | first_available_res = [ 76 | [ 77 | 1500004800000, 78 | "0.00005000", 79 | "0.00005300", 80 | "0.00001000", 81 | "0.00004790", 82 | "663152.00000000", 83 | 1500004859999, 84 | "30.55108144", 85 | 43, 86 | "559224.00000000", 87 | "25.65468144", 88 | "83431971.04346950", 89 | ] 90 | ] 91 | first_res = [] 92 | row = [ 93 | 1519892340000, 94 | "0.00099400", 95 | "0.00099810", 96 | "0.00099400", 97 | "0.00099810", 98 | "4806.04000000", 99 | 1519892399999, 100 | "4.78553253", 101 | 154, 102 | "1785.14000000", 103 | "1.77837524", 104 | "0", 105 | ] 106 | 107 | for i in range(0, 300): 108 | first_res.append(row) 109 | 110 | with requests_mock.mock() as m: 111 | m.get( 112 | "https://api.binance.com/api/v3/klines?interval=1m&limit=1&startTime=0&symbol=BNBBTC", 113 | json=first_available_res, 114 | ) 115 | m.get( 116 | "https://api.binance.com/api/v3/klines?interval=1m&limit=500&startTime=1519862400000&endTime=1519880400000&symbol=BNBBTC", 117 | json=first_res, 118 | ) 119 | klines = client.get_historical_klines( 120 | symbol="BNBBTC", 121 | interval=Client.KLINE_INTERVAL_1MINUTE, 122 | start_str="1st March 2018", 123 | end_str="1st March 2018 05:00:00", 124 | ) 125 | assert len(klines) == 300 126 | 127 | 128 | def test_start_and_end_timestamp(): 129 | """Test start_str and end_str work correctly with integer timestamp""" 130 | 131 | first_available_res = [ 132 | [ 133 | 1500004800000, 134 | "0.00005000", 135 | "0.00005300", 136 | "0.00001000", 137 | "0.00004790", 138 | "663152.00000000", 139 | 1500004859999, 140 | "30.55108144", 141 | 43, 142 | "559224.00000000", 143 | "25.65468144", 144 | "83431971.04346950", 145 | ] 146 | ] 147 | first_res = [] 148 | row = [ 149 | 1519892340000, 150 | "0.00099400", 151 | "0.00099810", 152 | "0.00099400", 153 | "0.00099810", 154 | "4806.04000000", 155 | 1519892399999, 156 | "4.78553253", 157 | 154, 158 | "1785.14000000", 159 | "1.77837524", 160 | "0", 161 | ] 162 | 163 | for i in range(0, 300): 164 | first_res.append(row) 165 | 166 | with requests_mock.mock() as m: 167 | m.get( 168 | "https://api.binance.com/api/v3/klines?interval=1m&limit=1&startTime=0&symbol=BNBBTC", 169 | json=first_available_res, 170 | ) 171 | m.get( 172 | "https://api.binance.com/api/v3/klines?interval=1m&limit=500&startTime=1519862400000&endTime=1519880400000&symbol=BNBBTC", 173 | json=first_res, 174 | ) 175 | klines = client.get_historical_klines( 176 | symbol="BNBBTC", 177 | interval=Client.KLINE_INTERVAL_1MINUTE, 178 | start_str=1519862400000, 179 | end_str=1519880400000, 180 | ) 181 | assert len(klines) == 300 182 | 183 | 184 | def test_historical_kline_generator(): 185 | """Test kline historical generator""" 186 | 187 | first_available_res = [ 188 | [ 189 | 1500004800000, 190 | "0.00005000", 191 | "0.00005300", 192 | "0.00001000", 193 | "0.00004790", 194 | "663152.00000000", 195 | 1500004859999, 196 | "30.55108144", 197 | 43, 198 | "559224.00000000", 199 | "25.65468144", 200 | "83431971.04346950", 201 | ] 202 | ] 203 | first_res = [] 204 | row = [ 205 | 1519892340000, 206 | "0.00099400", 207 | "0.00099810", 208 | "0.00099400", 209 | "0.00099810", 210 | "4806.04000000", 211 | 1519892399999, 212 | "4.78553253", 213 | 154, 214 | "1785.14000000", 215 | "1.77837524", 216 | "0", 217 | ] 218 | 219 | for i in range(0, 300): 220 | first_res.append(row) 221 | 222 | with requests_mock.mock() as m: 223 | m.get( 224 | "https://api.binance.com/api/v3/klines?interval=1m&limit=1&startTime=0&symbol=BNBBTC", 225 | json=first_available_res, 226 | ) 227 | m.get( 228 | "https://api.binance.com/api/v3/klines?interval=1m&limit=500&startTime=1519862400000&endTime=1519880400000&symbol=BNBBTC", 229 | json=first_res, 230 | ) 231 | klines = client.get_historical_klines_generator( 232 | symbol="BNBBTC", 233 | interval=Client.KLINE_INTERVAL_1MINUTE, 234 | start_str=1519862400000, 235 | end_str=1519880400000, 236 | ) 237 | 238 | for i in range(300): 239 | assert len(next(klines)) > 0 240 | 241 | with pytest.raises(StopIteration): 242 | next(klines) 243 | 244 | 245 | def test_historical_kline_generator_empty_response(): 246 | """Test kline historical generator if an empty list is returned from API""" 247 | first_available_res = [ 248 | [ 249 | 1500004800000, 250 | "0.00005000", 251 | "0.00005300", 252 | "0.00001000", 253 | "0.00004790", 254 | "663152.00000000", 255 | 1500004859999, 256 | "30.55108144", 257 | 43, 258 | "559224.00000000", 259 | "25.65468144", 260 | "83431971.04346950", 261 | ] 262 | ] 263 | first_res = [] 264 | 265 | with requests_mock.mock() as m: 266 | m.get( 267 | "https://api.binance.com/api/v3/klines?interval=1m&limit=1&startTime=0&symbol=BNBBTC", 268 | json=first_available_res, 269 | ) 270 | m.get( 271 | "https://api.binance.com/api/v3/klines?interval=1m&limit=500&startTime=1519862400000&endTime=1519880400000&symbol=BNBBTC", 272 | json=first_res, 273 | ) 274 | klines = client.get_historical_klines_generator( 275 | symbol="BNBBTC", 276 | interval=Client.KLINE_INTERVAL_1MINUTE, 277 | start_str=1519862400000, 278 | end_str=1519880400000, 279 | ) 280 | 281 | with pytest.raises(StopIteration): 282 | next(klines) 283 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py36, py37, py38, py39 3 | 4 | [testenv] 5 | deps = 6 | -rtest-requirements.txt 7 | -rrequirements.txt 8 | commands = py.test -v tests/ --doctest-modules --cov binance --cov-report term-missing 9 | passenv = 10 | TRAVIS 11 | TRAVIS_BRANCH 12 | TRAVIS_JOB_ID 13 | 14 | [testenv:flake8] 15 | commands = flake8 binance/ setup.py examples/ 16 | deps = flake8 17 | 18 | [travis] 19 | python = 20 | 3.8: py38, flake8 21 | 22 | [flake8] 23 | exclude = 24 | .git, 25 | .tox, 26 | build, 27 | dist 28 | ignore = E501 29 | 30 | [pep8] 31 | ignore = E501 32 | --------------------------------------------------------------------------------