Releases: pybotters/pybotters
Preview v0.12.0 アップデート✨
🚀 New Features
✨ 取引所 MEXC の API 認証をサポートしました
新たに海外取引所の MEXC をサポートしました 🚀
MEXC は取り扱いが銘柄が豊富で、複数のチェーンの入出金に対応しているのが特徴の取引所です。
Private REST / WebSocket API による DataStore クラスを利用できます。
(DataStore は今後サポート予定です)
MEXC API ドキュメント:
https://mxcdevelop.github.io/APIDoc/ (v1, v2)
https://mxcdevelop.github.io/apidocs/spot_v3_en/ (v3)
このリリース現在 MEXCには v1, v2, v3 の3種類の API エンドポイントが存在しています。
v2 と v3 が Spot 取引用、v1 が Contract 取引専用となっている模様です。
WebSocket ついては Contract 用の v1 のみ存在しており、Spot 用の v2, v3 にはありません。
どれも API 仕様が若干異なっていたりするので、他の取引所より多少難しいかもしれません。
pybotters ではこれら v1 ~ v3 全ての API 認証に対応しています ✨
(ccxt は v3 には未対応です!)
サンプルコード
オープンオーダーの取得、オーダーの送信、WebSocket のサンプルコードです。
async def mexc_v3():
async with pybotters.Client(base_url="https://api.mexc.com") as client:
# Get open orders
r = await client.get(
"/api/v3/openOrders",
params={"symbol": "BTCUSDT"}
)
data = await r.json()
print(data)
# Place order
r = await client.post(
"/api/v3/order",
data={
"symbol": "BTCUSDT",
"side": "BUY",
"type": "MARKET",
"quoteOrderQty": "5",
)
data = await r.json()
print(data)
async def mexc_v1():
async with pybotters.Client(base_url="https://contract.mexc.com") as client:
# Get open orders
r = await client.get(
"/api/v1/private/order/list/open_orders/BTC_USDT",
)
data = await r.json()
print(data)
# Place order
r = await client.post(
"/api/v1/private/order/submit",
data={
"symbol": "BTC_USDT",
"price": "40000.0",
"vol": "10", # contract vol
"side": 1,
"type": 1,
"openType": 1,
}
)
data = await r.json()
print(data)
# WebSocket login authentication
ws = await client.ws_connect(
"wss://contract.mexc.com/ws",
send_json={"method": "push.personal.order", "param": {}},
)
await ws
⏫ Improvements & Bugfix
- ✨ 1つの API 情報を複数の pybotters.Client に渡たせるようになりました
こうしたとき apis が参考渡しだったので、バイト化の関係上2回目でエラーになっていましたが値渡しをするように変更することで解消しました。
apis = {"mexc": ["API_KEY", "API_SECRET"]}
try:
client1 = async with pybotters.Client(apis=apis)
client2 = async with pybotters.Client(apis=apis) # before: error, after: ok
...
finally:
await client1.close()
await client2.close()
- ✨ 空の API 情報を指定できるようになりました
apis に空辞書 {}
を指定しても、環境変数などが設定されているとそちらの apis を優先されていましたが、 {}
が優先されようになり明示的に認証なしで利用できるようになりました。
- ✨ Phemex と Bitget の initialize でエラーが表示されるようになりました (Contributed by @kunmosky1 💖)
Phemex と Bitget の DataStore で REST API の initialize が失敗したとき、エラーが表示されるようになります。
Issues
✅MEXCのAPI認証に対応する #142
✅ソースコードの文字列クォーテーションを正規化する #145
⏩試験的に既存の機能を分離し抽象化を強化する #147
✅API情報が参照渡しなので元のAPI情報を書き換えてしまう #149
✅空の辞書をapisに渡すと意図しない暗黙的な読み込みをする #151
Pull requests
✅initializeの際のエラー時(主に認証エラー)にエラーメッセージを表示するように #144
Full Changelog: v0.11.1...v0.12.0
Preview v0.11.1 リリース[Hotfix]
👾 Hotfix
- OKX Demo trading で WebSocket 認証ができない問題を修正しました
- Bitget の API 認証ができない問題を修正しました
Preview v0.11.0 リリース
🚀 New Features
✨ 取引所 OKX をサポートしました
海外主要取引所の OKX をサポートしました。
Private API 認証及び WebSocket API による DataStore クラスを利用できます 🎉
OKX API ドキュメント:
https://www.okx.com/docs-v5/en/
API 認証
pybotters に渡す API 辞書に okx
のキーで API 情報をリストで格納してください。
OKX は他の取引所と異なり API のパスフレーズが存在します。
リストの3要素目にパスフレーズを記載してください。
{
"...": ["...", "..."],
"okx": ["OKX_API_KEY", "OKX_API_SECRET", "YOUR_PASSPHRASE"]
}
Demo Trading
pybotters は OKX の Demo Trading に対応しています。
デモ版はリアルマーケットとは別の API キーの作成が必要です。
デモ版 API は okx_demo
のキーで API 辞書に格納してください。
デモ版 API を選択してリクエストを行うには、ヘッダーに {"x-simulated-trading": "1"}
を指定してください。
async def main():
apis = {"okx_demo": ["OKX_API_KEY", "OKX_API_SECRET", "YOUR_PASSPHRASE"]}
headers = {"x-simulated-trading": "1"}
async with pybotters.Client(apis=apis, headers=headers) as client:
...
DataStore のプロパティ
OKX の DataStore は WebSocket のチャンネルごとに紐づいています。
Public
(https://www.okx.com/docs-v5/en/#websocket-api-public-channel)
- instruments
- tickers
- openinterest
- candle
- trades
- estimatedprice
- markprice
- markpricecandle
- pricelimit
- books
- optsummary
- fundingrate
- indexcandle
- indextickers
Private
(https://www.okx.com/docs-v5/en/#websocket-api-private-channel)
- account
- positions
- balance_and_position (※親クラス)
- balance
- position
- orders
- ordersalgo
- algoadvance
- liquidationwarning
- accountgreeks
(※) balance_and_position WebSocket から取得するデータ構造が階層構造になっています。
そのため store.balance_and_position.balance
store.balance_and_position.position
といったように子クラスを定義しています。
親クラスには差分処理していないイベントがメッセージが格納されています。
DataStore の initialize
OKX の DataStore は以下のエンドポイントの initialize に対応しています。
- GET /api/v5/trade/orders-pending (DataStore: orders)
- GET /api/v5/trade/orders-algo-pending (DataStore: ordersalgo, algoadvance)
サンプルコード
initialize と ws_connect で全チャンネルを接続するサンプルです。
while True のループでは試しに ticker 情報を表示しています。
コメントアウトの部分はデモ版 API です。
import asyncio
import pybotters
async def main():
# headers = {"x-simulated-trading": "1"}
async with pybotters.Client(base_url="https://www.okx.com") as client:
store = pybotters.OKXDataStore()
# initialize
await store.initialize(
client.get("/api/v5/trade/orders-pending"),
client.get("/api/v5/trade/orders-algo-pending?ordType=conditional"),
)
# ws_connect
ws_public, ws_private = await asyncio.gather(
client.ws_connect(
"wss://ws.okx.com:8443/ws/v5/public",
# "wss://wspap.okx.com:8443/ws/v5/public?brokerId=9999",
send_json={
"op": "subscribe",
"args": [
{"channel": "instruments", "instType": "SWAP"},
{"channel": "tickers", "instId": "BTC-USD-SWAP"},
{"channel": "open-interest", "instId": "BTC-USD-SWAP"},
{"channel": "candle1m", "instId": "BTC-USD-SWAP"},
{"channel": "trades", "instId": "BTC-USD-SWAP"},
{"channel": "estimated-price", "instType": "SWAP", "uly": "BTC-USD"},
{"channel": "mark-price", "instId": "BTC-USD-SWAP"},
{"channel": "mark-price-candle1m", "instId": "BTC-USD-SWAP"},
{"channel": "price-limit", "instId": "BTC-USD-SWAP"},
{"channel": "books", "instId": "BTC-USD-SWAP"},
{"channel": "opt-summary", "uly": "BTC-USD"},
{"channel": "funding-rate", "instId": "BTC-USD-SWAP"},
{"channel": "index-candle1m", "instId": "BTC-USD"},
{"channel": "status"},
],
},
hdlr_json=store.onmessage,
),
client.ws_connect(
"wss://ws.okx.com:8443/ws/v5/private",
# "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999",
send_json={
"op": "subscribe",
"args": [
{"channel": "account"},
{"channel": "positions", "instType": "ANY"},
{"channel": "balance_and_position"},
{"channel": "orders", "instType": "ANY"},
{"channel": "orders-algo", "instType": "ANY"},
{"channel": "algo-advance", "instType": "ANY"},
{"channel": "liquidation-warning", "instType": "ANY"},
{"channel": "account-greeks", "instType": "ANY"},
],
},
hdlr_json=store.onmessage,
),
)
# loop
while True:
print(store.tickers.find())
await store.tickers.wait()
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
✨ 取引所 Bitget をサポートしました (Contributed by @kunmosky1 💖)
コピートレードが可能な海外取引所の Bitget をサポートしました。
Private API 認証及び WebSocket API による DataStore クラスを利用できます 🎉
Bitget API ドキュメント:
https://bitgetlimited.github.io/apidoc/en/spot/
https://bitgetlimited.github.io/apidoc/en/mix/
API 認証
pybotters に渡す API 辞書に bitget
のキーで API 情報をリストで格納してください。
Bitget も上記 OKX と同様に API のパスフレーズが存在します。
リストの3要素目にパスフレーズを記載してください。
{
"...": ["...", "..."],
"bitget": ["BITGET_API_KEY", "BITGET_API_SECRET", "YOUR_PASSPHRASE"]
}
DataStore のプロパティ
Bitget の DataStore は WebSocket のチャンネルごとに紐づいています。
Public
(https://bitgetlimited.github.io/apidoc/en/mix/#public-channels)
- trade
- orderbook
- ticker
- candlesticks
Private
(https://bitgetlimited.github.io/apidoc/en/mix/#private-channels)
- account
- orders
- positions
DataStore の initialize
Bitget の DataStore は以下のエンドポイントの initialize に対応しています。
- GET /api/mix/v1/order/current (DataStore: orders)
サンプルコード
initialize と ws_connect で全チャンネルを接続するサンプルです。
while True のループでは試しに ticker 情報を表示しています。
import asyncio
import pybotters
async with pybotters.Client(base_url="https://api.bitget.com") as client:
store = pybotters.BitgetDataStore()
# initialize
await store.initialize(
client.get("/api/mix/v1/order/current", params={"symbol": "BTCUSDT_UMCBL"}), # リニア契約
client.get("/api/mix/v1/order/current", params={"symbol": "BTCUSD_DMCBL"}) # インバース契約
)
# ws_connect
ws = await client.ws_connect(
"wss://ws.bitget.com/mix/v1/stream",
send_json={
"op": "subscribe",
"args": [
# インバース契約
{"instType":"DMCBL", "channel":"account", "instId":"default"},
{"instType":"DMCBL", "channel":"positions", "instId":"default"},
{"instType":"DMCBL", "channel":"orders", "instId":"default"},
{"instType":"mc", "channel":"trade", "instId":"BTCUSD"},
{"instType":"mc", "channel":"ticker", "instId":"BTCUSD"},
{"instType":"mc", "channel":"candle1m", "instId":"BTCUSD"},
{"instType":"mc", "channel":"books", "instId":"BTCUSD"},
# リニア契約
{"instType":"UMCBL", "channel":"account", "instId":"default"},
{"instType":"UMCBL", "channel":"positions", "instId":"default"},
{"instType":"UMCBL", "channel":"orders", "instId":"default"},
{"instType":"mc", "channel":"trade", "instId":"BTCUSDT"},
{"instType":"mc", "channel":"ticker", "instId":"BTCUSDT"},
{"instType":"mc", "channel":"candle1m", "instId":"BTCUSDT"},
{"instType":"mc", "channel":"books", "instId":"BTCUSDT"},
],
},
hdlr_json=store.onmessage,
)
# loop
while True:
print(store.ticker.find())
await store.ticker.wait()
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
✨ WebSocket の接続状況が確認できるようになりました
wc_connect の返り値から WebSocket の接続状況が確認できるようになりました。
DataStore で発注管理している bot などの場合は、格納されているデータが信頼できる状態か確認を行うことで誤発注などを避ける手段となります。
以下のように connected
で処理を分岐することが可能です。
async def main():
async with pybotters.Client() as client:
ws = await client.ws_connect("...")
while True:
if ws.conneted: # ws.conneted: bool
print("ws is connected")
else:
print("ws is disconnected")
await asyncio.sleep(5.0)
# Ctrl+C to break
※ 従来の機能として ws_connect で接続したコネクションは常に自動で再接続されます。 再接続の隙間や、取引所のメンテナンス中などのタイミングで connected が False になります。
また wait
で connected
が True になるまで待機することができます。
接続されている場合は await は即時終了します。
async def main():
async with pybotters.Client() as client:
ws = await client.ws_connect("...")
while True:
await ws.wait()
print("ws is connected. continue logic...")
...
# Ctrl+C to break
返り値の変更:
ws_connect の返り値は asyncio.Task
から独自の WebSocketRunner
クラスに変更されます。
⏫ Improvements
- ✨ bitbankDataStore の Depth に timestamp を追加しました (Contributed by @yota-p 💖)
階層構造ではないので DataStore に格納していなかった timestamp をクラスプロパティとして格納するようになりました。
store = pybotters.bitbankDataStore()
store.depth.timestamp
- ✨ WebSocket でのエラーメッセージの logging を向上しました
殆どの取引所において認証エラーや、DataStoreを利用した場合に subscribe エラー等を logging するようになりました。
- ✨ いくつかの取引所の API 認証タイムスタンプを弾かれないようにしました
pybotters が裏で利用している認証タイムスタンプは 秒 で使っていましたが、ccxt などから ミリ秒 で API を一度でも利用すると弾かれる事象がありました(Coincheck など)。
取引所が 秒 で指定していない限りは ミリ秒 を利用するようになりました。
#...
Preview v0.10.0 リリース
🎉 New Features
✨ Coincheck の DataStore をサポートしました
国内現物取引所の Coincheck の DataStore をサポートしました。 Coincheck の WebSocket API によるリアルタイムデータを活用できます 🚀
DataStore のプロパティ
- trades: 取引履歴
- orderbook: 板情報
※ Coincheck の WebSocket API はパブリックデータのみ提供しています。プライベートデータはありません。
以下、接続のサンプルコードです。
import asyncio
import pybotters
async def main():
async with pybotters.Client(base_url="https://coincheck.com") as client:
store = pybotters.CoincheckDataStore()
wstask = await client.ws_connect(
"wss://ws-api.coincheck.com/",
send_json=[
{"type": "subscribe", "channel": "btc_jpy-trades"},
{"type": "subscribe", "channel": "btc_jpy-orderbook"},
],
hdlr_json=store.onmessage,
)
await store.initialize(client.get("/api/order_books"))
while True:
pybotters.print("Trades")
pybotters.print(store.trades.find()[-1:])
pybotters.print("Orderbook")
pybotters.print({k: v[:5] for k, v in store.orderbook.sorted().items()})
await store.wait()
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
詳しくは Coincheck のドキュメントもご覧ください。
https://coincheck.com/ja/documents/exchange/api#websocket
✨ DataStore のリバースイテレーションに対応しました
DataStore を reversed
関数でリバースイテレーションできるようになりました。
時系列データなどを逆順(時間の新しい順)で効率的に取得できます。
以下は、Bybit のトレードを WebSocket で10件取得するまで待機し逆順で表示するサンプルコードです。
※ この機能は辞書の reversed
を行っている為、 Python 3.8 以降で利用できます 。
async def main():
async with pybotters.Client() as client:
store = pybotters.BybitUSDTDataStore()
wstask = await client.ws_connect(
"wss://stream.bybit.com/realtime_public",
send_json=[
{"op": "subscribe", "args": ["trade.BTCUSDT"]},
],
hdlr_json=store.onmessage,
)
print("wait for trades")
while len(store.trade) < 10:
await store.wait()
print("printing trades in reverse order")
for item in reversed(store.trade):
print(item)
✨ GMOコインのアクセストークンが自動延長されるようになりました
GMOCoinDataStore の initialize
メソッドに「アクセストークンを取得」のリクエストを渡すと DataStore にトークンが保持され、アクセストークンが30分ごとに自動延長されます。
プログラムの起動中にアクセストークンが切れることがないので安全にプライベート WebSocket の再接続時されます。
サンプルコード
async def gmocoin():
async with pybotters.Client(base_url="https://api.coin.z.com") as client:
store = pybotters.GMOCoinDataStore()
await store.initialize(
client.post("/private/v1/ws-auth"),
)
wstask = await client.ws_connect(
f"wss://api.coin.z.com/ws/private/v1/{store.token}",
send_json=[
{"command": "subscribe", "channel": "executionEvents"},
{"command": "subscribe", "channel": "orderEvents"},
{"command": "subscribe", "channel": "positionEvents"},
{"command": "subscribe", "channel": "positionSummaryEvents", "option": "PERIODIC"},
],
hdlr_json=store.onmessage,
)
while True:
...
# something code
🎈 Improves
- ✨ BybitInverseDataStore に wallet を追加しました
Bybit の更新に伴い BybitInverseDataStore
に wallet
を追加しました。
ストアからインバースの残高情報を参照できます。
また initialize
も残高エンドポイントの初期化に対応しました。
※ Bybit インバースの残高については、従来の position
にもデータが存在しています。
- ✨ PhemexDataStore で認証エラーの Warning が表示されるようになりました
🐛 Bugfix
✨ いくつかのバグを修正しました
- GMOCoinDataStore の ticker が上書きされない問題を修正しました
- Python 3.8 以下の場合 GMOCoinDataStore が TypeError で落ちる問題を修正しました
- bitbankDataStore の depth.sorted() の型アノテーションの間違いを修正しました
Issues
✅ 各取引所のDataStoreを実装する #20
✅ DataStoreのリバースイテレーション可能にする #113
✅ PhemexDataStoreで認証エラーのWarningを表示する #114
✅ BybitInverseDataStoreにwalletを追加する #118
✅ GMOCoinDataStoreのtickerが上書きされない #120
✅ GMOCoinDataStoreがTypeErrorで落ちる。 #122
✅ GMOコインのPrivate WebSocketアクセストークンを自動延長する #124
✅ bitbankのDatastoreのDepthで、sorted()の返り値の型の定義が正しくない #126
Preview v0.9.0 リリース
🎉 New Features
✨ PhemexのDataStoreをサポートしました (Contributed by @kunmosky1 💖)
PhemexのDataStoreをサポートしました。PhemexのWebSocketによるリアルタイムデータを活用できます!
DataStoreのプロパティ
- trade: トレード
- orderbook: 板情報
- ticker: ティッカー
- market24h: マーケット
- kline: ローソク足
- accounts: アカウントデータ
- positions: ポジション
以下接続のサンプルコードです。接続後はローソク足の更新を表示しています。
import asyncio
import pybotters
import time
apis = {'phemex': ['API_KEY','API_SECRET'],}
async def main():
async with pybotters.Client(apis=apis, base_url='https://api.phemex.com') as client:
store = pybotters.PhemexDataStore()
endtime = int(time.time()) - 60 * 999 #ws接続時に1000本送られてくるので、それより前の2000本を取得(合計で起動時に2999本)
await store.initialize(
client.get('/exchange/public/md/kline', params={'symbol': 'BTCUSD', 'resolution': 60, 'from': endtime - 60 * 2000, 'to': endtime}),
)
wstask = await client.ws_connect(
'wss://phemex.com/ws',
send_json=[
{'id': 100, 'method': 'trade.subscribe', 'params': ['BTCUSD']},
{'id': 101, 'method': 'tick.subscribe', 'params': ['.BTC']},
{'id': 103, 'method': 'orderbook.subscribe', 'params': ['BTCUSD']},
{'id': 104, 'method': 'kline.subscribe', 'params': ['BTCUSD',60]},
{'id': 105, 'method': 'market24h.subscribe', 'params': []},
{'id': 200, 'method': 'aop.subscribe', 'params': []},
],
hdlr_json=store.onmessage,
)
# Ctrl+C to break
while True:
await store.kline.wait()
data = store.kline.find()
print(data)
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
✨ Bybit USDT契約のポジション ワンウェイモードに対応しました
Bybitのアップデートに伴い、pybotters.BybitUSDTDataStore
もワンウェイモードに対応しました!
store = pybotters.BybitUSDTDataStore()
await client.ws_connect(...)
...
position = store.position.one("BTCUSDT") # one-way mode
position = store.position.both("BTCUSDT") # hedge mode
✨ Bybitのタイムスタンプ認証が通りやすくなりました
BybitはクライアントPCの時刻同期が少しでもズレいると、REST APIでは invalid request, please check your timestamp and recv_window param
といったエラーが派生したり、WebSocketでは WSServerHandshakeError
が発生することがありました。
今回のアップデートでは内部的にタイムスタンプのズレの許容幅を広げ、おおよそ5秒のズレまでは上記エラーを発生しづらくなります。
🐛 Bugfix
✨ 多数のバグを修正しました
コミュニティの方々のバグ報告により、7つのバグを修正しました。
いつもバグ報告ありがとうございます!
- Bybit Spotで注文削除(DELETEリクエスト)などができない問題が修正しました
- Binance Spot WebScoketの1秒につき5リクエスト制限に対応しました
- bitFlyerの親注文(入れ子のリクエスト)などができない問題を修正しました
- BybitUSDTDataStoreのinitializeにウォレットを再実装しました
- PhemexやBybitのDELETEリクエストに
params
を指定しても警告を表示しないようにしました - GMOCoinDataStoreでタイムスタンプの例外が発生する問題を修正しました
- bitbankの認証タイムスタンプをUNIXタイムスタンプ(13桁)に修正しました
- bitbankDataStoreの板情報のsortedメソッドを数値でソートするように修正しました
Issues
✅ Bybit SpotのDELETE認証方式を修正する #95
✅ BinanceのWebSocket制限に対応する #96
✅ bitFlyerの親注文APIがエラーになる #98
✅ BybitUSDTDataStoreのウォレット実装が漏れている #99
✅ HTTPリクエストのメソッドにおけるパラメーター指定時の警告を削除する #101
✅ Bybitの認証タイムスタンプについて変更を検討する #102
✅ Bybit USDT無期限のワンウェイモードに対応する #105
✅ GMOコインのタイムスタンプにミリ秒がないレコードがパースできない #106
✅ Binance USDⓈ-M Futuresの新しいWebSocketエンドポイントに対応する #108
✅ bitbankの認証タイムスタンプを修正する #109
✅ 旧BybitDataStoreクラスがauto_castを受け付けない #111
✅ bitbankDataStoreの板情報のソートが間違っている #110
Pull requests
Preview v0.8.0 リリース
🎉 New Features
✨ bitFlyerのDataStoreをサポートしました
DataStoreのプロパティ
- board: 板情報
- ticker: Ticker
- executions: 約定
- childorderevents: 注文イベント
- childorders: アクティブな注文
- parentorderevents: 親注文(特殊注文)イベント
- parentorders: アクティブな親注文(特殊注文)
- positions: 建玉の一覧
REST APIのinitializeとWebSocket購読のサンプルコード
import asyncio
import pybotters
async def main():
async with pybotters.Client(apis=apis, base_url="https://api.bitflyer.com") as client:
store = pybotters.bitFlyerDataStore()
await store.initialize(
client.get("/v1/me/getchildorders?product_code=FX_BTC_JPY"),
client.get("/v1/me/getparentorders?product_code=FX_BTC_JPY"),
client.get("/v1/me/getpositions?product_code=FX_BTC_JPY"),
)
wstask = await client.ws_connect(
"wss://ws.lightstream.bitflyer.com/json-rpc",
send_json=[
{"method": "subscribe", "params": {"channel": "lightning_board_snapshot_FX_BTC_JPY"}, "id": 1},
{"method": "subscribe", "params": {"channel": "lightning_board_FX_BTC_JPY"}, "id": 2},
{"method": "subscribe", "params": {"channel": "lightning_ticker_FX_BTC_JPY"}, "id": 3},
{"method": "subscribe", "params": {"channel": "lightning_executions_FX_BTC_JPY"}, "id": 4},
{"method": "subscribe", "params": {"channel": "child_order_events"}, "id": 5},
{"method": "subscribe", "params": {"channel": "parent_order_events"}, "id": 6},
],
hdlr_json=store.onmessage,
)
while True:
await store.wait()
for name, ds in store._stores.items():
print(f"{name}: {len(ds)=}")
print()
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
✨ [重要] BybitのDataStoreを Inverse/USDT 取引用にクラス分けしました
BybitのDataStoreは以下の2クラスに変更されました。それぞれの取引に最適化されます。
pybotters.BybitInverseDataStore
, pybotters.BybitUSDTDataStore
既存のpybotters.BybitDataStore
は引き続き利用できますが、非推奨になります。(今後廃止されます)
✨ DataStoreのstr型数値フィールド自動キャスト機能を追加しました
auto_cast=True
にすることにより、「str型の数字」のデータを自動的にint/floatに変換します。
store = pybotters.BybitInverseDataStore(auto_cast=True)
この機能を有効にすることで演算が便利になりますが、WebScoketイベントごとのstr型フィールドを判定するので処理負荷が増加します。
✨ WebSocketにおけるバイナリ型データのリクエスト/ハンドリングをサポートしました
Client.ws_connect
メソッドに、send_bytes
, hdlr_bytes
を追加しました。
Huobi Global(非対応非期初)などのデータハンドリングも可能になります。
Huobiのサンプル
import asyncio
import aiohttp
import gzip
import json
import pybotters
async def huobi_handler(msg_bytes: bytes, ws: aiohttp.ClientWebSocketResponse):
msg_json = json.loads(gzip.decompress(msg_bytes).decode())
if "ping" in msg_json:
ping = msg_json["ping"]
await ws.send_str(f'{{"pong":{ping}}}')
else:
print(msg_json)
async def main():
async with pybotters.Client() as client:
ws = await client.ws_connect(
"wss://api.huobi.pro/ws",
send_str='{"sub": "market.btcusdt.ticker"}',
hdlr_bytes=huobi_handler,
)
await ws
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
✨ GMOCoinDataStoreの板情報にタイムスタンプを追加しました
pybotters.GMOCoinDataStore.orderbooks.timestamp
からタイムスタンプを取得できます
Issues
✅ Bybitの型問題の抜本的な解決方法について #82
✅ バイナリのWebSocketデータのハンドリングに対応する #87
✅ GMOコインのデータストアにタイムスタンプを追加する #88
Pull requests
Preview v0.7.1 リリース
🐛 Bugfix
✅ 一部ストアにおいてデータが更新されない不具合を修正しました
DataStoreの内部メソッド _clear
が正しく動作しない不具合を修正しました。
これを使用している以下のストアが v0.6.0 リリース 以降、動作に問題がありましたがこの修正により改善されます。
pybotters.BinanceDataStore
- Orderストア
pybotters.FTXDataStore
- Marketsストア
pybotters.experimental.BybitUSDTDataStore
- Walletストア
Preview v0.7.0 リリース
🎉 New Features
✨ BybitのWebSocketのLiquidation(清算)をサポートしました
2021-9-14にサポートされた WebSocketのLiquidationトピックをDataStoreに追加しました!
なお、REST APIの /v2/public/liq-records
は 2021-9-24に廃止される ので注意してください。
WebSocketの清算イベントを表示するサンプルです。
清算は直ぐには発生しないので気長に待ちましょう🛀
import asyncio
import pybotters
async def main():
async with pybotters.Client() as client:
store = pybotters.BybitDataStore()
await client.ws_connect(
"wss://stream.bybit.com/realtime",
send_json={"op": "subscribe", "args": ["liquidation.BTCUSD"]},
hdlr_json=store.onmessage,
)
while True:
print(await store.liquidation.wait())
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
🌈 試験的にBybitの型変換済みDataStoreを実装しました
Experimentalな機能ですが、 文字列になってる数値をfloatやintに変換 して保管する新設計のDataStoreを実装しました!
このように価格や数量などのフィールドはfloatやintに変換を掛けて保管するようになります。
#before
[
{"symbol": "BTCUSD", "price": "1234.50", "id": 1234500, "side": "Sell", size: "100"}
]
#after
[
{"symbol": "BTCUSD", "price": 1234.5, "id": 1234500, "side": "Sell", size: 100}
]
また、従来の pybotters.BybitDataStore
はInverse契約とUSDT(Linear)契約の共通DataStoreでしたが、新しいDataStoreでは双方の契約の細かな仕様や型の違いに対応するために、クラスを2つに分割しました。
pybotters.experimental.BybitInverseDataStore
、pybotters.experimental.BybitUSDTDataStore
から利用できます。
最も大きな違いとしては、クラスが共通でなくなった為にポジションストアのメンバ名が変更されています。
# before
store = pybotters.BybitDataStore()
store.position_inverse.getone("BTCUSD")
store.position_inverse.getboth("BTCUSDM21")
store.position_usdt.getboth("BTCUSDT")
# after
store = pybotters.experimental.BybitInverseDataStore()
store.position.one("BTCUSD")
store.position.both("BTCUSDM21")
store = pybotters.experimental.BybitUSDTDataStore()
store.position.both("BTCUSDT")
その他の細かい違いとしては、wallet
ストアはUSDTのみ、insurance
ストアはインバースのみ、USDTのstoporder
ストアはキー名を変換せずstop_order_id
のまま利用するようにした、などです。
Bybitは 文字列の数値 のおかげで演算がやっかいなので、この試験的な機能は役に立つかもしれません。
型変換済みのDataStoreで板情報を表示するコードです!
import asyncio
import pybotters
async def main():
async with pybotters.Client() as client:
store = pybotters.experimental.BybitInverseDataStore()
await client.ws_connect(
"wss://stream.bybit.com/realtime",
send_json={"op": "subscribe", "args": ["orderBookL2_25.BTCUSD"]},
hdlr_json=store.onmessage,
)
while not len(store.orderbook):
await store.wait()
pybotters.print(store.orderbook.sorted())
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
⚠ これは暫定的・試験的な実装なので、将来的に大きく変更が入るかもしれません
✨ BybitのKlineの初期化をサポートしました (Contributed by @LopeRope 💖)
initializeメソッドでKlineのデータを格納できる機能を追加しました!
使い方はこちらです。
import asyncio
import time
import pybotters
async def main():
async with pybotters.Client(base_url="https://api.bybit.com") as client:
store = pybotters.BybitDataStore()
ts = int(time.time()) - 300
await store.initialize(
client.get(f"/v2/public/kline/list?symbol=BTCUSD&interval=1&from={ts}")
)
pybotters.print(store.kline.find())
await client.ws_connect(
"wss://stream.bybit.com/realtime",
send_json={"op": "subscribe", "args": ["klineV2.1.BTCUSD"]},
hdlr_json=store.onmessage,
)
while True:
pybotters.print(store.kline.find())
await store.kline.wait()
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
Issues
✅ Bybitの型問題の抜本的な解決方法について #82
✅ BybitのLiquidationトピックを追加する #83
Pull requests
✅ BybitのKlineのinitializeを追加する #81
Preview v0.6.0 リリース
🎉 New Features
✨ GMOコインのDataStoreをサポートしました (Contributed by @supermomonga 💖)
pybottersでは初の国内取引所DataStoreをサポートしました!
pybotters.GMOCoinDataStore
から、GMOコインのWebSokcetによるリアルタイムデータを利用することができます。
さらに本DataStoreは初の試みとして データの型付け をサポートしています。
symbol
はstr型、price
などはDecimal型、timestamp
はdatetime型など、データの意味通りの型でDataStoreに保管されます。
従来のDataStoreは数値や時刻データが文字列型でもそのまま(元の型のまま)保管していましたが、これにより演算やさらなる処理が容易になります。
GMOCoinDataStoreのインターフェースはリファレンスをご覧ください。
✨ CoincheckのAPI認証をサポートしました
国内取引所 Coincheck のAPI認証をサポートしました!
オーダー発注や残高の取得などのプライベートAPIが利用できます。 ※DataStoreは未対応です
✨ waitメソッドから受信データを取得できるようになりました (Contributed by @kaznak 💖)
DataStore.wait
メソッドの返り値は従来はNoneでしたが、** 待機した結果取得したデータ ** を返すようになりました。
これにより ** PostOnlyオプションにより即時キャンセルされてしまったオーダー ** などのDataStoreに残らないオーダー(※)を取得できます。 ※各種DataStoreのオーダーはアクティブオーダーのみ管理する仕様なので約定orキャンセル済みは削除される
注意: 親クラスの DataStoreManager.wait
メソッドの方にはこの機能はありません。
async def main():
async with pybotters.Client(base_url='https://ftx.com/api, apis=apis) as client:
store = pybotters.FTXDataStore()
ws = await client.ws_connect(
'wss://ftx.com/ws',
send_json={'op': 'subscribe', 'channel': 'orders'},
hdlr_json=store.onmessage,
)
asyncio.create_task(client.post('/orders', data=...)) # Send an order that will be canceled immediately
result = await store.orders.wait()
print(result)
# {'id': ..., 'status': 'closed', ...: ...}
print(store.orders.find())
# []
📖 Documentation
✨ Sphinxによるドキュメント自動生成を導入しました (Contributed by @drillan 💖)
Read The Docsにドキュメントを生成できるSphinxを導入しました!
GitHub WikiからRead The Docsにドキュメントを移行する予定です。
https://pybotters.readthedocs.io/ja/latest/
Other
- pybottersのリリース状況についての表記をBETAから Preview の名称に変更しました
- DataStoreを管理する抽象クラスの名称をDataStoreInterfaceからDataStoreManagerに変更しました
- DataStoreに隠しメソッド _pop, _find_and_delete を追加しました
詳細については以下をご覧ください。
Issues
✅ 対応取引所の追加(Phemex、Coincheck) #52
✅ GMO コインの DataStore を実装する #60
✅ リリース表記をPreview版にする #73
✅ FTXDataStore の orders チャネルにおける close されたオーダーの取り扱いについて #75
✅ DataStoreInterfaceのクラス名を変更する #79
Pull requests
✅ GMO コイン用の DataStore を一部実装する #74
✅ DataStore のレコード削除メソッドのサンプル実装 #76
✅ DataStore の wait メソッドが変更されたデータを返す実装 #77
✅ Sphinxのドキュメントを追加 #78
BETA v0.5.0 リリース
✅ #20 bitbankのDataStoreをサポート (contributed by @Osaifu-Crypto )
✅ #52 PhemexのAPI認証をサポート
✅ #67 GMO コインの認証処理を修正 (contributed by @supermomonga)
✅ #70 WebSocketのClientOSErrorをキャッチする
✅ #71 BTCMEXのサポートを廃止する(BitMEXをサポートする)
🎉 New Features
✨ bitbankのDataStoreをサポートしました
bitbankのWebSocketデータをハンドリングするDataStoreを実装しました!
pybotters.bitbankDataStore
から利用できます。
bitbankはSockei.io形式なので接続方法については従来とは少し異なります。下記サンプルコードを参照してください。
本機能はおさいふ君さん(@Osaifu_Crypto)にコードを提供して頂きました💖
各チャンネルのデータを監視するサンプルコードです。(コメントアウト/解除して利用してください)
async def main():
async with pybotters.Client() as client:
store = pybotters.bitbankDataStore()
wstask = await client.ws_connect(
'wss://stream.bitbank.cc/socket.io/?EIO=3&transport=websocket',
send_str=[
'42["join-room","ticker_xrp_jpy"]',
'42["join-room","transactions_xrp_jpy"]',
'42["join-room","depth_whole_xrp_jpy"]',
],
hdlr_str=store.onmessage,
)
while True:
# Transactions
# await store.transactions.wait()
# pybotters.print(store.transactions.find()[-1])
# Depth
await store.depth.wait()
pybotters.print({k:v[:6] for k, v in store.depth.sorted().items()})
# Ticker
# await store.ticker.wait()
# pybotters.print(store.ticker.find())
✨ PhemexのAPI認証をサポートしました
シンガポールを拠点とする新興取引所 Phemex のAPI認証をサポートしました。
REST/WebSocketのプライベートAPIを利用できます。(※WebSocketデータを保管するDataStore機能は未実装です)
新規オーダーを送信、プライベートWebsocketに接続するサンプルコード
async def main():
async with pybotters.Client(apis=apis, base_url='https://api.phemex.com') as client:
data = {
'symbol': 'BTCUSD',
'side': 'Buy',
'priceEp': 334100000,
'orderQty': 1,
'ordType': 'Limit',
'timeInForce': 'PostOnly',
}
r = await client.post('/orders', data=data)
data = await r.json()
pybotters.print(data)
wstask = await client.ws_connect(
'wss://phemex.com/ws',
send_str='{"method":"aop.subscribe","params":[],"id":123}',
hdlr_json=pybotters.print_hander
)
await wstask # Ctrl+C to break
✨ BTCMEXのサポートを廃止、BitMEXのDataStoreをサポートしました
BTCMEXが営業終了しましたのでコードやWikiの記述を削除しました。
代わりにBTCMEXはBitMEXのほぼ互換APIだったので、やっつけながらDataStoreを逆輸入しBitMEXのDataStoreをサポートしました。
pybotters.BitMEXDataStore
から利用できます。
🐛 Bugfix
- GMOコインのWebSocket認証トーンが正常にリクエストできるよう不具合を修正しました (本修正はめちゃコミッタさん(@supermomonga)に提供して頂きました💖)
- WebSocketの接続が
ClientOSError
といったエラーで落ちないように処理を修正しました