noteのタイトル画像

BitMEXのfetchTicker代用品を作ってみました!

目次
・BitMEXのfetchTicker代用API探し
・「instrument」でデータ取得
・ccxtを探索→あ、あった!
・実行してみよう
・本家fetchTickerの値と比較

●BitMEXのfetchTicker代用API探し

先日の「BitMEXのfetchTickerが使用できなくなった問題」に対応するため代用APIを探していたところ、

というありがたい情報を得ました。

さっそくBitMEX API Explorerに飛んで APIを確認。

なるほど、これですね。
「GET /instrument」のようです。

他にも

のようにいくつか派生のAPIがあるみたいですが、今回は「instrument」の方だけ確認します。

使用方法を読んで、パラメータがたくさんあることがわかりました。

ま、取り急ぎ必要なパラメータは
・symbol
・reverse
くらいでしょうね。
・symbol : 'XBTUSD'
・reverse : true
にしてやってみましょう。
(動作確認はtestnet.bitmex.comで行なっています)

●「instrument」でデータ取得

APIの実行結果は

[
  {
    "symbol": "XBTUSD",
    "rootSymbol": "XBT",
    "state": "Open",
    "typ": "FFWCSX",
    "listing": "2016-05-04T12:00:00.000Z",
    "front": "2016-05-04T12:00:00.000Z",
    "expiry": null,
    "settle": null,
    "relistInterval": null,
    "inverseLeg": "",
    "sellLeg": "",
    "buyLeg": "",
    "optionStrikePcnt": null,
    "optionStrikeRound": null,
    "optionStrikePrice": null,
    "optionMultiplier": null,
    "positionCurrency": "USD",
    "underlying": "XBT",
    "quoteCurrency": "USD",
    "underlyingSymbol": "XBT=",
    "reference": "BMEX",
    "referenceSymbol": ".BXBT",
    "calcInterval": null,
    "publishInterval": null,
    "publishTime": null,
    "maxOrderQty": 10000000,
    "maxPrice": 1000000,
    "lotSize": 1,
    "tickSize": 0.5,
    "multiplier": -100000000,
    "settlCurrency": "XBt",
    "underlyingToPositionMultiplier": null,
    "underlyingToSettleMultiplier": -100000000,
    "quoteToSettleMultiplier": null,
    "isQuanto": false,
    "isInverse": true,
    "initMargin": 0.01,
    "maintMargin": 0.005,
    "riskLimit": 20000000000,
    "riskStep": 10000000000,
    "limit": null,
    "capped": false,
    "taxed": true,
    "deleverage": true,
    "makerFee": -0.00025,
    "takerFee": 0.00075,
    "settlementFee": 0,
    "insuranceFee": 0,
    "fundingBaseSymbol": ".XBTBON8H",
    "fundingQuoteSymbol": ".USDBON8H",
    "fundingPremiumSymbol": ".XBTUSDPI8H",
    "fundingTimestamp": "2018-06-07T20:00:00.000Z",
    "fundingInterval": "2000-01-01T08:00:00.000Z",
    "fundingRate": 0.000173,
    "indicativeFundingRate": 0.0001,
    "rebalanceTimestamp": null,
    "rebalanceInterval": null,
    "openingTimestamp": "2018-06-07T12:00:00.000Z",
    "closingTimestamp": "2018-06-07T14:00:00.000Z",
    "sessionInterval": "2000-01-01T02:00:00.000Z",
    "prevClosePrice": 7684.04,
    "limitDownPrice": null,
    "limitUpPrice": null,
    "bankruptLimitDownPrice": null,
    "bankruptLimitUpPrice": null,
    "prevTotalVolume": 44857274050,
    "totalVolume": 44867337924,
    "volume": 10063874,
    "volume24h": 269382776,
    "prevTotalTurnover": 620020959561767,
    "totalTurnover": 620151755541032,
    "turnover": 130795979265,
    "turnover24h": 3521286312409,
    "prevPrice24h": 7646.5,
    "vwap": 7650.5241,
    "highPrice": 7760,
    "lowPrice": 7538,
    "lastPrice": 7695,
    "lastPriceProtected": 7695,
    "lastTickDirection": "ZeroMinusTick",
    "lastChangePcnt": 0.0063,
    "bidPrice": 7695,
    "midPrice": 7695.25,
    "askPrice": 7695.5,
    "impactBidPrice": 7691.716,
    "impactMidPrice": 7694.5,
    "impactAskPrice": 7697.0443,
    "hasLiquidity": true,
    "openInterest": 176418206,
    "openValue": 2288849804644,
    "fairMethod": "FundingRate",
    "fairBasisRate": 0.189435,
    "fairBasis": 1.09,
    "fairPrice": 7707.6,
    "markMethod": "FairPrice",
    "markPrice": 7707.6,
    "indicativeTaxRate": 0,
    "indicativeSettlePrice": 7706.51,
    "optionUnderlyingPrice": null,
    "settledPrice": null,
    "timestamp": "2018-06-07T13:29:05.182Z"
  }
]

となり、、、ずらりと値が取得できました。
実行したURLは

https://testnet.bitmex.com/api/v1/instrument?symbol=XBTUSD&reverse=true

です。
試しに本家の方でも次のURLで実行しました。

https://www.bitmex.com/api/v1/instrument?symbol=XBTUSD&reverse=true

以下のように、しっかり値は取れているようです。

[
  {
    "symbol": "XBTUSD",
    "rootSymbol": "XBT",
    "state": "Open",
    "typ": "FFWCSX",
    "listing": "2016-05-13T12:00:00.000Z",
    "front": "2016-05-13T12:00:00.000Z",
    "expiry": null,
    "settle": null,
    "relistInterval": null,
    "inverseLeg": "",
    "sellLeg": "",
    "buyLeg": "",
    "optionStrikePcnt": null,
    "optionStrikeRound": null,
    "optionStrikePrice": null,
    "optionMultiplier": null,
    "positionCurrency": "USD",
    "underlying": "XBT",
    "quoteCurrency": "USD",
    "underlyingSymbol": "XBT=",
    "reference": "BMEX",
    "referenceSymbol": ".BXBT",
    "calcInterval": null,
    "publishInterval": null,
    "publishTime": null,
    "maxOrderQty": 10000000,
    "maxPrice": 1000000,
    "lotSize": 1,
    "tickSize": 0.5,
    "multiplier": -100000000,
    "settlCurrency": "XBt",
    "underlyingToPositionMultiplier": null,
    "underlyingToSettleMultiplier": -100000000,
    "quoteToSettleMultiplier": null,
    "isQuanto": false,
    "isInverse": true,
    "initMargin": 0.01,
    "maintMargin": 0.005,
    "riskLimit": 20000000000,
    "riskStep": 10000000000,
    "limit": null,
    "capped": false,
    "taxed": true,
    "deleverage": true,
    "makerFee": -0.00025,
    "takerFee": 0.00075,
    "settlementFee": 0,
    "insuranceFee": 0,
    "fundingBaseSymbol": ".XBTBON8H",
    "fundingQuoteSymbol": ".USDBON8H",
    "fundingPremiumSymbol": ".XBTUSDPI8H",
    "fundingTimestamp": "2018-06-07T20:00:00.000Z",
    "fundingInterval": "2000-01-01T08:00:00.000Z",
    "fundingRate": 0.000371,
    "indicativeFundingRate": 0.0001,
    "rebalanceTimestamp": null,
    "rebalanceInterval": null,
    "openingTimestamp": "2018-06-07T12:00:00.000Z",
    "closingTimestamp": "2018-06-07T14:00:00.000Z",
    "sessionInterval": "2000-01-01T02:00:00.000Z",
    "prevClosePrice": 7684,
    "limitDownPrice": null,
    "limitUpPrice": null,
    "bankruptLimitDownPrice": null,
    "bankruptLimitUpPrice": null,
    "prevTotalVolume": 517167663544,
    "totalVolume": 517244791155,
    "volume": 77127611,
    "volume24h": 2074802811,
    "prevTotalTurnover": 6693991766742544,
    "totalTurnover": 6694992832688921,
    "turnover": 1001065946377,
    "turnover24h": 27133543224065,
    "prevPrice24h": 7641,
    "vwap": 7647.0138,
    "highPrice": 7755,
    "lowPrice": 7478,
    "lastPrice": 7704.5,
    "lastPriceProtected": 7704.5,
    "lastTickDirection": "ZeroPlusTick",
    "lastChangePcnt": 0.0083,
    "bidPrice": 7704,
    "midPrice": 7704.25,
    "askPrice": 7704.5,
    "impactBidPrice": 7704.1602,
    "impactMidPrice": 7704.5,
    "impactAskPrice": 7704.7538,
    "hasLiquidity": true,
    "openInterest": 629338397,
    "openValue": 8165036362678,
    "fairMethod": "FundingRate",
    "fairBasisRate": 0.406245,
    "fairBasis": 2.3,
    "fairPrice": 7708.01,
    "markMethod": "FairPrice",
    "markPrice": 7708.01,
    "indicativeTaxRate": 0,
    "indicativeSettlePrice": 7705.71,
    "optionUnderlyingPrice": null,
    "settledPrice": null,
    "timestamp": "2018-06-07T13:33:37.389Z"
  }
]

なるほど、使えそう🎵

REST APIを直呼びしてもいいのだけれど、せっかくだからccxtでそれらしいAPIが実装されていないか探ってみよう。

●ccxtを探索→あ、あった!

ccxtライブラリの中に「instrument」系のAPIが用意されているか探索します。

うん、どうやら存在しているみたいです。
さっそくparamsに設定してAPIをキックしてみましょう。

●実行してみよう

実行したAPIとパラメータは以下です。

// exchangeはccxtのBitMEXオブジェクトです
let ret = await exchange.publicGetInstrument(
    {
        symbol: 'XBTUSD'
        , reverse: true
    }
);

実行結果は

戻り値は配列が1つ。その中にちゃんと値が格納されているようです。
よかった、よかった。

戻り値の全容は

[ { symbol: 'XBTUSD',
    rootSymbol: 'XBT',
    state: 'Open',
    typ: 'FFWCSX',
    listing: '2016-05-04T12:00:00.000Z',
    front: '2016-05-04T12:00:00.000Z',
    expiry: null,
    settle: null,
    relistInterval: null,
    inverseLeg: '',
    sellLeg: '',
    buyLeg: '',
    optionStrikePcnt: null,
    optionStrikeRound: null,
    optionStrikePrice: null,
    optionMultiplier: null,
    positionCurrency: 'USD',
    underlying: 'XBT',
    quoteCurrency: 'USD',
    underlyingSymbol: 'XBT=',
    reference: 'BMEX',
    referenceSymbol: '.BXBT',
    calcInterval: null,
    publishInterval: null,
    publishTime: null,
    maxOrderQty: 10000000,
    maxPrice: 1000000,
    lotSize: 1,
    tickSize: 0.5,
    multiplier: -100000000,
    settlCurrency: 'XBt',
    underlyingToPositionMultiplier: null,
    underlyingToSettleMultiplier: -100000000,
    quoteToSettleMultiplier: null,
    isQuanto: false,
    isInverse: true,
    initMargin: 0.01,
    maintMargin: 0.005,
    riskLimit: 20000000000,
    riskStep: 10000000000,
    limit: null,
    capped: false,
    taxed: true,
    deleverage: true,
    makerFee: -0.00025,
    takerFee: 0.00075,
    settlementFee: 0,
    insuranceFee: 0,
    fundingBaseSymbol: '.XBTBON8H',
    fundingQuoteSymbol: '.USDBON8H',
    fundingPremiumSymbol: '.XBTUSDPI8H',
    fundingTimestamp: '2018-06-07T20:00:00.000Z',
    fundingInterval: '2000-01-01T08:00:00.000Z',
    fundingRate: 0.000173,
    indicativeFundingRate: 0.0001,
    rebalanceTimestamp: null,
    rebalanceInterval: null,
    openingTimestamp: '2018-06-07T12:00:00.000Z',
    closingTimestamp: '2018-06-07T14:00:00.000Z',
    sessionInterval: '2000-01-01T02:00:00.000Z',
    prevClosePrice: 7684.04,
    limitDownPrice: null,
    limitUpPrice: null,
    bankruptLimitDownPrice: null,
    bankruptLimitUpPrice: null,
    prevTotalVolume: 44857274050,
    totalVolume: 44869644202,
    volume: 12370152,
    volume24h: 265465712,
    prevTotalTurnover: 620020959561767,
    totalTurnover: 620181699583247,
    turnover: 160740021480,
    turnover24h: 3469812180830,
    prevPrice24h: 7641,
    vwap: 7651.1094,
    highPrice: 7760,
    lowPrice: 7538,
    lastPrice: 7719.5,
    lastPriceProtected: 7719.5,
    lastTickDirection: 'MinusTick',
    lastChangePcnt: 0.0103,
    bidPrice: 7719.5,
    midPrice: 7719.75,
    askPrice: 7720,
    impactBidPrice: 7709.5058,
    impactMidPrice: 7715.75,
    impactAskPrice: 7722.0077,
    hasLiquidity: true,
    openInterest: 176092294,
    openValue: 2286910622178,
    fairMethod: 'FundingRate',
    fairBasisRate: 0.189435,
    fairBasis: 1.02,
    fairPrice: 7699.79,
    markMethod: 'FairPrice',
    markPrice: 7699.79,
    indicativeTaxRate: 0,
    indicativeSettlePrice: 7698.77,
    optionUnderlyingPrice: null,
    settledPrice: null,
    timestamp: '2018-06-07T13:51:27.850Z' } ]

となり、期待した動作はしていると思われます。

ですが、戻り値がものすごく多いのでcolumns指定で戻り値を「lastPrice」だけにしてみましょう。

与えるパラメータは

let ret = await exchange.publicGetInstrument(
    {
        symbol: 'XBTUSD'
        , reverse: true
        , columns: ['lastPrice']
    }
);

です。
実行結果は

[ { symbol: 'XBTUSD',
    timestamp: '2018-06-07T13:56:22.233Z',
    lastPrice: 7706.5 } ]

となり、かなりスッキリしましたね。

●本家fetchTickerの値と比較

本家fetchTickerも取得してみましたが、

{ symbol: 'BTC/USD',
  timestamp: 1528379790533,
  datetime: '2018-06-07T13:56:30.533Z',
  high: 7760,
  low: 7642.5,
  bid: 7706,
  bidVolume: undefined,
  ask: 7706.5,
  askVolume: undefined,
  vwap: 7701.1937,
  open: 7654,
  close: 7706.5,
  last: 7706.5,
  previousClose: undefined,
  change: 52.5,
  percentage: 0.6859158609877188,
  average: 7680.25,
  baseVolume: 12653.307064050001,
  quoteVolume: 97434171,
  info:
   { timestamp: '2018-06-08T00:00:00.000Z',
     symbol: 'XBTUSD',
     open: 7654,
     high: 7760,
     low: 7642.5,
     close: 7706.5,
     trades: 17591,
     volume: 97434171,
     vwap: 7701.1937,
     lastSize: 1406,
     turnover: 1265330706405,
     homeNotional: 12653.307064050001,
     foreignNotional: 97434171 } }

のようになり、instrumentの値「lastPrice」とtickerの値「last」は同じに見えます。
これなら使えそうですね。

とりあえず一晩ずっとループさせてAPIを5秒間隔で実行しましたが、fetchTickerのように開始数秒後でAPI例外を食らい続けることはなかったようです。
1秒間隔でもまず問題なかった。(時々APIコール後の戻りがかなり遅い時があった)

しかし、100ミリ秒間隔でぶん回したら数回に一回はAPI例外を食らいました。限度を心得ないとダメのようです。

このAPIがいつまで有効かはBitMEXさんの腹づもりにかかっていると思いますが、別の機会にwebsocket版や他の手段でのticker情報取得にトライしてみたいと思います。

ご期待いただければ「スキ」ボタンをポチっと、「フォロー」ボタンをクリック、よろしくお願いいたします。

note: https://note.mu/o_matsuo

twitter: @o_matsuo
もフォローしてくださると、喜びます。

あ、それから私の師匠である
コンドウ様のnoteもポチっとしていただけると、さらに喜びます。

みなさんと一緒に、楽しいBotライフを🎵

ソフトウェア・エンジニアを40年以上やってます。 「Botを作りたいけど敷居が高い」と思われている方にも「わかる」「できる」を感じてもらえるように頑張ります。 よろしくお願い致します。