diff --git a/.gitignore b/.gitignore index c45a744..916f084 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,5 @@ build/ ### VS Code ### .vscode/ -setup.py \ No newline at end of file +setup.py +id_rsa* \ No newline at end of file diff --git a/README.md b/README.md index e67d4b9..35afb60 100644 --- a/README.md +++ b/README.md @@ -1,143 +1,66 @@ -[TOC] +### Overview +This is an unofficial Python wrapper for the [OKX exchange v5 API](https://www.okx.com/okx-api) -### 如何使用? +If you came here looking to purchase cryptocurrencies from the OKX exchange, please go [here](https://www.okx.com/). -`python版本:>=3.9 +#### Source code +https://github.com/okxapi/python-okx +#### OKX API Telegram +https://t.me/OKXAPI +#### API trading tutorials +- Spot trading: https://www.okx.com/learn/spot-trading-with-jupyter-notebook +- Derivative trading: https://www.okx.com/learn/derivatives-trading-with-jupyter-notebook -`WebSocketAPI:autobahn.twisted>=22.10.0` +Make sure you update often and check the [Changelog](https://www.okx.com/docs-v5/log_en/) for new features and bug fixes. -#### 第一步:下载SDK,安装相关所需库 +### Features +- Implementation of all Rest API endpoints. +- Private and Public Websocket implementation +- Testnet support +- Websocket handling with reconnection and multiplexed connections -1.1 下载`python SDK` - -* 将SDK目录`Clone`或者`Download`到本地,选择使用`okx-python-sdk-api-v5`即可 - -1.2 安装所需库 - -```python -pip install requests -pip install autobahn\[twisted\] -pip install pyOpenSSL -``` - -#### 第二步:配置个人信息 - -2.1 如果还未有API,可[点击](https://www.okx.com/account/users/myApi)前往官网进行申请 - -```python -api_key = "" -secret_key = "" -passphrase = "" -``` - -#### 第三步:调用接口 - -* RestAPI - - * 运行`example.py` - - * 解开相应方法的注释传参调用各接口即可 - -* WebSocketAPI - * 参考Test文件夹下`WsPrivate`和`WsPublic`文件示例; - * 根据`公共频道`/`私有频道`选择对应`url`(如果是私有频道需要设置登陆信息),传入相应参数即可。 - - ```python - # WebSocket公共频道 - url = "wss://ws.okx.com:8443/ws/v5/public" - # WebSocket私有频道 - url = "wss://ws.okx.com:8443/ws/v5/private" - ``` - - ```python - # 公共频道 不需要登录(行情,持仓总量,K线,标记价格,深度,资金费率等) - 参考 WsPublicTest.py - - # 私有频道 需要登录(账户,持仓,订单等) - 参考 WsPrivateTest.py - ``` - -附言: - -* 如果对API尚不了解,建议参考`OKX`官方[API文档](https://www.okx.com/docs-v5/zh/) - -* 使用RestAPI的用户可以通过参考Test文件夹下的示例,设置正确的参数即可 - -* 使用WebSocketAPI的用户可以通过参考Test文件夹下的`WsPublicTest.py`和`WsPrivateTest.py`,设置正确的参数即可 - -* 若使用`WebSocketAPI`遇到问题建议参考相关链接 - - * `asyncio`、`websockets`文档/`github`: - https://docs.python.org/3/library/asyncio-dev.html - https://websockets.readthedocs.io/en/stable/intro.html - https://github.com/aaugustin/websockets - - * 关于`code=1006`: - https://github.com/Rapptz/discord.py/issues/1996 - https://github.com/aaugustin/websockets/issues/587 - - - -### How to use ? +### Quick start +#### Prerequisites `python version:>=3.9` -`WebSocketAPI: autobahn.twisted>=22.10.0` +`WebSocketAPI: websockets package advise version 6.0` -#### Step 1: Download the SDK and install the necessary libraries +#### Step 1: register an account on OKX and apply for an API key +- Register for an account: https://www.okx.com/account/register +- Apply for an API key: https://www.okx.com/account/users/myApi -1.1 Download python SDK - -- `Clone` or `Download` the SDK directory to your local directory,choose to use `okx-python-sdk-api-v5` - -1.2 Install the necessary libraries +#### Step 2: install python-okx ```python -pip install requests -pip install autobahn\[twisted\] -pip install pyOpenSSL +pip install python-okx ``` -#### Step 2: Configure Personal Information - -2.1 If you have no API,[Click here](https://www.okx.com/account/users/myApi) to the official websit to apply for the API - -2.2 Fill out all necessary informatiuon in `example.py(RestAPI)` and `websocket_example.py(WebSocketAPI)` +#### Step 3: Run examples +- Fill in API credentials in the corresponding examples ```python api_key = "" secret_key = "" passphrase = "" ``` - -#### Step 3: Call API - - RestAPI - - Run `example.py` - - Uncomment the corresponding method and then pass the arguments and call the interfaces + - For spot trading: run example/get_started_en.ipynb + - For derivative trading: run example/trade_derivatives_en.ipynb + - Tweak the value of the parameter `flag` (live trading: 0, demo trading: 1 +) to switch between live and demo trading environment - WebSocketAPI - - Open `websocket_example.py` - - According to the `public channel`/`private channel`, select the corresponding `url`, the corresponding start method, and pass in the corresponding parameters + - Run test/WsPrivateTest.py for private websocket channels + - Run test/WsPublicTest.py for public websocket channels + - Use different URLs for different environment + - Live trading URLs: https://www.okx.com/docs-v5/en/#overview-production-trading-services + - Demo trading URLs: https://www.okx.com/docs-v5/en/#overview-demo-trading-services -```python -# WebSocket public channel -url = "wss://ws.okx.com:8443/ws/v5/public?brokerId=9999" +Note -# WebSocket private channel -url = "wss://ws.okx.com:8443/ws/v5/private?brokerId=9999" -``` +- To learn more about OKX API, visit official [OKX API documentation](https://www.okx.com/docs-v5/en/) -P.S. - -- If you know little about API, advise consulting the offical [API document](https://www.okx.com/docs-v5/en/) - -- User with RestAPI can configure parameter `flag` in `example.py` in to choose to access to real trading or demo trading - -- User with WebSocketAPI can ucomment the corresponding `url` to choose to access to real trading or demo trading - -- Rest API support request by http2, you can refer to http2_example - -- If you face any questions when using `WebSocketAPI`,you can consult related link +- If you face any questions when using `WebSocketAPI`,you can consult the following links - `asyncio`、`websockets` document/`github`: @@ -153,6 +76,3 @@ P.S. https://github.com/Rapptz/discord.py/issues/1996 https://github.com/aaugustin/websockets/issues/587 ``` - - - diff --git a/http2_example.py b/http2_example.py deleted file mode 100644 index 7663d23..0000000 --- a/http2_example.py +++ /dev/null @@ -1,31 +0,0 @@ -import json -import time - -import okx.Account as Account - - -async def http2_request(request, parameters): - while 1: - begin = time.time() - if type(parameters) is list: - result = request(*parameters) - else: - result = request(**parameters) - - end = time.time() - cost = end - begin - print(f'request_cost:{cost}\nresponse_body:{json.dumps(result)}') - - -api_key = "" -secret_key = "" -passphrase = "" -# flag是实盘与模拟盘的切换参数 flag is the key parameter which can help you to change between demo and real trading. -# flag = '1' # 模拟盘 demo trading -flag = '0' # 实盘 real tradiang - -if __name__ == '__main__': - # account api - accountAPI = Account.AccountAPI(api_key, secret_key, passphrase, False, flag) - accountAPI.get_account_config() - accountAPI.get_greeks('BTC') diff --git a/test/WsPrivateTest.py b/test/WsPrivateTest.py index af12427..cf2ab5e 100644 --- a/test/WsPrivateTest.py +++ b/test/WsPrivateTest.py @@ -2,6 +2,7 @@ import time from okx.websocket.WsPrivate import WsPrivate + def privateCallback(message): print("WsPrivate subscribe callback:", message) diff --git a/test/WsPublicTest.py b/test/WsPublicTest.py index 6a56990..e0fbec5 100644 --- a/test/WsPublicTest.py +++ b/test/WsPublicTest.py @@ -1,12 +1,14 @@ import time + from okx.websocket.WsPublic import WsPublic + def publicCallback(message): print("publicCallback", message) if __name__ == '__main__': - url = "wss://wspri.coinall.ltd:8443/ws/v5/public?brokerId=9999" + url = "wss://ws.okx.com:8443/ws/v5/public" ws = WsPublic(url=url) ws.start() args = [] diff --git a/websocket_example.py b/websocket_example.py deleted file mode 100644 index 2b83cb0..0000000 --- a/websocket_example.py +++ /dev/null @@ -1,522 +0,0 @@ -import asyncio -import base64 -import datetime -import hmac -import json -import time -import zlib - -import requests -import websockets - - -def get_timestamp(): - now = datetime.datetime.now() - t = now.isoformat("T", "milliseconds") - return t + "Z" - - -def get_server_time(): - url = "https://www.okx.com/api/v5/public/time" - response = requests.get(url) - if response.status_code == 200: - return response.json()['data'][0]['ts'] - else: - return "" - - -def get_local_timestamp(): - return int(time.time()) - - -def login_params(timestamp, api_key, passphrase, secret_key): - message = timestamp + 'GET' + '/users/self/verify' - - mac = hmac.new(bytes(secret_key, encoding='utf8'), bytes(message, encoding='utf-8'), digestmod='sha256') - d = mac.digest() - sign = base64.b64encode(d) - - login_param = {"op": "login", "args": [{"apiKey": api_key, - "passphrase": passphrase, - "timestamp": timestamp, - "sign": sign.decode("utf-8")}]} - login_str = json.dumps(login_param) - return login_str - - -def partial(res): - data_obj = res['data'][0] - bids = data_obj['bids'] - asks = data_obj['asks'] - instrument_id = res['arg']['instId'] - # print('全量数据bids为:' + str(bids)) - # print('档数为:' + str(len(bids))) - # print('全量数据asks为:' + str(asks)) - # print('档数为:' + str(len(asks))) - return bids, asks, instrument_id - - -def update_bids(res, bids_p): - # 获取增量bids数据 - bids_u = res['data'][0]['bids'] - # print('增量数据bids为:' + str(bids_u)) - # print('档数为:' + str(len(bids_u))) - # bids合并 - for i in bids_u: - bid_price = i[0] - for j in bids_p: - if bid_price == j[0]: - if i[1] == '0': - bids_p.remove(j) - break - else: - del j[1] - j.insert(1, i[1]) - break - else: - if i[1] != "0": - bids_p.append(i) - else: - bids_p.sort(key=lambda price: sort_num(price[0]), reverse=True) - # print('合并后的bids为:' + str(bids_p) + ',档数为:' + str(len(bids_p))) - return bids_p - - -def update_asks(res, asks_p): - # 获取增量asks数据 - asks_u = res['data'][0]['asks'] - # print('增量数据asks为:' + str(asks_u)) - # print('档数为:' + str(len(asks_u))) - # asks合并 - for i in asks_u: - ask_price = i[0] - for j in asks_p: - if ask_price == j[0]: - if i[1] == '0': - asks_p.remove(j) - break - else: - del j[1] - j.insert(1, i[1]) - break - else: - if i[1] != "0": - asks_p.append(i) - else: - asks_p.sort(key=lambda price: sort_num(price[0])) - # print('合并后的asks为:' + str(asks_p) + ',档数为:' + str(len(asks_p))) - return asks_p - - -def sort_num(n): - if n.isdigit(): - return int(n) - else: - return float(n) - - -def check(bids, asks): - # 获取bid档str - bids_l = [] - bid_l = [] - count_bid = 1 - while count_bid <= 25: - if count_bid > len(bids): - break - bids_l.append(bids[count_bid - 1]) - count_bid += 1 - for j in bids_l: - str_bid = ':'.join(j[0: 2]) - bid_l.append(str_bid) - # 获取ask档str - asks_l = [] - ask_l = [] - count_ask = 1 - while count_ask <= 25: - if count_ask > len(asks): - break - asks_l.append(asks[count_ask - 1]) - count_ask += 1 - for k in asks_l: - str_ask = ':'.join(k[0: 2]) - ask_l.append(str_ask) - # 拼接str - num = '' - if len(bid_l) == len(ask_l): - for m in range(len(bid_l)): - num += bid_l[m] + ':' + ask_l[m] + ':' - elif len(bid_l) > len(ask_l): - # bid档比ask档多 - for n in range(len(ask_l)): - num += bid_l[n] + ':' + ask_l[n] + ':' - for l in range(len(ask_l), len(bid_l)): - num += bid_l[l] + ':' - elif len(bid_l) < len(ask_l): - # ask档比bid档多 - for n in range(len(bid_l)): - num += bid_l[n] + ':' + ask_l[n] + ':' - for l in range(len(bid_l), len(ask_l)): - num += ask_l[l] + ':' - - new_num = num[:-1] - int_checksum = zlib.crc32(new_num.encode()) - fina = change(int_checksum) - return fina - - -def change(num_old): - num = pow(2, 31) - 1 - if num_old > num: - out = num_old - num * 2 - 2 - else: - out = num_old - return out - - -# subscribe channels un_need login -async def subscribe_without_login(url, channels): - l = [] - while True: - try: - async with websockets.connect(url) as ws: - sub_param = {"op": "subscribe", "args": channels} - sub_str = json.dumps(sub_param) - await ws.send(sub_str) - print(f"send: {sub_str}") - - while True: - try: - res = await asyncio.wait_for(ws.recv(), timeout=25) - except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed) as e: - try: - await ws.send('ping') - res = await ws.recv() - print(res) - continue - except Exception as e: - print("连接关闭,正在重连……") - break - - print(get_timestamp() + res) - res = eval(res) - if 'event' in res: - continue - for i in res['arg']: - if 'books' in res['arg'][i] and 'books5' not in res['arg'][i]: - # 订阅频道是深度频道 - if res['action'] == 'snapshot': - for m in l: - if res['arg']['instId'] == m['instrument_id']: - l.remove(m) - # 获取首次全量深度数据 - bids_p, asks_p, instrument_id = partial(res) - d = {} - d['instrument_id'] = instrument_id - d['bids_p'] = bids_p - d['asks_p'] = asks_p - l.append(d) - - # 校验checksum - checksum = res['data'][0]['checksum'] - # print('推送数据的checksum为:' + str(checksum)) - check_num = check(bids_p, asks_p) - # print('校验后的checksum为:' + str(check_num)) - if check_num == checksum: - print("校验结果为:True") - else: - print("校验结果为:False,正在重新订阅……") - - # 取消订阅 - await unsubscribe_without_login(url, channels) - # 发送订阅 - async with websockets.connect(url) as ws: - sub_param = {"op": "subscribe", "args": channels} - sub_str = json.dumps(sub_param) - await ws.send(sub_str) - print(f"send: {sub_str}") - - elif res['action'] == 'update': - for j in l: - if res['arg']['instId'] == j['instrument_id']: - # 获取全量数据 - bids_p = j['bids_p'] - asks_p = j['asks_p'] - # 获取合并后数据 - bids_p = update_bids(res, bids_p) - asks_p = update_asks(res, asks_p) - - # 校验checksum - checksum = res['data'][0]['checksum'] - # print('推送数据的checksum为:' + str(checksum)) - check_num = check(bids_p, asks_p) - # print('校验后的checksum为:' + str(check_num)) - if check_num == checksum: - print("校验结果为:True") - else: - print("校验结果为:False,正在重新订阅……") - - # 取消订阅 - await unsubscribe_without_login(url, channels) - # 发送订阅 - async with websockets.connect(url) as ws: - sub_param = {"op": "subscribe", "args": channels} - sub_str = json.dumps(sub_param) - await ws.send(sub_str) - print(f"send: {sub_str}") - except Exception as e: - print(e) - print("连接断开,正在重连……") - continue - - -# subscribe channels need login -async def subscribe(url, api_key, passphrase, secret_key, channels): - while True: - try: - async with websockets.connect(url) as ws: - # login - timestamp = str(get_local_timestamp()) - login_str = login_params(timestamp, api_key, passphrase, secret_key) - await ws.send(login_str) - # print(f"send: {login_str}") - res = await ws.recv() - print(res) - - # subscribe - sub_param = {"op": "subscribe", "args": channels} - sub_str = json.dumps(sub_param) - await ws.send(sub_str) - print(f"send: {sub_str}") - - while True: - try: - res = await asyncio.wait_for(ws.recv(), timeout=25) - except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed) as e: - try: - await ws.send('ping') - res = await ws.recv() - print(res) - continue - except Exception as e: - print("连接关闭,正在重连……") - break - - print(get_timestamp() + res) - - except Exception as e: - print("连接断开,正在重连……") - continue - - -# trade -async def trade(url, api_key, passphrase, secret_key, trade_param): - while True: - try: - async with websockets.connect(url) as ws: - # login - timestamp = str(get_local_timestamp()) - login_str = login_params(timestamp, api_key, passphrase, secret_key) - await ws.send(login_str) - # print(f"send: {login_str}") - res = await ws.recv() - print(res) - - # trade - sub_str = json.dumps(trade_param) - await ws.send(sub_str) - print(f"send: {sub_str}") - - while True: - try: - res = await asyncio.wait_for(ws.recv(), timeout=25) - except (asyncio.TimeoutError, websockets.exceptions.ConnectionClosed) as e: - try: - await ws.send('ping') - res = await ws.recv() - print(res) - continue - except Exception as e: - print("连接关闭,正在重连……") - break - - print(get_timestamp() + res) - - except Exception as e: - print("连接断开,正在重连……") - continue - - -# unsubscribe channels -async def unsubscribe(url, api_key, passphrase, secret_key, channels): - async with websockets.connect(url) as ws: - # login - timestamp = str(get_local_timestamp()) - login_str = login_params(timestamp, api_key, passphrase, secret_key) - await ws.send(login_str) - # print(f"send: {login_str}") - - res = await ws.recv() - print(f"recv: {res}") - - # unsubscribe - sub_param = {"op": "unsubscribe", "args": channels} - sub_str = json.dumps(sub_param) - await ws.send(sub_str) - print(f"send: {sub_str}") - - res = await ws.recv() - print(f"recv: {res}") - - -# unsubscribe channels -async def unsubscribe_without_login(url, channels): - async with websockets.connect(url) as ws: - # unsubscribe - sub_param = {"op": "unsubscribe", "args": channels} - sub_str = json.dumps(sub_param) - await ws.send(sub_str) - print(f"send: {sub_str}") - - res = await ws.recv() - print(f"recv: {res}") - - -api_key = "" -secret_key = "" -passphrase = "" - -# WebSocket公共频道 public channels -# 实盘 real trading -# url = "wss://ws.okx.com:8443/ws/v5/public" -# 模拟盘 demo trading -# url = "wss://wspap.okx.com:8443/ws/v5/public" - -# WebSocket私有频道 private channels -# 实盘 real trading -# url = "wss://ws.okx.com:8443/ws/v5/private" -# 模拟盘 demo trading -# url = "wss://wspap.okx.com:8443/ws/v5/private" - -''' -公共频道 public channel -:param channel: 频道名 -:param instType: 产品类型 -:param instId: 产品ID -:param uly: 合约标的指数 - -''' - -# 产品频道 Instruments Channel -# channels = [{"channel": "instruments", "instType": "FUTURES"}] -# 行情频道 tickers channel -# channels = [{"channel": "tickers", "instId": "BTC-USDT"}, {"channel": "tickers", "instId": "ETH-USDT"}] -# 持仓总量频道 Open interest Channel -# channels = [{"channel": "open-interest", "instId": "BTC-USD-210326"}] -# K线频道 Candlesticks Channel -# channels = [{"channel": "candle1m", "instId": "BTC-USD-210326"}] -# 交易频道 Trades Channel -# channels = [{"channel": "trades", "instId": "BTC-USD-201225"}] -# 预估交割/行权价格频道 Estimated delivery/exercise Price Channel -# channels = [{"channel": "estimated-price", "instType": "FUTURES", "uly": "BTC-USD"}] -# 标记价格频道 Mark Price Channel -# channels = [{"channel": "mark-price", "instId": "BTC-USDT-210326"}] -# 标记价格K线频道 Mark Price Candlesticks Channel -# channels = [{"channel": "mark-price-candle1D", "instId": "BTC-USD-201225"}] -# 限价频道 Price Limit Channel -# channels = [{"channel": "price-limit", "instId": "BTC-USD-201225"}] -# 深度频道 Order Book Channel -# channels = [{"channel": "books", "instId": "BTC-USD-SWAP"}] -# 期权定价频道 OPTION Summary Channel -# channels = [{"channel": "opt-summary", "uly": "BTC-USD"}] -# 资金费率频道 Funding Rate Channel -# channels = [{"channel": "funding-rate", "instId": "BTC-USD-SWAP"}] -# 指数K线频道 Index Candlesticks Channel -# channels = [{"channel": "index-candle1m", "instId": "BTC-USDT"}] -# 指数行情频道 Index Tickers Channel -# channels = [{"channel": "index-tickers", "instId": "BTC-USDT"}] -# status频道 Status Channel -# channels = [{"channel": "status"}] -# 公共大宗交易频道 Public block trading channel -# channels = [{"channel": "public-struc-block-trades"}] -# 大宗交易行情频道 Block trading market channel -# channels = [{"channel": "block-tickers", "instId":"BTC-USDT-SWAP"}] - -''' -私有频道 private channel -:param channel: 频道名 -:param ccy: 币种 -:param instType: 产品类型 -:param uly: 合约标的指数 -:param instId: 产品ID - -''' - -# 账户频道 Account Channel -# channels = [{"channel": "account", "ccy": "BTC"}] -# 持仓频道 Positions Channel -# channels = [{"channel": "positions", "instType": "FUTURES", "uly": "BTC-USDT", "instId": "BTC-USDT-210326"}] -# 余额和持仓频道 Balance and Position Channel -# channels = [{"channel": "balance_and_position"}] -# 订单频道 Order Channel -# channels = [{"channel": "orders", "instType": "FUTURES", "uly": "BTC-USD", "instId": "BTC-USD-201225"}] -# 策略委托订单频道 Algo Orders Channel -# channels = [{"channel": "orders-algo", "instType": "FUTURES", "uly": "BTC-USD", "instId": "BTC-USD-201225"}] -# 高级策略委托订单频道 Cancel Advance Algos -# channels = [{"channel": "algo-advance", "instType": "SPOT","instId": "BTC-USD-201225","algoId":"12345678"}] -# 爆仓风险预警推送频道 -# channels = [{"channel": "liquidation-warning", "instType": "SWAP","instType": "","uly":"","instId":""}] -# 账户greeks频道 -# channels = [{"channel": "account-greeks", "ccy": "BTC"}] -# 询价频道 Inquiry channel -# channels = [{"channel": "rfqs"}] -# 报价频道 Quote channel -# channels = [{"channel": "quotes"}] -# 大宗交易频道 Block trading channel -# channels = [{"channel": "struc-block-trades"}] -# 现货网格策略委托订单频道 Consignment order channel of spot grid strategy -# channels = [{"channel": "grid-orders-spot", "instType": "ANY"}] -# 合约网格策略委托订单频道 Spot grid policy delegated order channel contract grid policy delegated order channel -# channels = [{"channel": "grid-orders-contract", "instType": "ANY"}] -# 合约网格持仓频道 Contract grid position channel -# channels = [{"channel": "grid-positions", "algoId": ""}] -# 网格策略子订单频道 Grid policy suborder channel -# channels = [{"channel": "grid-sub-orders", "algoId": ""}] -''' -交易 trade -''' - -# 下单 Place Order -# trade_param = {"id": "1512", "op": "order", "args": [{"side": "buy", "instId": "BTC-USDT", "tdMode": "isolated", "ordType": "limit", "px": "19777", "sz": "1"}]} -# 批量下单 Place Multiple Orders -# trade_param = {"id": "1512", "op": "batch-orders", "args": [ -# {"side": "buy", "instId": "BTC-USDT", "tdMode": "isolated", "ordType": "limit", "px": "19666", "sz": "1"}, -# {"side": "buy", "instId": "BTC-USDT", "tdMode": "isolated", "ordType": "limit", "px": "19633", "sz": "1"} -# ]} -# 撤单 Cancel Order -# trade_param = {"id": "1512", "op": "cancel-order", "args": [{"instId": "BTC-USDT", "ordId": "259424589042823169"}]} -# 批量撤单 Cancel Multiple Orders -# trade_param = {"id": "1512", "op": "batch-cancel-orders", "args": [ -# {"instId": "BTC-USDT", "ordId": ""}, -# {"instId": "BTC-USDT", "ordId": ""} -# ]} -# 改单 Amend Order -# trade_param = {"id": "1512", "op": "amend-order", "args": [{"instId": "BTC-USDT", "ordId": "259432767558135808", "newSz": "2"}]} -# 批量改单 Amend Multiple Orders -# trade_param = {"id": "1512", "op": "batch-amend-orders", "args": [ -# {"instId": "BTC-USDT", "ordId": "", "newSz": "2"}, -# {"instId": "BTC-USDT", "ordId": "", "newSz": "3"} -# ]} - - -loop = asyncio.get_event_loop() - -# 公共频道 不需要登录(行情,持仓总量,K线,标记价格,深度,资金费率等)subscribe public channel -loop.run_until_complete(subscribe_without_login(url, channels)) - -# 私有频道 需要登录(账户,持仓,订单等)subscribe private channel -# loop.run_until_complete(subscribe(url, api_key, passphrase, secret_key, channels)) - -# 交易(下单,撤单,改单等)trade -# loop.run_until_complete(trade(url, api_key, passphrase, secret_key, trade_param)) - -loop.close()