币安Python API简明教程

Binance API 是一种允许你通过 Python 或其他几种编程语言连接到 Binance 服务器的方法。 有了它,可以自动化你的交易。

币安Python API简明教程
一键发币: SOL | BNB | ETH | BASE | Blast | ARB | OP | POLYGON | AVAX | FTM | OK

Binance API 是一种允许你通过 Python 或其他几种编程语言连接到 Binance 服务器的方法。 有了它,可以自动化你的交易。

更具体地说,币安有一个 RESTful API,它使用 HTTP 请求发送和接收数据。 此外,还有一个可用的 WebSocket,可以实现报价和帐户更新等数据流。

2、我为什么应该使用币安 API?

币安已成为加密货币交易领域的市场领导者。 根据 coinmarketcap.com,它目前在比特币交易量中排名第一,并且在许多其他货币中排名也很高。

佣金非常有竞争力,你可能很难找到另一个费用更低的交易所。

最后,币安拥有良好的安全记录。 币安被黑客攻击的例子很少,但由于业务的性质,所有交易所都容易受到黑客攻击。

最重要的是,当币安在 2019 年遭到黑客攻击,超过 4000 万美元被盗时,币安覆盖了受影响的用户。

3、为什么我不应该使用币安 API?

虽然安全性是币安交易所的一大优势,但根据你的需求,还有更好的选择。

如果你的主要兴趣是交易比特币,那么最好与盈透证券等受监管经纪商交易比特币期货。

受监管经纪人的好处是他们有适当的保险计划来保护消费者。

如果你不喜欢期货交易,有几家受监管的经纪商提供加密货币差价合约交易,这可能是一个不错的选择。

应该指出的是,这些选项的产品范围并不像币安那样广泛。 在大多数情况下,交易费用要高得多。

币安 API 交易的另一个挑战是 API 经常发生变化。

API 的改变通常是一件好事。 这意味着交易所正在尝试更新和改进其基础设施(大多数时候)。

然而,这需要密切关注币安的 API 公告并根据需要更新我们的交易算法。 并非所有更改都会导致我们的代码被破坏,但其中一些更改肯定会导致代码被破坏。

也有停电的情况。 2020 年底,币安大约每月将其 API 离线一次,每次几个小时以进行计划更新。 这需要算法交易者进行手动干预和额外的头寸管理。

2021 年初,在加密货币价格飙升的背景下,由于新用户的涌入和交易量的急剧上升,币安在波动时期经历了中断。

币安首席执行官赵长鹏(更广为人知的名字是 CZ)曾多次评论称,在加密货币等不断发展的行业中,中断是正常的,用户应该预期这种情况将来可能会再次发生。

4、使用币安 API 的替代方案有哪些?

Coinmarketcap 的数据库中列出了 300 多家交易所,其中许多都提供 API。 所以并不缺乏替代品。

在其名单中脱颖而出的知名交易所包括 Coinbase、Kraken、Bitfinex、Bitstamp 和 Bittrex。

期货交易者可能还想看看 Bitmex,这是一家颇受欢迎的交易所,佣金具有竞争力。 他们甚至向您支付某些订单类型的费用,而不是收取交易费。

5、是否有可用于 Binance API 的 Python 库?

有几个可用的第三方库,最流行的是 python-binance。

关于这个库如何成为币安最受欢迎的 Python 库,有一个有趣的故事。

当币安于 2017 年推出时,他们举办了一场竞赛,看看谁能为各种不同的编程语言提出最好的库。 获奖者每人奖励 1000 币安币 (BNB)。

比赛时,BNB 的交易价格低于 2 美元,但在 2021 年上半年飙升至 691 美元的高位!

Python 类别有一些不错的参赛作品,但 python-binance 最终获胜。

这是一个聪明的方法,可以确保最好的开发人员努力创建一个好的库。

另一个流行的库是 CCXT。 该库支持一百多种不同的交换,并且可用于许多不同的编程语言。

第三个可能不太为人所知的选项是 Binance Connector,它看起来可能是一个官方库,因为它托管在 Binance 的 Github 页面下。 Binance API 文档中还提供了建议和链接。

如果你计划在多个交易所进行交易,或者希望灵活地切换到另一个交易所,而无需完全重新学习另一个库,那么 CCXT 是一个不错的选择。

Python Binance 的优点是有很多人使用它,因此很容易获得其他用户的支持和帮助。

最后,币安连接器似乎经常更新,并且是一个很棒的库。 然而,缺点是它的学习曲线可能很陡峭,因为没有很多可用的文档或使用示例。

6、如何开始使用币安 API?

第一步是创建币安账户, 只需输入你的电子邮件并创建密码:

系统会询问你是否要启用双因素身份验证以提高安全性。 我们强烈建议你这样做。 如果以前从未使用过,则需要安装 Google Authenticator。

6.1 获取API密钥

登录币安账户后,点击屏幕右上角的个人资料图标。 从那里选择 API 管理:

接下来,系统会要求你为 API 密钥创建标签。 如果计划创建多个密钥,最好在此处使用描述性名称,以便轻松区分。

如果你启用了双因素身份验证,此时系统会要求你再次进行身份验证。

币安将向你发送一封电子邮件以确认 API 密钥创建。 单击确认电子邮件中的确认链接以继续。

此时应创建你的 API 密钥。 请注意,这是你的 API 秘密唯一一次被泄露。 如果离开此屏幕,你将无法再次看到它。

在这种情况下,你将需要删除 API 密钥并通过创建新密钥重新开始。

像使用任何密码一样保护你的 API 详细信息,因为任何人只要能够掌握此信息,就可以访问你的帐户。

在继续之前,我们需要看一下这里的一些设置。

默认情况下,“只读”选项处于选中状态,你可能无法取消选中它。

这允许 API 读取你的帐户详细信息,并且默认情况下处于启用状态。 也许这有点误导,因为它包含术语“仅”,但你仍然可以在选中此选项的情况下执行其他操作。

还有一个选项可以启用交易、启用提款和启用未来。

如果你仍在测试 API,那么不选中这些可能是个好主意。 如果你准备好开始交易,请勾选“启用交易”框,如果计划交易期货,请勾选“启用期货”框。

对于某些人来说,此处不会显示“启用期货”框。 这意味着该账户不是为交易期货而设置的。

注意:如果显示“启用期货”框,你仍应先设置您的期货账户,然后再尝试创建 API 密钥(如果打算交易期货)。 否则可能会导致API认证错误。

如果你的账户尚未启用期货交易,则可以轻松设置它。 在币安主登录页面中,单击顶部菜单栏中的衍生品选项。

从那里,点击期货,你将进入期货交易屏幕。 该页面上应该有一个开设期货账户的选项。

如果计划从 Python 交易脚本中提款,则需要启用它。 为此,你必须指定脚本访问 API 的 IP 地址。 这是出于安全目的。

如果你打算从 AWS 等虚拟专用服务器运行脚本,这应该不是什么大问题。 但是,如果你从本地计算机运行脚本,则可能会遇到问题,因为大多数互联网服务提供商不提供静态 IP 地址。

有一些第三方解决方案(例如 noip.com)提供了一种解决没有静态 IP 的方法。

6.2 安装 python-binance 库

安装 python-binance 库的最简单方法是使用 pip。 在命令行中,只需键入:

pip install python-binance

6.3 保护你的 API 密钥

我们建议将你的 API 密钥存储为环境变量。 这样,如果你将代码上传到 GitHub 或将其发送给某人,就不会面临泄露凭据的风险。

这可以通过命令提示符来完成。 以下是适用于 Windows 用户的语法。

set binance_api=your_api_key_here
set binance_secret=your_api_secret_here

你可以通过启动 Python 从命令提示符验证密钥是否已保存。 这是一个例子:

这就是使用终端在 Mac 或 Linux 环境中存储环境变量的方法。

句法:

export binance_api="your_api_key_here"
export binance_secret="your_api_secret_here"

示例:

稍后我们可以使用 os 库从 Python 交易脚本中检索这些值。

6.3 币安提供模拟账户吗?

在使用 Binance API 进行实时交易之前,可以选择在 Binance API 测试网上测试你的 Python 交易脚本。

首先访问 Binance Spot 测试网络网站,可以在这里找到它。

从那里,即使你已经拥有 Binance.com 帐户,也必须创建一个帐户。 我们只看到了使用 GitHub 帐户登录的选项。

登录后,你必须创建新的 API 密钥。 这些密钥将与上一步中创建的密钥分开,并且仅用于访问你的模拟帐户。

选择生成 HMAC 密钥的选项。 在下一步中,输入密钥的描述性名称:

单击“生成”后,你将进入显示密钥的屏幕。 如果离开此屏幕,你将无法再次访问他们的密钥,并且必须重新开始。

使用密钥进行设置后,实时 API 中的所有端点将与测试网 API 中的相同。 唯一的区别是你必须使用不同的 URL 来访问测试网。

在撰写本文时,我们在所有示例中使用的 python-binance 库不支持测试网络。 不过,我们将在下一步中讨论解决方法。

请注意,测试网络帐户通常会在每个月初被删除。 任何未平仓交易都将被清除。 有关 Spot 测试网络的更多详细信息可以在您创建密钥的同一页面上找到。

7、如何使用币安 API 检索我的账户余额?

现在我们已经安装了库并获得了 API 密钥,是时候测试与 API 的连接了。 我们将启动一个客户端并检查详细说明不同帐户余额的四个功能。

import os

from binance.client import Client

我们从导入开始。 我们需要 python-binance 库和 os 库中的 Client 类来检索我们存储为环境变量的 API 密钥。

# init
api_key = os.environ.get('binance_api')
api_secret = os.environ.get('binance_secret')

接下来,我们将 API 密钥和秘密存储到本地变量中。

client = Client(api_key, api_secret)

最后,我们初始化客户端并传递 API 密钥和秘密。 此时我们已准备好开始访问 API。

不幸的是,python-binance 库不支持前面讨论的演示环境。 但是,我们可以通过手动更改库中的 API 端点 URL 来进行连接,如下所示:

client.API_URL = 'https://testnet.binance.vision/api'

如果你决定从演示 API 开始,请确保在初始化客户端时传递测试网络 API 凭据,而不是实时 API 密钥。

# get balances for all assets & some account information
print(client.get_account())

上述代码将打印平台上可用的每种货币的所有帐户详细信息。 它还将提供一些其他信息,例如当前佣金率以及您的帐户是否启用保证金交易。

这可能是有点太多的信息。 如果我们只对 BTC 余额感兴趣,我们可以使用另一个端点。

# get balance for a specific asset only (BTC)
print(client.get_asset_balance(asset='BTC'))

如果想要了解其他资产的余额详细信息,只需将 BTC 替换为你想要的资产即可。

# get balances for futures account
print(client.futures_account_balance())

期货账户的账户余额与主余额是分开的,因此需要不同的端点。

同样,保证金账户详细信息也分开。 你可以通过以下方式访问你的保证金账户。 请注意,如果尚未激活保证金账户,则会出现例外情况。

# get balances for margin account
print(client.get_margin_account())

如果你不熟悉保证金交易,可以查看币安指南:什么是保证金交易以获取更多详细信息,并查看币安保证金交易指南以获取设置说明。

8、如何检索比特币的最新价格?

有多种方法可以获得比特币的最新价格。 最简单的一种涉及使用 get_symbol_ticker函数。

如果想要另一种资产,你可以在此处传入任何代码,而不是 BTCUSDT

# get latest price from Binance API
btc_price = client.get_symbol_ticker(symbol="BTCUSDT")
# print full output (dictionary)
print(btc_price)

上面的代码将打印出包含符号和价格的字典。 这是一个示例输出 –

{'symbol': 'BTCUSDT', 'price': '9678.08000000'}

我们可以按如下方式访问价格:

print(btc_price["price"])

在实时 Python 交易脚本中,我们可能需要所交易资产的最新价格信息。 幸运的是,有一个比不断向 API 发出请求更好的解决方案。 它涉及使用 Binance WebSocket。

9、使用 WebSocket 获取最新的比特币价格

Binance WebSocket 要求我们只发送一次命令来打开一个流,然后数据将随着价格更新而自动传输。

from time import sleep

from binance import ThreadedWebsocketManager

我们需要导入 ThreadedSocketManager 来使用这个函数,以及 time 模块中的 sleep 函数。

btc_price = {'error':False}

接下来,我们将创建一个字典来保存最新的价格数据,并让我们知道 websocket 是否存在问题。

def btc_trade_history(msg):
    ''' define how to process incoming WebSocket messages '''
    if msg['e'] != 'error':
	print(msg['c'])
	btc_price['last'] = msg['c']
	btc_price['bid'] = msg['b']
	btc_price['last'] = msg['a']
	btc_price['error'] = False
    else:
        btc_price['error'] = True

然后,我们将创建一个函数,告诉套接字管理器在收到新数据时要做什么。

现在,我们只将最后的收盘价打印到屏幕上。

我们还将一些项目存储到之前创建的字典文件中。 这允许我们访问函数外部的数据,这就是你通常从主交易脚本访问 websocket 数据的方式。

除了最新的价格、出价和要价之外,我们还内置了错误检查。这将使我们知道 Binance WebSocket 是否存在错误,在这种情况下我们需要重新启动它。

后一个涉及 websocket 的示例扩展了错误检查部分。

你可能已经注意到,币安不使用完整的变量名称。 IE 收盘价通过 websocket 传递到名为“c”而不是“close”的变量中。 币安这样做可能是为了保持消息的整体大小最小,以提高通信速度。

如果你尝试编写新的 Websocket 连接并且不确定变量代表什么,请查看 Binance API 文档。 他们对 websocket 消息的每个组件的用途都有详细的解释。

# init and start the WebSocket
bsm = ThreadedWebsocketManager()
bsm.start()

下一步是初始化套接字管理器。 当我们这样做时,库将创建一个我们在上面的代码片段中启动的新线程。

# subscribe to a stream
bsm.start_symbol_ticker_socket(callback=btc_trade_history, symbol='BTCUSDT')

我们将调用 start_symbol_ticker_socket,它与我们之前讨论的 API 的 get_symbol_ticker 函数具有类似的输出。

我们需要传递一个符号,在本例中是 BTCUSDT。 我们还指定它在每次新消息传入时调用我们的自定义 btc_trade_history 函数。

如果按照步骤操作,运行上述代码,你应该会在屏幕上看到一系列价格。 它看起来应该类似于币安网页上现货交易部分下的交易历史框。

在实时 Python 交易脚本中,您将从函数外部的字典文件访问数据,而不是从函数将数据打印到屏幕。

Binance 有多个 websocket 流,我们可以轻松添加更多。

bsm.start_symbol_ticker_socket(callback=btc_trade_history, symbol='ETHUSDT')

上面的代码片段订阅了 ETHUSDT 的股票价格。 我们将回调保留为 btc_trade_history。 这意味着当 ETHUSDT 的新消息到达时,它将由我们创建的相同 btc_trade_history 函数处理。

这仅用于示例目的,以展示如何轻松添加更多流。 如果需要,您可以选择为其他流创建单独的函数。

使用完 WebSocket 后,请使用以下语法正确终止它:

# stop websocket
bsm.stop()

WebSocket可以传送各种数据。 要全面了解可用内容,请在 Python 终端中键入以下内容:

help(ThreadedWebsocketManager)

这将列出所有可用的不同方法,并提供有关返回数据的一些信息。

以下是 start_symbol_ticker_socket 的示例:

正如你所看到的,它提供了简短的描述、有关该函数的币安官方文档的链接以及有关返回数据的一些详细信息。

除了检查文档之外,这是确定 msg['b'] 返回最佳出价的另一种方法。

10、如何获取 CSV 格式的比特币历史价格数据?

我们将从 Binance API 请求历史比特币价格数据,然后概述将数据保存到 CSV 文件的四个选项。

我们想要尽可能追溯的数据。 幸运的是,库中有一个函数可以让我们确定第一个可用的价格点。

# valid intervals - 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M

# get timestamp of earliest date data is available
timestamp = client._get_earliest_valid_timestamp('BTCUSDT', '1d')
print(timestamp)

在上面的代码片段中,我们调用了 ._get_earliest_valid_timestamp 函数,并传入 BTCUSDT 作为我们的交易品种,并传入 1d 作为我们的时间范围。 输出保存到变量中。

# request historical candle (or klines) data
bars = client.get_historical_klines('BTCUSDT', '1d', timestamp, limit=1000)

接下来,我们调用历史数据。 我们再次需要传递符号和变量。 此外,还需要一个开始日期,我们为此使用了时间戳变量。

最后,该函数默认调用最后500点数据。 最大值为 1000,因此我们将限制增加到最大值。

在后台,该端点将不断循环查询API,一次收集1000个价格点,直到返回从起点到今天的所有数据。

为了对 API“友好”,每三次调用后都会内置一个睡眠函数。 因此,如果您从一开始就寻找 1 分钟的数据,这可能需要一段时间。

币安于 2017 年夏季开始运营,因此这可能是最早可用的价格点。

以下是根据 Binance API 文档返回的数据的定义:

现在我们有了日期,让我们通过四种不同的选项将其保存到文件中。

# option 1 - save to file using json method
with open('btc_bars.json', 'w') as e:
    json.dump(bars, e)

第一个涉及使用 JSON 库。 这将维护数据的结构,即列表的列表。 如果你想保留这个结构,这就是你要走的路。 确保导入 json。

# option 2 - save as CSV file using the csv writer library
with open('btc_bars.csv', 'w', newline='') as f:
	wr = csv.writer(f)
    for line in bars:
        wr.writerow(line)

第二种方法使用 csv writer 将列表保存为 CSV 文件。 确保导入 csv。

# option 3 - save as CSV file without using a library. 
with open('btc_bars2.csv', 'w') as d:
    for line in bars:
        d.write(f'{line[0]}, {line[1]}, {line[2]}, {line[3]}, {line[4]}\n')

第三个选项不使用任何库。 我们创建了一个 f 字符串,它是 Python 3 及更高版本的本机函数。

这里有更多的灵活性。 我们利用了它,只保存了前五列:日期、开盘价、最高价、最低价、收盘价。

或者,如果不需要的话,你也可以删除附加列,如下所示:

# delete unwanted data - just keep date, open, high, low, close
for line in bars:
    del line[5:]

最后一个选项是利用 Pandas 的导出到 CSV 功能。 如果你打算将数据保存在 DataFrame 中,那么使用此选项是有意义的。

# option 4 - create a Pandas DataFrame and export to CSV
btc_df = pd.DataFrame(bars, columns=['date', 'open', 'high', 'low', 'close'])
btc_df.set_index('date', inplace=True)
print(btc_df.head())

我们已将数据传递到 DataFrame 中并定义了列。 由于我们删除了一些不需要的列,因此只需要定义五个列。

这就是我们的 DataFrame 此时的样子 –

日期列已设置为索引,这使其成为时间序列索引的 DataFrame。 这样,以后根据时间范围进行操作就更容易了。 当我们将其保存为 CSV 时,它还会删除多余的不需要的索引列。

最后,我们可以将 DataFrame 导出为 CSV 文件。

# export DataFrame to csv
btc_df.to_csv('btc_bars3.csv')

11、我应该交易期货还是现货? 有什么不同?

在期货市场上,你可以签订合约以在以后购买加密货币。 这意味着如果进行交易,你并不拥有实际所有权。

事实上,大多数期货交易者从未拥有所有权。 交易期货主要是出于投机目的,尽管它是出于其他原因而设计的。

交易期货的主要优点是你可以做空自己不拥有的资产。 这对于套利和对冲策略非常有用。

期货交易的另一个方面是它是通过保证金进行的。 这意味着你只需投入部分交易价值,即可使用杠杆。

币安有一个单独的选项可以以保证金交易现货市场。 但做空数量的限制相当低,而且利息(借款成本)比交易期货高得多。

由于各种持有成本,期货价格通常与主要市场(或称为现货价格)不同。 然而,价格通常会在期货合约到期日之前趋于一致。

对于币安来说,交易期货的一大优势是交易费用比现货低很多。 因此,进行期货市场交易有很多理由。

以下是你可能不想交易期货的一些原因:

  • 你计划交易许多不同的加密货币,甚至可能相互交易——币安目前提供的期货仅限于流行的 USDT 货币对。
  • 你想拥有加密货币并可能将其存储在离线钱包中。

Binance API 使用不同的端点进行期货交易。 但如果你使用的是 python-binance 库,这些端点已在库中配置。

此外,库内的期货功能已被适当标记,以将其与现货市场区分开来。

例如,如果你进行现货交易,将使用以下函数来访问未平仓订单:

client.get_open_orders

如果交易期货,则使用:

client.futures_get_open_orders

12、如何获取20 SMA等技术指标?

有几个可用的库可以简化技术指标的计算过程。

我们已经讨论了如何将 DataFrame 导出为 CSV 文件。 你可以使用 Pandas 做很多事情,计算移动平均值就是其中之一。

这是一个例子:

import btalib
import pandas as pd

# load DataFrame
btc_df = pd.read_csv('btc_bars3.csv', index_col=0)
btc_df.set_index('date', inplace=True)
btc_df.index = pd.to_datetime(btc_df.index, unit='ms')

# calculate 20 moving average using Pandas
btc_df['20sma'] = btc_df.close.rolling(20).mean()
print(btc_df.tail(5))

在上面的代码中,我们从之前创建的 CSV 文件中加载了数据。 然后我们使用 mean()函数计算关闭列的平均值。

滚动功能允许我们设置移动平均线的周期。 这一切都被附加到现有的 DataFrame 中。 这就是结果的样子。

正如你所看到的,已使用 20 移动平均线创建了一个新柱。

假设你只需要知道目前的移动平均线在哪里。 或者截至 DataFrame 中的最后一个价格点。

我们可以使用相同的 mean()函数,并在DataFrame的最后20行上运行它,如下所示:

# calculate just the last value for the 20 moving average
mean = btc_df.close.tail(20).mean()

Pandas能做的还有很多。 我们可以轻松获取今年比特币交易的最高价格,如下:

# get the highest closing price in 2020
max_val = btc_df.close['2020'].max()

但 Pandas 无法计算其他技术指标,例如 RSI 或 MACD。 Binance API 也不提供此信息。

TA-LIB 成为流行的库已有一段时间了。 我们最近有机会测试一个新的库 - bta-lib。

这个库是由 Backtrader 的作者创建的。 他在博客上讨论了 TA-LIB 有几个指标执行不当。

此外,TA-LIB 并不是为 Python 设计的。 有一个可用的包装器,但为 Python 设计的解决方案的开销要少得多。

Bta-lib 可以使用 PIP 安装,如下所示。

pip install bta-lib

让我们尝试计算与库相同的移动平均值作为比较 -

sma = btalib.sma(btc_df.close)
print(sma.df)

我们现在有一个单独的 DataFrame,其中包含移动平均值的值。 它看起来像这样:

请注意,bta-lib 将向我们的 sma 变量返回一个对象。 要访问其中包含的 DataFrame,只需在变量名称后键入 .df 即可。

默认情况下,库使用 30 周期移动平均线。

我们可以复制之前的相同函数并计算 20 移动平均值并将其作为列附加到我们的原始 DataFrame,如下所示。

# create sma and attach as column to original df
btc_df['sma'] = btalib.sma(btc_df.close, period=20).df
print(btc_df.tail())

让我们再创建一些指标。 以下是我们如何使用 bta-lib 库计算 RSI –

rsi = btalib.rsi(btc_df, period=14)

再次返回一个包含 df 的对象。 我们可以像这样访问最后一个值。

print(rsi.df.rsi[-1])

在实际环境中,你可能只需要最后一个值。

以下是我们如何在 bta-lib 中计算比特币的 MACD。

macd = btalib.macd(btc_df, pfast=20, pslow=50, psignal=13)

最后,我们将 RSI 和 MACD 值加入到我们原始的比特币价格 DataFrame 中

# join the rsi and macd calculations as columns in original df
btc_df = btc_df.join([rsi.df, macd.df])
print(btc_df.tail())

现在我们可以从一个 DataFrame 轻松访问所有计算 –

13、如何使用币安 API 触发以太坊订单?

我们使用的库有一个功能可以让我们创建测试订单。 这是一个例子:

buy_order_limit = client.create_test_order(
    symbol='ETHUSDT',
    side='BUY',
    type='LIMIT',
    timeInForce='GTC',
    quantity=100,
    price=200)

我们可以确保我们的语法正确,而无需提交实时订单。 当您了解 API 时,这非常有用。

例如,如果我们将上面代码中的类型更改为“MARKET”,它将抛出异常。 原因是 timeInForce 和价格参数不用于市价订单。 相反,市价订单将如下所示:

buy_order = client.create_test_order(symbol='ETHUSDT', side='BUY', type='MARKET', quantity=100)

一旦你的语法正确后,只需将 create_test_order 函数替换为 create_order 函数即可。

注意:如果你按照示例进行操作,则在使用上述 ETHUSDT 限价订单代码时,如果自编写本文以来价格发生了大幅波动,你可能会收到 API 错误。 币安只允许与代币当前交易价格一定百分比范围内的订单。

由于可能存在异常,我们将把代码包装在 try/ except 块中,并从库中导入一些已定义的异常。

import os

from binance.client import Client
from binance.enums import *
from binance.exceptions import BinanceAPIException, BinanceOrderException

# init
api_key = os.environ.get('binance_api')
api_secret = os.environ.get('binance_secret')

client = Client(api_key, api_secret)

除了客户端和自定义异常之外,我们还导入了 binance.enums,我们将很快讨论。

这是订单代码块。

# create a real order if the test orders did not raise an exception

try:
    buy_limit = client.create_order(
        symbol='ETHUSDT',
        side='BUY',
        type='LIMIT',
        timeInForce='GTC',
        quantity=100,
        price=200)

except BinanceAPIException as e:
    # error handling goes here
    print(e)
except BinanceOrderException as e:
    # error handling goes here
    print(e)

订单确认将从交易所发回并存储在我们的 buy_limit 变量中。 它看起来是这样的:

它是字典格式的。 请注意,它包含一个 orderId。 我们可以使用这个 id 来取消限价订单,如下所示 –

    # cancel previous orders
    cancel = client.cancel_order(symbol='ETHUSDT', orderId=buy_limit['orderId'])

我们再次收到确认。 我们可以打印出 cancel变量来查看。

reate_order函数是下订单的主要方法。 我们可以在这里传递几个参数。

但有些命令是常见的,并且已经为它们创建了辅助函数。 他们缩短了下订单所需的代码,使事情变得更容易。 这里有一些例子:

    # same order but with helper function
    buy_limit = client.order_limit_buy(symbol='ETHUSDT', quantity=100, price=200)

    # market order using a helper function
    market_order = client.order_market_sell(symbol='ETHUSDT', quantity=100)

以下是你可能想要使用的一些辅助函数:

  • order_limit_buy()
  • order_limit_sell()
  • order_market_buy()
  • order_market_sell()
  • order_oco_buy()
  • order_ocosell()

最后两种被视为高级订单类型。 OCO 代表一个取消另一个。

一个很好的例子是当你使用止损和止盈目标时。 如果其中一个订单被命中,你会希望另一个订单被取消。

某些订单类型需要字符串常量,例如“MARKET”或“BUY”。 另一个经纪人可能会使用“MKT”,因此对于你应该使用什么并不总是有一个合乎逻辑的答案。

如果需要,你可以在文档中查找这些内容。 或者,该库将字符串硬编码为你可以使用的变量。

如果你的编码编辑器具有自动完成功能,这尤其有用,因为你可以快速确定要使用哪些参数,而无需查看文档。

以下是不使用内置变量的订单示例:

buy_order = client.create_test_order(symbol='ETHUSDT', side='BUY', type='MARKET', quantity=100)

这里使用内置变量也是同样的事情。

buy_order = client.create_test_order(symbol='ETHUSDT', side=SIDE_BUY, type=ORDER_TYPE_MARKET, quantity=100)

如果你打算走这条路,将需要前面讨论的枚举导入。

可以在此处找到所有硬编码字符串的完整列表。

14、如何使用币安API实现止损或止盈?

与股票或外汇等其他市场相比,加密货币的止损或获利方法有所不同。

原因是,对于股票,你有一个基础货币。 这通常以美元为单位。 一旦你购买了股票,你就进入了“交易”。 在某些时候,你会想要出售该股票并返回到你的基础美元货币。

对于加密货币来说,实际上不存在基础货币的概念。 当你进行交易时,是将一种货币交换为另一种货币。 系统不会将其视为你最终想要退出的“交易”。

因此,币安不允许你在主订单上添加止损和止盈。

但我们仍然可以手动实现。

为此,我们可以下 OCO 订单。 这个想法是,如果止损或止盈被触及,另一个订单应该被取消。

回到我们的 ETH 订单,以下是我们如何实施止损和获利。

try:
    order = client.create_oco_order(
        symbol='ETHUSDT',
        side='SELL',
        quantity=100,
        price=250,
        stopPrice=150,
        stopLimitPrice=150,
        stopLimitTimeInForce='GTC')

except BinanceAPIException as e:
    # error handling goes here
    print(e)
except BinanceOrderException as e:
    # error handling goes here
    print(e)

请注意,我们同时传递了 stopPricestopLimitPrice。 一旦达到 stopPrice 水平,将使用 stopLimitPrice 下限价单。 在大多数情况下,这两个参数的价格是相同的。

虽然大多数资产接受止损限价指令,但并非所有资产都接受。 在下订单之前,最好检查一下是否受支持。

你可以为此使用交易所信息端点。

# use exchange info to confirm order types
info = client.get_symbol_info('ETHUSDT')
print(info['orderTypes'])

这是响应结果——

在 orderTypes 下,它表明该资产确实接受止损限制。

这里还有其他有用的信息,例如资产是否可以保证金交易、最小数量和价格变动大小。

15、如何使用币安币(BNB)享受折扣交易佣金?

佣金加起来很快,但幸运的是,有折扣计划。

上图显示了现货市场交易的费用表和折扣。 期货交易也有折扣。

你可以根据自己的交易量或拥有的币安币数量获得折扣。

币安币或 BNB 由币安于 2017 年创建。它可以用作货币,尽管它更常见的用途可能是支付交易费用。

如果你不热衷于拥有 BNB,那么持有一点点来支付交易费用仍然是有意义的。 毕竟,任何数量的 BNB 都将使你有资格进入第一梯队。

请记住,如果使用 BNB 支付交易费用,你的余额会随着时间的推移而减少。

下面的函数可确保你的帐户中存在最低数量的 BNB,如果没有则进行充值。

def topup_bnb(min_balance: float, topup: float):
	''' Top up BNB balance if it drops below minimum specified balance '''
	bnb_balance = client.get_asset_balance(asset='BNB')
	bnb_balance = float(bnb_balance['free'])
	if bnb_balance < min_balance:
		qty = round(topup - bnb_balance, 5)
		print(qty)
		order = client.order_market_buy(symbol='BNBUSDT', quantity=qty)
		return order
	return False

交易脚本通常是循环运行的,因此定期调用上述函数将确保账户中有足够的 BNB 以获得最低折扣。

作为一个例子,我们可以这样调用上面的函数 -

min_balance = 1.0
topup = 2.5
order = topup_bnb(min_balance, topup)

这将检查至少 1 BNB 的余额。 如果 BNB 数量低于该数量,则会将账户数量增加至 2.5 BNB。

要使用BNB支付交易费用并获得折扣,需要启用它。 登录后,在币安主页上单击右上角的个人资料图标。

第一个选项应该是你的电子邮件地址,单击该地址即可进入你的仪表板。 从那里,会有一个看起来像这样的部分 –

你可以在此处启用和禁用使用 BNB 支付交易费用的选项。

16、当BTC达到一定价格时如何执行ETH交易?

在下一个示例中,当比特币价格突破 10,000 美元价格点时,我们将在以太坊下达买入订单。

我们将使用 Binance WebSocket 来跟踪比特币的价格。

import os
from time import sleep

from binance.client import Client
from binance import ThreadedWebsocketManager

# init
api_key = os.environ.get('binance_api')
api_secret = os.environ.get('binance_secret')
client = Client(api_key, api_secret)
price = {'BTCUSDT': None, 'error': False}

上面的代码看起来与之前展示如何使用 WebSocket 的示例非常相似。

def btc_pairs_trade(msg):
    ''' define how to process incoming WebSocket messages '''
    if msg['e'] != 'error':
        price['BTCUSDT'] = float(msg['c'])
    else:
        price['error'] = True

接下来,我们有回调函数。 这是所有 WebSocket 数据都将流经的地方。 我们也可以在这里编写我们的交易逻辑。

但是,由于我们需要使用 try/ except 块来输入订单,因此最好不要这样做,因为这可能会干扰库中后端发生的错误检查。

我们将启动 WebSocket 并将其定向到我们刚刚创建的 btc_pairs_trade 函数。

bsm = ThreadedWebsocketManager()
bsm.start()
bsm.start_symbol_ticker_socket(symbol='BTCUSDT', callback=btc_pairs_trade)

在开始之前,快速检查一下以确保我们有数据。

while not price['BTCUSDT']:
    # wait for WebSocket to start streaming data
    sleep(0.1)

一旦 WebSocket 用新值填充我们的价格字典,上述无限循环就会中断。

谈谈主要的贸易逻辑。

while True:
    # error check to make sure WebSocket is working
    if price['error']:
        # stop and restart socket
	bsm.stop()
	sleep(2)
	bsm.start()
        price['error'] = False

    else:
        if price['BTCUSDT'] > 10000:
            try:
                order = client.order_market_buy(symbol='ETHUSDT', quantity=100)
                break
            except Exception as e:
                print(e)

    sleep(0.1)

在这里,我们检查价格是否高于我们的参数,在本例中为 10,000 美元。 如果是这样,我们会发送市价订单来购买 ETHUSDT。

发送购买订单后,我们跳出循环,脚本完成。

不要忘记正确终止 WebSocket

bsm.stop()

17、BTC 在5分内波动5%时,如何执行 ETH 交易?

我们将再次基于比特币做出以太坊的交易决策。 尽管在本例中,我们正在寻找过去五分钟内价格变动大于 5% 的情况。

因此,如果比特币上涨超过 5%,我们就会购买以太坊。 如果跌幅超过5%,我们就会卖出以太坊。

由于我们可以在这里持有空头头寸,因此我们将进行期货交易。 在现货市场上,只有当你已经拥有该加密货币时才可以出售。

我们的导入和脚本的大部分初始部分都没有改变。 这里的主要区别是我们使用 Pandas,因为我们将从 WebSocket 传入的数据存储到 DataFrame 中。

import os
from time import sleep

import pandas as pd
from binance import ThreadedWebsocketManager
from binance.client import Client

# init
api_key = os.environ.get('binance_api')
api_secret = os.environ.get('binance_secret')
client = Client(api_key, api_secret)
price = {'BTCUSDT': pd.DataFrame(columns=['date', 'price']), 'error': False}

因此,我们导入了 Pandas 并在价格字典中创建了一个空白 DataFrame。 DataFrame 有两列,一列表示日期,或者更确切地说是时间。 另一列将保存价格。

回调函数包含从 WebSocket 数据填充 DataFrame 的代码。

def btc_pairs_trade(msg):
	''' define how to process incoming WebSocket messages '''
    if msg['e'] != 'error':
        price['BTCUSDT'].loc[len(price['BTCUSDT'])] = [pd.Timestamp.now(), float(msg['c'])]
    else:
        price['error'] = True

我们使用 .loc 函数通过最后一个索引值将数据附加到 DataFrame 中。 我们使用 DataFrame 的长度来确定索引值。

此时,我们只需插入通过使用 Pandas 的 Timestamp 函数获得的当前时间以及来自套接字流的价格。

现在我们已经创建了回调函数,我们将启动 WebSocket。

# init and start the WebSocket
bsm = ThreadedWebsocketManager()
bsm.start()
bsm.start_symbol_ticker_socket(symbol='BTCUSDT', callback=btc_pairs_trade)

我们将再次进行快速检查以确保数据正在传输。

## main
while len(price['BTCUSDT']) == 0:
	# wait for WebSocket to start streaming data
	sleep(0.1)
	
sleep(300)

在开始主要交易逻辑之前,我们将使脚本休眠五分钟,因为我们至少需要那么多数据。

while True:
	# error check to make sure WebSocket is working
    if price['error']:
        # stop and restart socket
        bsm.stop()
	sleep(2)
        bsm.start()
        price['error'] = False
    else:
		df = price['BTCUSDT']
		start_time = df.date.iloc[-1] - pd.Timedelta(minutes=5)
		df = df.loc[df.date >= start_time]
		max_price = df.price.max()
		min_price = df.price.min()

在我们的主循环中,我们首先从字典文件中获取 DataFrame 并将其分配给变量 df。 此步骤不是必需的,但可以使我们的示例中的代码更易于阅读。

接下来,我们确定五分钟前的时间。 我们可以通过从 DataFrame 中获取最后一个日期值并使用 Pandas 内置的 Timedelta 函数减去 5 分钟来实现这一点。 我们将此值赋给变量 start_time

使用 start_time 值,我们可以过滤 DataFrame 以仅包含最后五分钟的数据。

从那里,我们可以使用 Pandas 中的 max()min() 函数来查找最高和最低价格。

现在我们需要做的就是确定最后价格与最大值或最小值之间的变动是否大于 5%。

		if df.price.iloc[-1] < max_price * 0.95:
			try:
				order = client.futures_create_order(symbol='ETHUSDT', side='SELL', type='MARKET', quantity=100)
				break
			except Exception as e:
				print(e)

		elif df.price.iloc[-1] > min_price * 1.05:
			try:
				order = client.futures_create_order(symbol='ETHUSDT', side='BUY', type='MARKET', quantity=100)
				break
			except Exception as e:
				print(e)

	sleep(0.1)

如果最新价格比最后价格大 5%,我们就知道比特币正在上涨,我们将做空以太坊,作为均值回归策略的一部分。

如果最后价格比 DataFrame 中的最高价格低 5%,那么我们会执行相反的操作。

请注意,该库没有期货市场订单的辅助函数,因此我们使用类似于现货市场的 create_order 函数的方法。

再一次,如果我们的订单被执行,我们将跳出主循环并正确终止 WebSocket。

# properly stop and terminate WebSocket
bsm.stop()

然而,这一策略可能会无限期地执行。 如果您不打算在下单后爆发,那么让脚本休眠一段时间是个好主意。

否则,新订单将在每个价格变动时发送,直到 5% 的背离差距结束。

18、最后的想法

我们对币安的总体看法是,它是一家很棒的交易所。 很难击败他们的佣金,他们拥有良好的声誉,并且能够访问 WebSocket 来传输数据使生活变得更加轻松。

如果你计划使用币安 API,我们强烈建议你加入他们的 Telegram 群组。 他们有一组 API 公告,可以让你及时了解任何计划内或计划外的停机情况。

他们还有另一个小组进行一般 API 讨论。 该小组受到监管,管理员通常擅长回答任何 API 特定问题。

我们建议你进一步研究错误处理。 有些人喜欢将错误记录到日志文件中。 但是,如果你的交易策略需要精确性并且可能因 API 调用失败而受到负面影响,则可以采取其他措施。

查看我们关于盈透证券 API 的文章,其中我们讨论了使用 Telegram API 作为警报系统。 如果调用 API 时出现错误,这可能是一个提醒你的好方法。

最后,如果速度是你交易脚本的主要因素,并且你计划在虚拟服务器上运行它,请考虑使用位于亚洲的服务器。

币安使用东京以外的 AWS 服务器,因此使用同一服务器或附近的服务器将获得更快的速度。 与美国服务器相比,通过从 AWS Tokyo 运行我们的脚本,我们能够将 API 请求时间缩短近 200 毫秒。

如果您以前从未使用过 AWS,他们会为新客户提供一年的免费服务器。 此次促销适用于“微型”层的服务器,该服务器足以运行基本的 Python 脚本。

这里使用的所有代码示例都可以在 GitHub 上下载。 请随时下载它们以获得 API 的第一手体验。 请小心一些订单脚本,以免意外将市价订单发送到真实账户!


原文链接:Binance Python API – A Step-by-Step Guide

DefiPlot翻译整理,转载请标明出处

通过 NowPayments 打赏