Releases: pybotters/pybotters
v1.2.0
What's Changed
Added
- Add post-maintenance reconnect helper for GMO Coin by @MtkN1 in #290
- Support Bybit Websocket Trade by @MtkN1 in #293
Deprecated
Development
Full Changelog: v1.1.1...v1.2.0
v1.1.1
v1.1.0
What's Changed
Added
Documentation
- Fix Read the Docs build using Poetry by @MtkN1 in #276
- Fix typo in docstring in DataStore.get method by @nukopy in #275
Development
- Use Ruff instead of Flake8, isort, and Black by @MtkN1 in #277
- Migrate project management from Poetry to Hatch by @MtkN1 in #279
- Update project configuration by @MtkN1 in #280
- Configuring automatically generated release notes by @MtkN1 in #284
- Integrate version control into Git tag with hatch-vcs by @MtkN1 in #285
New Contributors
Full Changelog: v1.0.0...v1.1.0
🚀 Version 1.0.0
Release highlights
pybotters が遂に v1.0 リリースを迎えられることを嬉しく思います 🎉🎉
pybotters の最初のリリースは v0.1.0 で 2021 年 4 月です。
3 年近くの時を経ててようやく v1.0 へのバージョンアップができました。
v1.0 リリースには以下の変更内容が含まれています。
- 幾つかの新機能
- 多数の破壊的な変更
- 多数の内部改善、テストカバレッジ 100% (取引所固有の DataStore を除く)
- ドキュメントの大幅アップデート、ブランディングロゴの追加
- リポジトリの移管 (MtkN1/pybotters -> pybotters/pybotters)
また pybotters はスポンサーシップを始めました。
開発者である @MtkN1 の GitHub スポンサーに登録して頂く事で、プロジェクトを支援できます。
💖 https://github.com/sponsors/MtkN1
プロジェクト継続の為にご支援のほどよろしくお願いします 🙏
New Features
- Add fetch API by @MtkN1 in #243
- 新しいリクエストメソッド
Client.fetch
を追加しました。Client.get
などよりもよりシンプルに HTTP リクエストを処理できます。
async def main(): async with pybotters.Client() as client: result = await client.fetch( "GET", "https://api.bitflyer.com/v1/getticker", params={"product_code": "BTC_JPY"}, ) print(result.response.status, result.response.reason) print(result.data)
- 新しいリクエストメソッド
- Redesign GMOCoin DataStore by @MtkN1 in #249
GMOCoinDataStore
のデータ型が再設計されました。 シンボルのデータが ENUM 型で独自定義されているなど、他の DataStore とは異なる仕様になっていました。 それを他と同様に「取引所由来のデータ型」を尊重する仕様になるよう変更しました。
# legacy { 'ask': Decimal('6484170'), 'bid': Decimal('6481482'), 'high': Decimal('6535603'), 'last': Decimal('6481889'), 'low': Decimal('6256694'), 'symbol': <Symbol.BTC_JPY: 24>, 'timestamp': datetime.datetime(2024, 1, 8, 13, 49, 0, 31000), 'volume': Decimal('1877.89') } # new { 'channel': 'ticker', 'ask': '6492347', 'bid': '6489767', 'high': '6535603', 'last': '6490200', 'low': '6256694', 'symbol': 'BTC_JPY', 'timestamp': '2024-01-08T13:47:46.410Z', 'volume': '1875.45' }
- なお、旧仕様の
GMOCoinDataStore
はpybotters.models.legacy.gmocoin
から引き続き利用できます。
- Enhance WebSocket Features by @MtkN1 in #259
- WebSocket の再接続が指数バックオフによって行われるようになります (より賢くなります) 。 以前の再接続は最大 60 秒固定でした。 さらに、指数バックオフを引数で指定できるようになります。
Client.ws_connect
のハンドラ引数send_json
などをリストで複数指定できるようになります。 以前は 1 つのみの指定でした。WebSocketApp
(Client.ws_connect
の戻り値) のurl
属性を利用して再接続時の URL を変更できるようになります。 これはトークン認証方式で WebSocket に接続している取引所で便利です。
- Improve DataStore.sorted in Order Book by @MtkN1 in #265
- Order Book 系 DataStore の
sorted
メソッドで引数limit
から板の行数を指定できるようになりました。
store = pybotters.bitFlyerDataStore() ... print(store.board.sorted(limit=2))
- Order Book 系 DataStore の
Breaking changes
💥 このアップデートには多数の破壊的な変更が含まれています 💥
以下の Pull request にて v1.0 における全ての破壊的変をまとめているので、マイグレーションガイドとして活用できます。
- Remove some APIs #252
以下の機能を利用してる場合コードが動作しなくなる場合があります。
必ずマイグレーションガイドを確認してトレード bot 等のコードの動作確認を行ってください。
影響が多いと考えられるものには Emoji 💥 を付けます。
- トップレベルの同期関数
pybotters.get
など - Bybit の古い DataStore
BybitUSDTDataStore
など - Binance の古い DataStore
BinanceDataStore
- 💥 Bybit V5 のDataStore
BybitV5DataStore
- DataStore の引数
auto_case
- 💥 WebSocket キュー
WebSocketQueue
- コールバック用関数
pybotters.print_handler
- KuCoin の API 認証情報にキー名
kucoinspot
kucoinfuture
- メソッド
DataStore.wait
WebSocketRunnner
(Client.ws_connect
の戻り値) の属性.connected
WebSocketRunnner
(Client.ws_connect
の戻り値) の属性.ws
- 💥💥 全ての取引所固有の DataStore のメソッド
sorted
また機能の変更以外に、サポート対象から Python 3.7 が外され Python 3.8 >= が対象になります。
- Drop Python 3.7 and support Python 3.8 through 3.12 by @MtkN1 in #246
- Remove some APIs by @MtkN1 in #252
- Remove return value of DataStore.wait method by @MtkN1 in #257
- Remove KuCoin API name compatibility by @MtkN1 in #254
- Improve Binance Authentication by @MtkN1 in #256
- Improve WebScoket auth by @MtkN1 in #262
Docs
ドキュメントを大幅にアップデートしました ✨
以前は実装されている機能の説明がなかったりしましたが、今回のアップデートで全てを網羅するようになっています!
まだドキュメントをみたことない方も、以前のドキュメントをみたことある方も、是非一度チェックしてください 👉
https://pybotters.readthedocs.io/ja/stable
- Update README.md by @MtkN1 in #251
- Update docs for v1.0 by @MtkN1 in #264
- Add sponsors information by @MtkN1 in #272
Improves
Bug fixes
- Wait for WebSocket login to complete in Bitget by @MtkN1 in #242
- Fix signatures when no parameters are specified in MEXC by @MtkN1 in #250
- Fix Binace order book buffer by @MtkN1 in #255
Developments
GitHub リポジトリを開発者の @MtkN1 から @pybotters に移管しました。
これは pybotters のプロジェクトとしての公共性をより表現する為です。
https://github.com/MtkN1/pybotters
👉
https://github.com/pybotters/pybotters
- Fix readthedocs build by @MtkN1 in #245
- Update tools version by @MtkN1 in #260
- Improve client and store testing by @MtkN1 in #261
- Improve type annotation style by @MtkN1 in #267
- Update docs for organization repository by @MtkN1 in #271
What's Changed
Full Changelog: v0.17.0...v1.0.0
🚀 Version 0.17.0
🪧 What's Changed
🚀 New Features
✅ Phemex Hedged Contract API の DataStore をサポートしました
新しくリリースされた Phemex Hedged Contract の DataStore をサポートしました。 Hedged Contract API とは USDT 建ての契約用の API です。 従来の契約は Contract API という表記になっておりクリプト建てと米ドル建ての契約が存在しています。
Hedged Contract の WebSocket API は配信されるチャンネル名が通常の Contract API から新しくなっていた為、今回の変更で DataStore をこれに対応しました。 なお REST API 認証の互換性があることは確認している為、従来の pybotters バージョンから引き続き利用ができます。
Phemex Hedged Contract WebSocket API ドキュメント: https://phemex-docs.github.io/#hedged-contract-websocket-api
アップデート後の PhemexDataStore
では以下ストアにて対応するチャンネルのデータがハンドリングされるようになります。
trade
store:trades_p
channelorderbook
store:orderbook_p
channelticker
store:tick_p
channelmarket24h
store:market24h_p
channelkline
store:kline_p
channelaccounts
store:aop_p
channelorders
store:aop_p
channelpositions
store:aop_p
channel
🔥 Breaking changes
PhemexDataStore が Hedged Contract をサポートするにあたって ** PhemexDataStore の以下ストアにおいて破壊的な変更があります **。
trade
ストアとorderbook
ストアのアイテムにおいて、数量を表すキーsize
をqty
に変更します。- キーが Phemex のドキュメントと不一致していた為。
trade
ストアとkline
ストアのアイテムにおいて、価格を表すprice
,open
,high
,low
,close
,turnover
の値に対して意図的に ÷ 10000 を行って価格を扱い易くしていた仕様を削除し元の値を尊重します。- これにより Contract API の場合は元の
priceEp
と同等の値が格納されます。 つまりユーザー側で明示的にスケールを演算する必要があります。 スケールの仕様ついては詳しくは Phemex のドキュメント (https://phemex-docs.github.io/#price-ratio-value-scales) をご覧ください。
- これにより Contract API の場合は元の
🎨 Sample Code
以下は PhemexDataStore
の利用例です。 Phemex Hedged Contract WebSocket API (testnet) の AOP(Account / Order / Position) チャンネルを購読して DataStore で変更を監視します。
import asyncio
import pybotters
async def main():
async with pybotters.Client() as client:
store = pybotters.PhemexDataStore()
asyncio.create_task(
client.ws_connect(
"wss://testnet-api.phemex.com/ws",
send_json={
"id": 1234,
"method": "aop_p.subscribe",
"params": [],
},
hdlr_json=store.onmessage,
)
)
async def watch_accounts():
with store.accounts.watch() as stream:
async for change in stream:
print("accounts", change)
async def watch_orders():
with store.orders.watch() as stream:
async for change in stream:
print("orders", change)
async def watch_positions():
with store.positions.watch() as stream:
async for change in stream:
print("positions", change)
await asyncio.gather(
watch_accounts(),
watch_orders(),
watch_positions(),
)
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
変更の詳細は #233 をご覧ください。
✅ Binance の現物用 "WebSocket API" をサポートしました。
Binance の現物用 "WebSocket API" とは、Public API (マーケットデータの取得など) と Private API (注文の送信や残高の取得など) を ** WebSocket 接続経由 **でリクエストできる API です。 従来の "Websocket Market Streams" [^2] や "User Data Streams" [^3] ではリアルタイムデータの受信に限られていましたが、この "WebSocket API" では REST API 同様の操作を WebSocket 経由で行えます。
これに REST API を利用するより早いレイテンシーで注文を作成できる可能性があります。 ただし Rate Limit としては REST API と同様なので注意が必要です。
以下は Binance "WebSocket API" で Public API (ティッカー) と Private API (アカウントステータス) をリクエストするサンプルコードです。
import asyncio
import uuid
import pybotters
from rich import print
async def main():
apis = {"binance_testnet": [api_key, api_sercret]}
async with pybotters.Client(apis=apis) as client:
wsq = pybotters.WebSocketQueue()
wsrunnner = await client.ws_connect(
"wss://testnet.binance.vision/ws-api/v3", hdlr_json=wsq.onmessage
)
if wsrunnner.ws is not None:
id1 = str(uuid.uuid4())
id2 = str(uuid.uuid4())
ids = {id1, id2}
data = {
"id": id1,
"method": "ticker.price",
"params": {"symbol": "BNBBTC"},
}
await wsrunnner.ws.send_json(data, auth=None)
data = {
"id": id2,
"method": "account.status",
"params": {},
}
await wsrunnner.ws.send_json(data)
async for msg in wsq.iter_msg():
print(msg)
ids.remove(msg["id"])
if not len(ids):
break
asyncio.run(main())
変更の詳細は #235 をご覧ください。
✅ KuCoin の high-frequency 用 API の動作確認を行いました
KuCoin に新しく追加された high-frequency API の対応状況を確認しました。 high-frequency API とはその名の通り取引のレイテンシーが低く、Rate Limit も緩い API とのことです。 現在現物のみで利用できる API のようです。
pybotters では新しく対応が必要な事象がないか確認したところ、従来のバージョンより認証の互換性があり API が利用可能ということが分かりました。 その為コードの変更等はありません。
high-frequency API を利用する為のサンプルコードについては Issue #230 のコメントをご覧ください。
⚡️ KuCoin の API 名は "kucoin"
に変更されます
以前 KuCoin の API キーは「現物用」と「先物用」で独立しており別々の発行になっていました。 つまり現物と先物を取引するには API キーが 2 つ必要だったということです。 しかし現在の KuCoin は「現物用」と「先物用」で独立する仕様はなくなっていることを確認しました。
pybotters では以前の仕様に対応する為に "kucoinspot" "kucoinfuture"
の 2 つの API 名を定義していました。 今回の変更ではこの KuCoin の API 名は "kucoin"
に統合されます。
# Old
{
"kucoinspot": ["KUCOIN_SPOT_API_KEY", "KUCOIN_SPOT_API_SECRET", "KUCOIN_SPOT_API_PASSPHRASE"],
"kucoinfuture": ["KUCOIN_FUTURE_API_KEY", "KUCOIN_FUTURE_API_SECRET", "KUCOIN_FUTURE_API_PASSPHRASE"]
}
# New
{
"kucoin": ["KUCOIN_COMMON_API_KEY", "KUCOIN_COMMON_API_SECRET", "KUCOIN_COMMON_API_PASSPHRASE"],
}
** しかしながら pybotters では API 名が "kucoinspot" "kucoinfuture"
のままでも認証が動作するよう互換性を保つ措置を行っています ** 。 引き続き Old の状態でもプログラムがエラーになることはありません。 この措置は pybotters がプレビュー版の間は保たれる予定です。 ただしドキュメント等は "kucoin"
の定義にマイグレーションされますので、既存のユーザーは変更の対応をお願いします。
⬆️ Improves / Bugfix
- ✅ WebSocket の例外処理を向上しました
- ✅ Phemex の新しいエンドポイント URL を認証ホストに追加しました
- ✅ KuCoin の DELETE メソッドで発生する認証のバグを修正しました
📝 Documentation
- ✅ ドキュメンテーションを Wiki から Read the docs に移行しました
Pull requests
- Update Phemex auth hosts by @MtkN1 in #232
- Support Phemex Hedged Contract Websocket Data by @MtkN1 in #233
- Catch ServerDisconnectedError exception by @MtkN1 in #234
- Support Binance Spot "WebSocket API" by @MtkN1 in #235
- Fix KuCoin signatures affected by HTTP methods by @MtkN1 in #236
- Integrate KuCoin API name by @MtkN1 in #237
- Renew documentation by @MtkN1 in #238
Full Changelog: v0.16.0...v0.17.0
🚀 Version 0.16.0
🪧 What's Changed
- Workaround: Bybit の Derivatives v3 Contract API に対応する by @cococig in #219
- typing-extensionsのバージョンアップ by @yota-p in #222
- Bybit の認証方式を新しい認証方式に変更する by @MtkN1 in #223
- PyPI へのアップロードを自動化する by @MtkN1 in #224
- README.md のバッジや分類を追加する by @MtkN1 in #225
- Bybit V5 API DataStore by @MtkN1 in #226
🚀 New Features
✅ Bybit V5 API をサポートしました (API 認証 / DataStore)
Bybit にて新しくリリースされた V5 API 1 を pybotters で利用できるようになりました!
V5 API では Bybit の以下主要プロダクトの API インターフェースが統合されました。
- USDT 無期限
- USDC 無期限
- USDC オプション
- インバース契約
- 現物取引
- マージン取引
- レバレッジトークン
- V5 API でこれら全てのプロダクトを利用するには Bybit 側で「統合取引アカウント」 2 へのアップグレートが必要です。
アップグレートを行っていない「デリバティブアカウント」の場合は、V5 API からは USDT 無期限とインバース契約のみ利用可能 3 です。
基本的には「統合取引アカウント」へアップグレートをおすすめしますが、既存の口座をアップグレートしたくない場合は、サブアカウントを作成してそちらを「統合取引アカウント」へアップグレートして利用することも可能です。 - (互換性のある変更) pybotters 内部の自動認証の仕組みにおいて Bybit への REST API リクエストを全て新しい認証方式 4 に変更しています。 URL クエリまたはリクエストボディに与えられていた認証情報がリクエストヘッダーに付与されるようになります。 これは従来の V2 API 5 の認証にも影響を与えますが、新しい認証方式でも動作することは確認済みです。
- (互換性のある変更) 同様に WebSocket API の認証方式も変更しています。 URL クエリに付与されていた認証情報は、WebSocket メッセージとして送信されるようになります。 こちらも V2 API でも動作することは確認済みです。
統合された API インターフェースを利用することで各プロダクト間での API 呼び出しがシームレスになります!
pybotters で V5 API を利用して他のトレーダーに差を付けましょう 🚀
💡 サンプルコード
REST API で成行注文を送信する
🚧 このコードを実行するとテストネットに BTCUSDT 0.001 枚の買い成行注文が送信されます。
import asyncio
import pybotters
from rich.pretty import pprint
apis = {
"bybit_testnet": ["BYBIT_TESTNET_API_KEY", "BYBIT_TESTNET_API_SECRET"],
}
async def main():
async with pybotters.Client(
base_url="https://api-testnet.bybit.com", apis=apis
) as client:
async with client.post(
"/v5/order/create",
data={
"category": "linear",
"symbol": "BTCUSDT",
"side": "Buy",
"orderType": "Market",
"qty": "0.001",
},
) as resp:
content = await resp.json()
pprint(content)
asyncio.run(main())
Public WebSocket を購読して DataStore でウォッチする
BTCUSDT に関する全ての Public WebSocket トピックを指定している為大量データの print 出力が表示されます。
適宜 topics の内容をコメントアウトして絞ってください。
import asyncio
import pybotters
import pybotters.store
from rich.pretty import pprint
async def watcher(ctx: pybotters.store.StoreStream):
try:
with ctx as stream:
async for change in stream:
pprint(change)
except KeyboardInterrupt:
pass
async def main():
topics = [
"orderbook.50.BTCUSDT",
"publicTrade.BTCUSDT",
"tickers.BTCUSDT",
"kline.5.BTCUSDT",
"liquidation.BTCUSDT",
]
async with pybotters.Client() as client:
store = pybotters.BybitV5DataStore()
ws = await client.ws_connect(
"wss://stream.bybit.com/v5/public/linear",
send_json={
"op": "subscribe",
"args": topics,
},
hdlr_json=store.onmessage,
)
for topic in topics:
dsname, *_ = topic.split(".")
asyncio.create_task(watcher(store[dsname].watch()))
await ws
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
Private WebSocket を購読して DataStore でウォッチする
こちらのコードを実行後、テストネットにて注文などのアカウント操作をするとリアルタイムデータが DataStore のウォッチ機能で出力されます。
watcher 関数のコメントアウトを切り替えると、リアルタイムデータがハンドリングされた後の実際のストアの中身を確認することができます。
import asyncio
import pybotters
import pybotters.store
from rich.pretty import pprint
apis = {
"bybit_testnet": ["BYBIT_TESTNET_API_KEY", "BYBIT_TESTNET_API_SECRET"],
}
async def watcher(ctx: pybotters.store.StoreStream):
with ctx as stream:
async for change in stream:
pprint(change)
# pprint(change.store.find())
async def main():
topics = [
"position",
"execution",
"order",
"wallet",
"greeks",
]
async with pybotters.Client(apis=apis) as client:
store = pybotters.BybitV5DataStore()
await store.initialize(
client.get(
"https://api-testnet.bybit.com/v5/position/list?category=linear&symbol=BTCUSDT" # noqa
),
client.get(
"https://api-testnet.bybit.com/v5/order/realtime?category=linear&symbol=BTCUSDT" # noqa
),
client.get(
"https://api-testnet.bybit.com/v5/account/wallet-balance?accountType=UNIFIED" # noqa
),
)
ws = await client.ws_connect(
"wss://stream-testnet.bybit.com/v5/private",
send_json={
"op": "subscribe",
"args": topics,
},
hdlr_json=store.onmessage,
)
for topic in topics:
asyncio.create_task(watcher(store[topic].watch()))
await ws
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
その他のサンプルや詳細仕様は、#223 #226 をご覧ください。
⬆️ Improves
✅ 依存関係を見直し、他のライブラリと併用しやすくなりました
pybotters の依存関係を整理しました。
具体的には typing-extensions のバージョン制約で、InfluxDB のクライアントライブラリ influxdb-client を pybottes に併せてインストールができない問題が発生していましたが、それを解消しました。
👷 CI / Misc
- ✅ pybotters の PyPI アップロードを GitHub Actions で自動化しました
- ✅ pybotters の GitHub README にバッジを追加したり PyPI の概要を更新しました
New Contributors
Full Changelog: v0.15.0...v0.16.0
-
https://www.bybithelp.com/ja-JP/s/article/Introduction-to-Bybit-Unified-Trading-Account ↩
-
https://bybit-exchange.github.io/docs/v5/upgrade-guide#current-api-coverage ↩
-
https://bybit-exchange.github.io/docs/v5/intro#parameters-for-authenticated-endpoints ↩
-
https://bybit-exchange.github.io/docs-legacy/futuresV2/linear/#t-introduction ↩
✨ v0.15.0 アップデート
🪧 What's Changed
- GMOコインの現物取引所にここ一年半ほどで追加された銘柄に対応 by @meetaco in #204
- Dev Containers 仕様のオープン化に対応及びローカルの API 設定がマウントされるようにした by @MtkN1 in #202
- Coincheck の WebSocket 仕様変更に対応した by @MtkN1 in #207
- GitHub Actions のテストに Python 3.10+ を追加した by @MtkN1 in #208
- WebSocketのメッセージキューを実装する by @MtkN1 in #209
- PhemexDataStore で条件付き注文のデータを格納する by @MtkN1 in #210
- bitFlyer のストアに現物向けの Balance を追加する by @MtkN1 in #211
- watch メソッドの変更クラスに影響されたストアとデータを追加する by @MtkN1 in #212
- Hotfix: bitFlyer の Positions ストアのメッセージ判断条件を修正する by @MtkN1 in #213
- ストアにおけるアイテムの参照性を変更する by @MtkN1 in #214
- Liquid に関する機能を廃止する by @MtkN1 in #215
- FTX に関する機能を廃止する by @MtkN1 in #216
- bitFlyer Positions ストアでのアップデートの watch ストリームを有効にする by @MtkN1 in #217
🚀 New Features
✅ bitFlyer の資産残高のストアを実装しました
bitFlyer の現物資産残高のストアが利用できるようになりました!
WebSocket の child_order_events チャンネルのデータを元に資産残高を計算し、リアルタイムで情報を利用できます。 また REST API による初期化にも対応しています。 ストアの値は GET /v1/me/getbalance
の形式で格納されます。
[
{
"currency_code": "JPY",
"amount": 1024078,
"available": 508000
},
{
"currency_code": "BTC",
"amount": 10.24,
"available": 4.12
},
{
"currency_code": "ETH",
"amount": 20.48,
"available": 16.38
}
]
サンプルコード
Balance
ストアの利用方法です。 REST API でデータを初期化し、watch メソッドで WebSocket からのデータを監視します。
import asyncio
import pybotters
async def main():
async with pybotters.Client(base_url="https://api.bitflyer.com", apis=apis) as client:
store = pybotters.bitFlyerDataStore()
await client.ws_connect(
"wss://ws.lightstream.bitflyer.com/json-rpc",
send_json={
"method": "subscribe",
"params": {"channel": "child_order_events"},
},
hdlr_json=store.onmessage,
)
with store.balance.watch() as stream:
await store.initialize(client.get("/v1/me/getbalance"))
async for change in stream:
print(change)
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
詳細は #211 をご覧ください。
✅ WebSocket のメッセージキューを実装しました
pybotters では WebSocket のハンドラとして各取引所の DataStore を提供していましたが、新たに WebSocketQueue を実装しました。 WebSocketQueue はシンプルなメッセージキューです。 asyncio.Queue を継承して実装されています。
💡 使いどころ
- DataStore を利用せずに素の WebSocket データを利用したい場合
- DataStore が実装されていない取引所の WebSocket データを利用したい場合
💡 DataStore の watch メソッドとの比較
DataStore の watch メソッドでもデータのキューイングが可能ですが、WebSocketQueue とは仕様が異なります。 少し似た機能なので、違いを説明します。
- 取得するデータ単位
- watch
- DataStore アイテムごと
- 例えば trade というストアがあり WebSocket から
{"channel": "trade, "data": [{"id": 1}, {"id": 2}]}
のようなデータが配信されたとしたら、ストア内の処理で{"id": 1}
と{"id": 2}
の 2 つのアイテムとして登録され、その 2 つが watch のストリームから取得されます。
- 例えば trade というストアがあり WebSocket から
- DataStore アイテムごと
- WebSocketQueue
- WebSocket メッセージごと
- 上記の例で言うと、WebSocket メッセージ
{"channel": "trade, "data": [{"id": 1}, {"id": 2}]}
がそのまま取得されます。
- 上記の例で言うと、WebSocket メッセージ
- WebSocket メッセージごと
- watch
- 発火の単位
- watch
- DataStore アイテムの更新ごと
- 例えば order というストアが WebSocket からあるオーダー ID がキャンセルされた旨のメッセージが配信された時に、order ストアに該当オーダー ID が存在していればそのアイテムは削除され watch に配信されます。 しかし該当オーダー ID が存在しない場合はストアに変更は存在しない為、watch に変更は配信されません。 つまり、
WebSocket メッセージの配信数 >= watch の発火数
です。
- 例えば order というストアが WebSocket からあるオーダー ID がキャンセルされた旨のメッセージが配信された時に、order ストアに該当オーダー ID が存在していればそのアイテムは削除され watch に配信されます。 しかし該当オーダー ID が存在しない場合はストアに変更は存在しない為、watch に変更は配信されません。 つまり、
- DataStore アイテムの更新ごと
- WebSocketQueue
- WebSocket メッセージの配信ごと
WebSocket メッセージの配信数 == WebSocketQueue の発火数
です。
- WebSocket メッセージの配信ごと
- watch
- データの形式
- watch
- 例えば trade というストアに WebSocket メッセージ
{"channel": "trade, "data": [{"id": 1}]}
が配信されたとしたら、ストア内の処理で{"id": 1}
にパースされストアに格納されます。 このアイテムが watch で取得されます。
- 例えば trade というストアに WebSocket メッセージ
- WebSocketQueue
- 上記の例で言うと、
{"channel": "trade, "data": [{"id": 1}]}
がそのまま取得されます。
- 上記の例で言うと、
- watch
サンプルコード
Coincheck で約定をキューイングするサンプルコードです。
pybotters.WebSocketQueue()
でインスタンスを生成するonmessage
メソッドをハンドラに渡すiter_msg
メソッドをコールしてasync for
ループに渡す- WebSocket メッセージ受信時、
async for
で定義したループ変数に値が格納される
import asyncio
import pybotters
async def main():
async with pybotters.Client() as client:
wsq = pybotters.WebSocketQueue()
await client.ws_connect(
"wss://ws-api.coincheck.com/",
send_json={"type": "subscribe", "channel": "btc_jpy-trades"},
hdlr_json=wsq.onmessage,
)
async for msg in wsq.iter_msg():
print(msg)
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
iter_msg
はタイムアウトを指定するなども可能です。 また asyncio.Queue の継承クラスなので get
を利用することもできます。
詳細は #209 をご覧ください。
⏫ Improvements
✅ watch 機能で影響元のデータとストアが分かるようになりました
例えば bitFlyer でオーダーがキャンセルされた時に watch で受け取るデータは以下の通りでした。
# 変更前
StoreChange(
│ operation='delete',
│ data={
│ │ 'product_code': 'BTC_JPY',
│ │ 'child_order_id': 'JOR20221228-121846-331601',
│ │ 'child_order_acceptance_id': 'JRF20221228-121846-183970',
│ │ 'event_date': '2022-12-28T12:18:46.9290446Z',
│ │ 'event_type': 'ORDER',
│ │ 'child_order_type': 'LIMIT',
│ │ 'side': 'BUY',
│ │ 'price': 2228600,
│ │ 'size': 0.001,
│ │ 'expire_date': '2023-01-27T12:18:46'
│ }
)
キャンセルされたイベントの通知ですが data
は "event_type": "ORDER"
となっており、プログラム側としても何の変更なのか分かりにくいです。
変更後は以下のようになります。
# 変更後
StoreChange(
│ store=<pybotters.models.bitflyer.ChildOrders object at 0x7fe8b38efcd0>,
│ operation='delete',
│ source={
│ │ 'product_code': 'BTC_JPY',
│ │ 'child_order_id': 'JOR20221228-121846-331601',
│ │ 'child_order_acceptance_id': 'JRF20221228-121846-183970',
│ │ 'event_date': '2022-12-28T12:18:48.8355776Z',
│ │ 'event_type': 'CANCEL',
│ │ 'price': 2228600,
│ │ 'size': 0.001
│ },
│ data={
│ │ 'product_code': 'BTC_JPY',
│ │ 'child_order_id': 'JOR20221228-121846-331601',
│ │ 'child_order_acceptance_id': 'JRF20221228-121846-183970',
│ │ 'event_date': '2022-12-28T12:18:46.9290446Z',
│ │ 'event_type': 'ORDER',
│ │ 'child_order_type': 'LIMIT',
│ │ 'side': 'BUY',
│ │ 'price': 2228600,
│ │ 'size': 0.001,
│ │ 'expire_date': '2023-01-27T12:18:46'
│ }
)
source
プロパティに影響元のアイテムが格納されるようになります。 "event_type": "CANCEL"
という値が分かるようになるのでより柔軟な処理が行えるようになります。
また store
プロパティで影響元のストアが渡されます。 プログラムはこのプロパティを利用してストアのデータを取得することが可能になります。
詳細は #212 をご覧ください。
✅ Coincheck の WebSocket 仕様変更に対応しました
以下のアナウンスの通り Coincheck の WebSocket が仕様変更され DataStore がデータをハンドリングできない状態でしたが正常にハンドリングされるよう修正しました。
https://corporate.coincheck.com/news/_XbwDwWN
Other Changes
- ✅ PhemexDataStore で条件付き注文のデータを格納できるようになりました
- ✅ GMOCoinDataStore の銘柄をアップデートしました
- ✅ Liquid と FTX に関する機能を廃止しました
- ✅ bitFlyerDataStore のポジションが減少した際 watch で取得されない問題を修正しました
👨💻👩💻 pybotters Development
✅ pybotters の Dev Containers を更新しました
VS Code などで利用できる開発コンテナの定義を刷新しました。
イメージの更新や、拡張機能のインストール、ローカルの PYBOTTERS_APIS
で指定している環境変数とファイルが自動でマウントされるようになります。 Author @MtkN1 と全く同じ開発環境を自動で構築されるのでコントリビュートされる方は是非ご利用ください。
詳細は #202 をご覧ください。
💖 New Contributors
Full Changelog: v0.14.1...v0.15.0
v0.14.1 Bugfix 💊
v0.14.0 アップデート ✨
🪧 What's Changed
- Binance DataStore が Spot / COIN-M をサポートしました by @ko0hi in #189
- KuCoin をサポートしました by @ko0hi in #185
- Bitget Trade DataStoreで side の項目に間違った値が入っている問題を修正しました by @ko0hi in #183
- bitFlyer Positions DataStore で watch 機能を利用した際、ポジションが解消されたイベントが受け取れない問題を修正しました by @ko0hi in #182
🚀 New Features
✨ Binance DataStore が Spot / COIN-M をサポートしました
BinanceDataStore は USDⓈ-M Futures トレードの WebSocket 配信情報のみをサポートしていましたが、このアップデートにより Spot と COIN-M のサポートを追加しました!
追加された Spot と COIN-M のストアも、従来の USDⓈ-M ストア同様に WebSocket から配信される板情報やオーダー情報などを利用できます。
1. 非推奨
既存のクラス pybotters.BinanceDataStore
は USDⓈ-M のストアとして実装されていますが、このクラスは非推奨となり将来的に削除されます。
Spot / USDⓈ-M / COIN-M のストアはそれぞれ新しいクラス名で提供されます。 (以下参照)
2. リファレンス
実装されているストアのプロパティ変数名と、それに対応する WebSocket Streams を表します。
Spot
- class pybotters.BinanceSpotDataStore
- coroutine initialize(*aws)
- Order Book
- orderbook
- Kline/Candlestick Data
- kline
- Current Open Orders
- order
- Query Open OCO
- ocoorder
- Account Information
- account
- LISTEN KEY (SPOT)
- listenkey
- 自動で定期的に listenkey を延長する
- Order Book
- trade
- kline
- ticker
- bookticker
- orderbook
- account
- order
- Order Update の
executionReport
イベント
- Order Update の
- ocoorder
- Order Update の
listStatus
イベント
- Order Update の
- listenkey
- coroutine initialize(*aws)
USDⓈ-M
- class pybotters.BinanceUSDSMDataStore
- coroutine initialize(*aws)
- Order Book
- orderbook
- Kline/Candlestick Data
- kline
- Current All Open Orders
- order
- Futures Account Balance V2
- balance
- Position Information V2
- position
- Start User Data Stream
- listenkey
- 自動で定期的に listenkey を延長する
- Order Book
- trade
- markprice
- kline
- continuouskline
- ticker
- bookticker
- liquidation
- orderbook
- compositeindex
- balance
- Balance and Position Update の
"B"
キー
- Balance and Position Update の
- position
- Balance and Position Update の
"P"
キー
- Balance and Position Update の
- order
- listenkey
- coroutine initialize(*aws)
COIN-M
- class pybotters.BinanceCOINMDataStore
- coroutine initialize(*aws)
- Order Book
- orderbook
- Kline/Candlestick Data
- kline
- Index Price Kline/Candlestick Data
- indexpricekline
- Mark Price Kline/Candlestick Data
- markpricekline
- Current All Open Orders
- order
- Futures Account Balance
- balance
- Position Information
- position
- Start User Data Stream
- listenkey
- 自動で定期的に listenkey を延長する
- Order Book
- trade
- indexprice
- markprice
- kline
- continuouskline
- indexpricekline
- markpricekline
- ticker
- bookticker
- liquidation
- orderbook
- balance
- Balance and Position Update の
"B"
キー
- Balance and Position Update の
- position
- Balance and Position Update の
"P"
キー
- Balance and Position Update の
- order
- listenkey
- coroutine initialize(*aws)
3. サンプルコード
Spot, USDⓈ-M, COIN-M の User Data (残高、オーダー、ポジション) を watch 機能で監視するサンプルコードです。
このコードを実行中に Web 画面でオーダーを送信するなどすると、その情報が画面に表示されます。
import pybotters
import asyncio
from rich.pretty import pprint
apis = {"binance": ["KEY", "SECRET"]}
async def watcher(_stream):
with _stream as stream:
async for change in stream:
pprint(change)
async def main():
async with pybotters.Client(apis=apis) as client:
pybotters.Binance...
Preview v0.13.1 アップデート✨
⏫ Improvements
- FTXDataStore.orderbook に time プロパティを追加しました (Contributed by @sunbluesome 💖)
FTXDataStore では WebSocket から受信する Orderbooks データの "time" を利用していませんでしたが、プロパティ変数として格納するようになりました。
FTX - WebSocket- Orderbooks のデータ形式
{
"channel": "orderbook",
"market": "BTC-PERP",
"type": "update",
"data": {
"time": 1657555432.5312576,
"checksum": 804021281,
"bids": [...],
"asks": [...],
"action": "update"
}
}
参照方法
>>> store = pybotters.FTXDataStore()
...
>>> store.orderbook.time
1657555432.5312576
- BinanceDataStore.kline を initialize できるようになりました (Contributed by @5QgKxT2j 💖)
async def main():
async with pybotters.Client(base_url="https://fapi.binance.com") as client:
store = pybotters.BinanceDataStore()
await store.initialize(
client.get(
"/fapi/v1/klines",
params={
"symbol": "BTCUSDT",
"interval": "1m",
"limit": "10",
},
)
)
print(store.kline.find())
- BitMEXDataStore に各種 tradeBin と quoteBin プロパティを追加しました
添え字アクセスのみ可能だった tradeBin* と quoteBin* トピックをストアのプロパティに追加しました。
>>> store = pybotters.BitMEXDataStore()
>>> store.quotebin
store.quotebin1m store.quotebin5m store.quotebin1h store.quotebin1d
>>> store.tradebin
store.tradebin1m store.tradebin5m store.tradebin1h store.tradebin1d
- pybotters の User Agent を設定しました
各取引所に API リクエストをすると pybotters クライアントあることが分かるようになります。
>>> async with client.get("https://httpbin.org/get") as resp:
... data = await resp.text()
>>> print(data)
{
"args": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "pybotters/0.13.1"
},
"url": "https://httpbin.org/get"
}
🐛 Bigfix
-
BinanceDataStore.order.initialize において symbol の初期化が正しく行われない問題を修正しました
-
MEXC の GET の REST API において認証が正しく行われるよう修正しました
-
WebSocket クラスのコネクション確認変数の Typo を修正しました
ws = await client.ws_connect(...)
- ws.conneted # Incorrect
+ ws.connected # Corrent
👨💻👩💻 pybotters Development
(必読) pybotter コントリビューターの方へ
Contributing Wiki ページを刷新しました
https://github.com/MtkN1/pybotters/wiki/Contributing
- VS Code 用の .devcontainer を定義しました (Contributed by @tk42 💖)
リポジトリに .devcontainer
ディレクトリを追加しました。
これは VS Code の Remote - Container 拡張機能による開発コンテナの作成機能です。
マシンに VS Code と Docker がインストールされている場合は、"Reopen in Container" をクリックすることで必要な Python バージョンやその他ソフトウェアやライブラリ、VS Code の細かい設定が自動で行われます。
pybotters コントリビューターの方は是非利用してみてください!
- リポジトリ及びブランチの運用方針を更新しました
develop ブランチの運用を廃止して main ブランチを開発ブランチとして運用するようにしました。
GitHub Flow に則る形になります。
(著者 MtkN1 によるメンテ方法についても、main ブランチを直接コミットせず必ず Pull Request を通して行うようになります)
詳しくは Wiki ページをご覧ください。
Issues
✅ mainブランチの運用方法についての検討する #104
✅ VS Code の devcontainer で pybotters 開発環境を用意する #164
✅ FTXのOrderBookにtimeを追加する #168
✅ BinanceDataStore.order.initialize による初期化時にレコードが削除されない #170
✅ User Agent を設定する #171
✅ MEXC の REST API が一部認証がエラーになる #173
✅ BitMEXDataStore のプロパティに tradeBin や quoteBin を追加する #174
✅ WebSocket 接続状態変数の Typo #175
Pull requests
✅ Added devcontainer.json and Dockerfile #165
✅ add time for Orderbook #169
✅ BinanceのKlineをREST APIのレスポンスでDataStoreを初期化可能にする #178
Full Changelog: v0.13.0...v0.13.1