Hyperliquid(ハイリキ)のAPIのドキュメントを読んで残高取得や注文をしてみる

初めに

エアドロで盛り上がるHyperliquidのAPIを使って、残高取得や注文を試してみたというお話。非常に初心者向けかと思いますが、プログラムトレード(いわゆるbot)をしてみたい&ハイリキ使ってやってみたいという方がいるかもと思い、自分の勉強の共有も兼ねて書いています。

※記事内でもしつこいほど触れましたが、中身は間違いがあるかもしれませんし、そもそもHyperliquidを利用していいのか等含め、すべて自己責任でお願いします。筆者は一切責任とりません。

必要なもの

・Pythonのある程度の知識(ライブラリの呼び出し、その参照、関数利用あたり)
・ウォレットを持っている

ドキュメント

何はともあれ公式ドキュメントのAPIのドキュメントへ。

APIとは

Application Programming Interfaceの略で、ソフトウェア同士、プログラム同士がやり取りをするためのルールのようなものです。既存のシステムを再利用するのに便利で、取引所から価格情報を得たり、注文したりということができます。

インストール

以下のページのREADME的なところにある通り、まずはこれでハイリキSDKがインストールできます

pip install hyperliquid-python-sdk

残高取得の例

上記のページの次のステップとして残高取得の例があります。ここでは、
・from xxx import yyyで関連ライブラリを呼び出し
・info = xxxではテストネットに接続
・user_state = xxxでは、"0xcd…"のウォレットの状態を取得しています。この部分を自分のアドレスに変更すれば見られます。

from hyperliquid.info import Info
from hyperliquid.utils import constants

info = Info(constants.TESTNET_API_URL, skip_ws=True)
user_state = info.user_state("任意のウォレットアドレス")
print(user_state)

ここでいくつか注意点というか自分が軽く引っかかったポイントとして、
1. TESTNET vs MAINNNET
2. user_stateには種類がある
というのがあります。

1点目は簡単な話で、上記の例はテストネットの情報を取得しているので、テスト用であればよいですが本番の情報を知りたければMAINNET_API_URLとする必要があるので、状況によって使い分けます。

info = Info(constants.MAINNET_API_URL, skip_ws=True)

もう一点目が、ユーザーステートです。ハイリキにはスポットアカウント(?)やPerpアカウント(?)がありそれぞれ分かれているので、例えばSpotアカウントに入っている情報を取り出したいときには

user_state = info.spot_user_state("任意のウォレットアドレス")

と、"info."以降を変更する必要があります。

なんでそんなことわかるねんというと、こちらのページの関数の種類として"user_state"と"spot_user_state"とが分かれているから、、ということです(というか私はそれで理解しましたがほかにこうすれば同様のことがわかる、という方法があればそれはそれで知りたいです)。

まとめると、、Spotに何か残高がある状態で

from hyperliquid.info import Info
from hyperliquid.utils import constants
import json
import example_utils
import eth_account

from hyperliquid.exchange import Exchange
from hyperliquid.info import Info

# get the current wallet status
info = Info(constants.MAINNET_API_URL, skip_ws=True)
spot_user_state = info.spot_user_state("任意のウォレットアドレス") #wallet address
print(spot_user_state)

とやると残高が見られます

約12ドル。5桁くらい増えてくれ

注文

さて残高取得で慣れたことだしspotで注文もしてみるかーということでなんかいいコード例ないんすかと探してみるとこちらにたどり着きました。

https://github.com/hyperliquid-dex/hyperliquid-python-sdk/blob/master/examples/basic_spot_order.py

見てみると、PURR/USDCを注文してみるコードの模様。

import json

import example_utils

from hyperliquid.utils import constants

PURR = "PURR/USDC"
OTHER_COIN = "@8"
OTHER_COIN_NAME = "KORILA/USDC"


def main():
    address, info, exchange = example_utils.setup(base_url=constants.TESTNET_API_URL, skip_ws=True)

    # Get the user state and print out position information
    spot_user_state = info.spot_user_state(address)
    if len(spot_user_state["balances"]) > 0:
        print("spot balances:")
        for balance in spot_user_state["balances"]:
            print(json.dumps(balance, indent=2))
    else:
        print("no available token balances")

    # Place an order that should rest by setting the price very low
    order_result = exchange.order(PURR, True, 24, 0.5, {"limit": {"tif": "Gtc"}})
    print(order_result)

    # Query the order status by oid
    if order_result["status"] == "ok":
        status = order_result["response"]["data"]["statuses"][0]
        if "resting" in status:
            order_status = info.query_order_by_oid(address, status["resting"]["oid"])
            print("Order status by oid:", order_status)

    # Cancel the order
    if order_result["status"] == "ok":
        status = order_result["response"]["data"]["statuses"][0]
        if "resting" in status:
            cancel_result = exchange.cancel(PURR, status["resting"]["oid"])
            print(cancel_result)

    # For other spot assets other than PURR/USDC use @{index} e.g. on testnet @8 is KORILA/USDC
    order_result = exchange.order(OTHER_COIN, True, 1, 12, {"limit": {"tif": "Gtc"}})
    print(order_result)
    if order_result["status"] == "ok":
        status = order_result["response"]["data"]["statuses"][0]
        if "resting" in status:
            # The sdk now also support using spot names, although be careful as they might not always be unique
            cancel_result = exchange.cancel(OTHER_COIN_NAME, status["resting"]["oid"])
            print(cancel_result)


if __name__ == "__main__":
    main()

関数そのままたたくよりmainの中身を追っていったほうがいいかなと思って上から順番に行きましたが引っ掛かりポイントが3つありました。

引っかかったポイントその1

import example_utils

これ。そんなのありません、と言われる。多分pip installが失敗したのかなんなのかよくわかりませんが、いずれにせよexample_utilsを読めばいいって話なんで、ここにあるコードをそのままコピペして、自分の作業しているpyファイルがある場所と同じフォルダに"example_utils.py"という名前で置いておきます。何言ってるかよくわからんという人は"python 自作ライブラリ 呼び出し"とかで調べると分かるかもしれません。

引っかかったポイントその2
で次の引っかかりポイントがここです

    config_path = os.path.join(os.path.dirname(__file__), "config.json")

そんなので引っかかるなよ、、って言われそうですが、いわゆる環境変数を利用して秘密鍵を管理する的なやつだと理解しています。"秘密鍵 環境変数"とかで出てくるかもしれませんが、いずれにせよ同様のフォルダに

{
    "secret_key": "自分の秘密鍵",
    "account_address": "自分の公開鍵鍵"
}

こういう形式で"config.json"という名前で保存したファイルを置きます。これでこの人のカギがあっているということをコード上で確認することとなります。

引っかかったポイントその3

※以下では本当に注文を行います。試すときの価格や数量は現在価格を見て調整してください。入力値しだいでは即約定されるかもしれません。
とにかく自己責任でお願いします、一切責任負いません。※

    order_result = exchange.order(PURR, True, 24, 0.5, {"limit": {"tif": "Gtc"}})

まあいうほど引っかかったわけでもないですが、注文はここで行われています。けどパラメータがよくわからん、、ということで"exchange.order"をしているのだから"exchange"を探していくと"example_utils.setup()"の返り値として出てるのだからってことで、まずは結局"import example_utils"のexample_utilsを見に行けばいいじゃんと分かるのでそっち行ってみると…

from hyperliquid.exchange import Exchange
from hyperliquid.info import Info

冒頭で"Exchange"を読み込んでいるということがわかりますので次はそちらへ。

    def order(
        self,
        name: str,
        is_buy: bool,
        sz: float,
        limit_px: float,
        order_type: OrderType,
        reduce_only: bool = False,
        cloid: Optional[Cloid] = None,
        builder: Optional[BuilderInfo] = None,

長いので全部は引用しませんが、ああここが関連パラメータね、とわかります。実行に進む前に再度注意です。繰り返しですが、試すときの価格や数量は現在価格を見て調整してください。即約定されるかもしれません。とにかく自己責任でお願いします、一切責任負いません。

では実行してみるかという前に、価格0.5だとちょっと大きいので、注文金額10ドルになるよう調整して1枚0.2ドルで50枚という注文に変えてみます。で、

 order_result = exchange.order(PURR, True, 50, 0.2, {"limit": {"tif": "Gtc"}}) #name, buy=True, size, limit price, order type

とやると、50枚を0.2ドルで買うという指値をいれるということになります。tifやgtcは調べてください。しつこいですが、試すときの価格や数量は現在価格を見て調整してください。即約定されるかもしれません。とにかく自己責任でお願いします、一切責任負いません。

上記の結果、GUIでも注文が反映されていることが確認できる

ちなみに、めちゃくちゃ乖離している価格は入れられないようです。超低価格で入れてみたらエラーが返ってきました。

あとはハイリキの例に書いてる通りではありますが、キャンセルも可能です。ただしTIFは取引所が指定する一定時間経過後は勝手にキャンセルするものなので、しばらくたつと消えていてそのあとにキャンセルコードを送っても多分エラーになります(試してませんが)

#キャンセルの例
cancel_result = exchange.cancel(PURR, status["resting"]["oid"])

まとめ

上記の方法を基本に、「残高取得してXXという条件のもと注文」を繰り返せばbot化も可能だと思います。初めて書いたので不足点等あるかもしれませんが、自分の備忘録+どなたかの参考になればという記事なのでご容赦ください。

最後に繰り返しですが、Hyperliquidの利用含め、とにかくすべて自己責任でお願いします。一切責任とりません。

で、最後の最後に、ハイリキ全般についてはlutwiseさんが書かれたこの記事が非常に参考になると思います。ハイリキ使わない人でも普通にめちゃくちゃ勉強になると思います。

いいなと思ったら応援しよう!