├── .gitignore ├── balances.py ├── btc_bars3.csv ├── btc_historical_csv.py ├── buy_bnb.py ├── create_order.py ├── indicators.py ├── latest_btc_price.py ├── pair_trading_percent.py ├── pair_trading_price.py ├── readme.rst ├── requirements.txt ├── stop_loss_order.py └── websocket_stream.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /balances.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from binance.client import Client 4 | 5 | # init 6 | api_key = os.environ.get('binance_api') 7 | api_secret = os.environ.get('binance_secret') 8 | 9 | client = Client(api_key, api_secret) 10 | 11 | ## main 12 | 13 | # get balances for all assets & some account information 14 | print(client.get_account()) 15 | 16 | # get balance for a specific asset only (BTC) 17 | print(client.get_asset_balance(asset='BTC')) 18 | 19 | # get balances for futures account 20 | print(client.futures_account_balance()) 21 | 22 | # get balances for margin account 23 | # will raise an exception if margin account is not activated 24 | #print(client.get_margin_account()) 25 | -------------------------------------------------------------------------------- /btc_historical_csv.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import json 3 | import os 4 | 5 | import pandas as pd 6 | from binance.client import Client 7 | 8 | # init 9 | api_key = os.environ.get('binance_api') 10 | api_secret = os.environ.get('binance_secret') 11 | 12 | client = Client(api_key, api_secret) 13 | 14 | ## main 15 | 16 | # valid intervals - 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M 17 | # get timestamp of earliest date data is available 18 | timestamp = client._get_earliest_valid_timestamp('BTCUSDT', '1d') 19 | print(timestamp) 20 | 21 | # request historical candle (or klines) data 22 | bars = client.get_historical_klines('BTCUSDT', '1d', timestamp, limit=1000) 23 | # print(bars) 24 | 25 | # option 1 - save to file using json method - this will retain Python format (list of lists) 26 | with open('btc_bars.json', 'w') as e: 27 | json.dump(bars, e) 28 | 29 | # option 2 - save as CSV file using the csv writer library 30 | with open('btc_bars.csv', 'w', newline='') as f: 31 | wr = csv.writer(f) 32 | for line in bars: 33 | wr.writerow(line) 34 | 35 | # option 3 - save as CSV file without using a library. Shorten to just date, open, high, low, close 36 | with open('btc_bars2.csv', 'w') as d: 37 | for line in bars: 38 | d.write(f'{line[0]}, {line[1]}, {line[2]}, {line[3]}, {line[4]}\n') 39 | 40 | # delete unwanted data - just keep date, open, high, low, close 41 | for line in bars: 42 | del line[5:] 43 | 44 | # option 4 - create a Pandas DataFrame and export to CSV 45 | btc_df = pd.DataFrame(bars, columns=['date', 'open', 'high', 'low', 'close']) 46 | btc_df.set_index('date', inplace=True) 47 | print(btc_df.head()) 48 | # export DataFrame to csv 49 | btc_df.to_csv('btc_bars3.csv') 50 | -------------------------------------------------------------------------------- /buy_bnb.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from binance.client import Client 4 | 5 | # init 6 | api_key = os.environ.get('binance_api') 7 | api_secret = os.environ.get('binance_secret') 8 | 9 | client = Client(api_key, api_secret) 10 | 11 | 12 | # functions 13 | 14 | def topup_bnb(min_balance: float, topup: float): 15 | ''' Top up BNB balance if it drops below minimum specified balance ''' 16 | bnb_balance = client.get_asset_balance(asset='BNB') 17 | bnb_balance = float(bnb_balance['free']) 18 | if bnb_balance < min_balance: 19 | qty = round(topup - bnb_balance, 5) 20 | print(qty) 21 | order = client.order_market_buy(symbol='BNBUSDT', quantity=qty) 22 | return order 23 | return False 24 | 25 | 26 | # example 27 | min_balance = 1.0 28 | topup = 2.5 29 | order = topup_bnb(min_balance, topup) 30 | -------------------------------------------------------------------------------- /create_order.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from binance.client import Client 4 | from binance.enums import * 5 | from binance.exceptions import BinanceAPIException, BinanceOrderException 6 | 7 | # init 8 | api_key = os.environ.get('binance_api') 9 | api_secret = os.environ.get('binance_secret') 10 | 11 | client = Client(api_key, api_secret) 12 | 13 | ## main 14 | 15 | # create order 16 | 17 | # make a test order first. This will raise an exception if the order is incorrect. 18 | buy_order_limit = client.create_test_order( 19 | symbol='ETHUSDT', 20 | side='BUY', 21 | type='LIMIT', 22 | timeInForce='GTC', 23 | quantity=100, 24 | price=200) 25 | 26 | buy_order = client.create_test_order(symbol='ETHUSDT', side='BUY', type='MARKET', quantity=100) 27 | 28 | # create a real order if the test orders did not raise an exception 29 | try: 30 | buy_limit = client.create_order( 31 | symbol='ETHUSDT', 32 | side='BUY', 33 | type='LIMIT', 34 | timeInForce='GTC', 35 | quantity=100, 36 | price=200) 37 | 38 | # same order but with helper function 39 | buy_limit = client.order_limit_buy(symbol='ETHUSDT', quantity=100, price=200) 40 | 41 | # market order using a helper function 42 | market_order = client.order_market_sell(symbol='ETHUSDT', quantity=100) 43 | 44 | # cancel previous orders 45 | cancel = client.cancel_order(symbol='ETHUSDT', orderId=buy_limit['orderId']) 46 | except BinanceAPIException as e: 47 | # error handling goes here 48 | print(e) 49 | except BinanceOrderException as e: 50 | # error handling goes here 51 | print(e) 52 | 53 | # using binance constants - the library has hard coded commonly used strings 54 | # https://python-binance.readthedocs.io/en/latest/constants.html# 55 | 56 | # this order uses required strings such as 'BUY' and 'MARKET' which are prone to spelling errors 57 | buy_order = client.create_test_order(symbol='ETHUSDT', side='BUY', type='MARKET', quantity=100) 58 | 59 | # binance constants can be used instead 60 | buy_order = client.create_test_order(symbol='ETHUSDT', side=SIDE_BUY, type=ORDER_TYPE_MARKET, quantity=100) 61 | -------------------------------------------------------------------------------- /indicators.py: -------------------------------------------------------------------------------- 1 | import btalib 2 | import pandas as pd 3 | 4 | # load DataFrame 5 | btc_df = pd.read_csv('btc_bars3.csv', index_col=0) 6 | # btc_df.set_index('date', inplace=True) 7 | btc_df.index = pd.to_datetime(btc_df.index, unit='ms') 8 | 9 | # calculate 20 moving average using Pandas 10 | btc_df['20sma'] = btc_df.close.rolling(20).mean() 11 | print(btc_df.tail(5)) 12 | 13 | # calculate just the last value for the 20 moving average 14 | mean = btc_df.close.tail(20).mean() 15 | 16 | # get the highest closing price in 2020 17 | max_val = btc_df.close['2020'].max() 18 | 19 | print(mean) 20 | print(max_val) 21 | 22 | # technical indicators using bta-lib 23 | 24 | # sma 25 | sma = btalib.sma(btc_df.close) 26 | print(sma.df) 27 | 28 | # create sma and attach as column to original df 29 | btc_df['sma'] = btalib.sma(btc_df.close, period=20).df 30 | print(btc_df.tail()) 31 | 32 | # calculate rsi and macd 33 | rsi = btalib.rsi(btc_df, period=14) 34 | macd = btalib.macd(btc_df, pfast=20, pslow=50, psignal=13) 35 | 36 | print(rsi.df) 37 | print(macd.df) 38 | 39 | # access last rsi value 40 | print(rsi.df.rsi[-1]) 41 | 42 | # join the rsi and macd calculations as columns in original df 43 | btc_df = btc_df.join([rsi.df, macd.df]) 44 | print(btc_df.tail()) 45 | -------------------------------------------------------------------------------- /latest_btc_price.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from binance.client import Client 4 | 5 | # init 6 | api_key = os.environ.get('binance_api') 7 | api_secret = os.environ.get('binance_secret') 8 | 9 | client = Client(api_key, api_secret) 10 | 11 | ## main 12 | 13 | # get latest price from Binance API 14 | btc_price = client.get_symbol_ticker(symbol='BTCUSDT') 15 | # print full output (dictionary) 16 | print(btc_price) 17 | # print just the price 18 | print(btc_price['price']) 19 | -------------------------------------------------------------------------------- /pair_trading_percent.py: -------------------------------------------------------------------------------- 1 | import os 2 | from time import sleep 3 | 4 | import pandas as pd 5 | from binance import ThreadedWebsocketManager 6 | from binance.client import Client 7 | 8 | # init 9 | api_key = os.environ.get('binance_api') 10 | api_secret = os.environ.get('binance_secret') 11 | client = Client(api_key, api_secret) 12 | price = {'BTCUSDT': pd.DataFrame(columns=['date', 'price']), 'error':False} 13 | 14 | 15 | def btc_pairs_trade(msg): 16 | ''' define how to process incoming WebSocket messages ''' 17 | if msg['e'] != 'error': 18 | price['BTCUSDT'].loc[len(price['BTCUSDT'])] = [pd.Timestamp.now(), float(msg['c'])] 19 | else: 20 | price['error'] = True 21 | 22 | 23 | # init and start the WebSocket 24 | bsm = ThreadedWebsocketManager() 25 | bsm.start() 26 | bsm.start_symbol_ticker_socket(symbol='BTCUSDT', callback=btc_pairs_trade) 27 | 28 | 29 | ## main 30 | while len(price['BTCUSDT']) == 0: 31 | # wait for WebSocket to start streaming data 32 | sleep(0.1) 33 | 34 | sleep(300) 35 | 36 | while True: 37 | # error check to make sure WebSocket is working 38 | if price['error']: 39 | # stop and restart socket 40 | bsm.stop() 41 | sleep(2) 42 | bsm.start() 43 | price['error'] = False 44 | else: 45 | df = price['BTCUSDT'] 46 | start_time = df.date.iloc[-1] - pd.Timedelta(minutes=5) 47 | df = df.loc[df.date >= start_time] 48 | max_price = df.price.max() 49 | min_price = df.price.min() 50 | 51 | if df.price.iloc[-1] < max_price * 0.95: 52 | try: 53 | order = client.futures_create_order(symbol='ETHUSDT', side='SELL', type='MARKET', quantity=100) 54 | break 55 | except Exception as e: 56 | print(e) 57 | 58 | elif df.price.iloc[-1] > min_price * 1.05: 59 | try: 60 | order = client.futures_create_order(symbol='ETHUSDT', side='BUY', type='MARKET', quantity=100) 61 | break 62 | except Exception as e: 63 | print(e) 64 | 65 | sleep(0.1) 66 | 67 | 68 | # properly stop and terminate WebSocket 69 | bsm.stop() 70 | -------------------------------------------------------------------------------- /pair_trading_price.py: -------------------------------------------------------------------------------- 1 | import os 2 | from time import sleep 3 | 4 | import pandas as pd 5 | from binance import ThreadedWebsocketManager 6 | from binance.client import Client 7 | 8 | # init 9 | api_key = os.environ.get('binance_api') 10 | api_secret = os.environ.get('binance_secret') 11 | client = Client(api_key, api_secret) 12 | price = {'BTCUSDT': None, 'error':False} 13 | 14 | 15 | def btc_pairs_trade(msg): 16 | ''' define how to process incoming WebSocket messages ''' 17 | if msg['e'] != 'error': 18 | price['BTCUSDT'] = float(msg['c']) 19 | else: 20 | price['error'] = True 21 | 22 | 23 | # init and start the WebSocket 24 | bsm = ThreadedWebsocketManager() 25 | bsm.start_symbol_ticker_socket(symbol='BTCUSDT', callback=btc_pairs_trade) 26 | bsm.start() 27 | 28 | 29 | ## main 30 | while not price['BTCUSDT']: 31 | # wait for WebSocket to start streaming data 32 | sleep(0.1) 33 | 34 | while True: 35 | # error check to make sure WebSocket is working 36 | if price['error']: 37 | # stop and restart socket 38 | bsm.stop() 39 | sleep(2) 40 | bsm.start() 41 | price['error'] = False 42 | else: 43 | if price['BTCUSDT'] > 10000: 44 | try: 45 | order = client.order_market_buy(symbol='ETHUSDT', quantity=100) 46 | break 47 | except Exception as e: 48 | print(e) 49 | 50 | sleep(0.1) 51 | 52 | 53 | bsm.stop() 54 | -------------------------------------------------------------------------------- /readme.rst: -------------------------------------------------------------------------------- 1 | =============================================================== 2 | Binance Python API – A Step-by-Step Guide - AlgoTrading101 Blog 3 | =============================================================== 4 | 5 | This is the code used in `Binance Python API – A Step-by-Step Guide `_ published on the Algotrading101 Blog 6 | 7 | ** The code and article were updated on June 28, 2021 to work with the latest version of Python-Binance (v0.7.10) 8 | ----------------- 9 | Table of Contents 10 | ----------------- 11 | 12 | * `What is the Binance API? `_ 13 | * `Why should I use the Binance API? `_ 14 | * `Why shouldn’t I use the Binance API? `_ 15 | * `What are the alternatives to using the Binance API? `_ 16 | * `Are there any Python libraries available for the Binance API? `_ 17 | * `How do I get started with the Binance API? `_ 18 | * `Does Binance offer a demo account? `_ 19 | * `How do I retrieve my account balance using the Binance API? `_ 20 | * `How can I retrieve the latest price for Bitcoin? `_ 21 | * `How can I get Bitcoin’s historical price data in CSV format? `_ 22 | * `Should I trade futures or spot? What is the difference? `_ 23 | * `How to access technical indicators such as the 20 SMA? `_ 24 | * `How to fire an order for Ethereum using the Binance API? `_ 25 | * `How to implement a stop loss or take profit using the Binance API? `_ 26 | * `How to use Binance Coin (BNB) for discounted trading commissions? `_ 27 | * `How to execute a trade on ETH when BTC hits a certain price? `_ 28 | * `How to execute an ETH trade when BTC moves 5% in the last 5 minutes? `_ 29 | * `Final Thoughts `_ 30 | 31 | ------------ 32 | Requirements 33 | ------------ 34 | 35 | * `python `_ >= 3.4+ 36 | * `python_binance `_ (tested to work with >= 0.7.10 ) 37 | * `bta_lib `_ (tested to work with >= 1.0.0 ) 38 | * `pandas `_ (tested to work with >= 1.0.3 ) 39 | 40 | ----------- 41 | Author Info 42 | ----------- 43 | 44 | :author: Jignesh Davda 45 | :author page: https://algotrading101.com/learn/author/jdavda/ 46 | :published: 2020-06-30 47 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | python_binance==0.7.10 2 | bta_lib==1.0.0 3 | pandas==1.0.3 4 | -------------------------------------------------------------------------------- /stop_loss_order.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from binance.client import Client 4 | from binance.enums import * 5 | from binance.exceptions import BinanceAPIException, BinanceOrderException 6 | 7 | # init 8 | api_key = os.environ.get('binance_api') 9 | api_secret = os.environ.get('binance_secret') 10 | 11 | client = Client(api_key, api_secret) 12 | 13 | ## main 14 | 15 | try: 16 | order = client.create_oco_order( 17 | symbol='ETHUSDT', 18 | side='SELL', 19 | quantity=100, 20 | price=250, 21 | stopPrice=150, 22 | stopLimitPrice=150, 23 | stopLimitTimeInForce='GTC') 24 | 25 | except BinanceAPIException as e: 26 | # error handling goes here 27 | print(e) 28 | except BinanceOrderException as e: 29 | # error handling goes here 30 | print(e) 31 | 32 | 33 | # use exchange info to confirm order types 34 | info = client.get_symbol_info('ETHUSDT') 35 | print(info['orderTypes']) 36 | -------------------------------------------------------------------------------- /websocket_stream.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | from binance import ThreadedWebsocketManager 4 | 5 | 6 | btc_price = {'error':False} 7 | 8 | def btc_trade_history(msg): 9 | ''' define how to process incoming WebSocket messages ''' 10 | if msg['e'] != 'error': 11 | print(msg['c']) 12 | 13 | btc_price['last'] = msg['c'] 14 | btc_price['bid'] = msg['b'] 15 | btc_price['last'] = msg['a'] 16 | btc_price['error'] = False 17 | else: 18 | btc_price['error'] = True 19 | 20 | 21 | # init and start the WebSocket 22 | bsm = ThreadedWebsocketManager() 23 | bsm.start() 24 | 25 | # subscribe to a stream 26 | bsm.start_symbol_ticker_socket(callback=btc_trade_history, symbol='BTCUSDT') 27 | 28 | # put script to sleep to allow WebSocket to run for a while 29 | # this is just for example purposes 30 | sleep(2) 31 | 32 | # add a second stream 33 | bsm.start_symbol_ticker_socket(callback=btc_trade_history, symbol='ETHUSDT') 34 | 35 | # put script to sleep to allow WebSocket to run for a while 36 | # this is just for example purposes 37 | sleep(2) 38 | 39 | # stop websocket 40 | bsm.stop() 41 | 42 | sleep(2) 43 | # display more info about the various websocket streams 44 | help(ThreadedWebsocketManager) 45 | --------------------------------------------------------------------------------