├── .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 |
--------------------------------------------------------------------------------