def test_funding():
    t = Funding(
        'BINANCE_FUTURES',
        'BTC-USD-PERP',
        Decimal(10),
        Decimal(100),
        time(),
        time(),
    )
    d = t.to_dict(numeric_type=str)
    d = json.dumps(d)
    d = json.loads(d)
    t2 = Funding.from_dict(d)
    assert t == t2
Example #2
0
    async def _funding(self, msg: dict, pair: str, timestamp: float):
        if 'funding_rate' in msg:
            f = Funding(
                self.id,
                pair,
                None,
                msg['funding_rate'],
                self.timestamp_normalize(msg['next_funding_rate_time']),
                self.timestamp_normalize(msg['time']),
                predicted_rate=msg['funding_rate_prediction'],
                raw=msg
            )
            await self.callback(FUNDING, f, timestamp)

        oi = msg['openInterest']
        if pair in self._open_interest_cache and oi == self._open_interest_cache[pair]:
            return
        self._open_interest_cache[pair] = oi
        o = OpenInterest(
            self.id,
            pair,
            oi,
            self.timestamp_normalize(msg['time']),
            raw=msg
        )
        await self.callback(OPEN_INTEREST, o, timestamp)
Example #3
0
 async def _funding(self, msg: dict, timestamp: float):
     for update in msg['data']:
         f = Funding(self.id,
                     self.exchange_symbol_to_std_symbol(update['instId']),
                     None,
                     Decimal(update['fundingRate']),
                     None,
                     self.timestamp_normalize(int(update['fundingTime'])),
                     predicted_rate=Decimal(update['nextFundingRate']),
                     raw=update)
         await self.callback(FUNDING, f, timestamp)
Example #4
0
    async def _funding(self, pairs):
        """
        {
            "status": "ok",
            "data": {
                "estimated_rate": "0.000100000000000000",
                "funding_rate": "-0.000362360011416593",
                "contract_code": "BTC-USD",
                "symbol": "BTC",
                "fee_asset": "BTC",
                "funding_time": "1603872000000",
                "next_funding_time": "1603900800000"
            },
            "ts": 1603866304635
        }
        """
        while True:
            for pair in pairs:
                # use symbol to look up correct endpoint
                sym = str_to_symbol(self.exchange_symbol_to_std_symbol(pair))
                endpoint = None
                for ep in self.rest_endpoints:
                    if sym.quote in ep.instrument_filter[1]:
                        endpoint = self.rest_endpoints[0].route(
                            'funding').format(pair)

                data = await self.http_conn.read(endpoint)
                data = json.loads(data, parse_float=Decimal)
                received = time.time()
                update = (data['data']['funding_rate'],
                          self.timestamp_normalize(
                              int(data['data']['next_funding_time'])))
                if pair in self.funding_updates and self.funding_updates[
                        pair] == update:
                    await asyncio.sleep(1)
                    continue
                self.funding_updates[pair] = update

                f = Funding(self.id,
                            self.exchange_symbol_to_std_symbol(pair),
                            None,
                            Decimal(data['data']['funding_rate']),
                            self.timestamp_normalize(
                                int(data['data']['next_funding_time'])),
                            self.timestamp_normalize(
                                int(data['data']['funding_time'])),
                            predicted_rate=Decimal(
                                data['data']['estimated_rate']),
                            raw=data)
                await self.callback(FUNDING, f, received)
                await asyncio.sleep(0.1)
Example #5
0
def test_funding_to_dict():
    data = {
        "exchange":
        "FTX",
        "symbol":
        "BTC-USD-PERP",
        "mark_price":
        Decimal("50000"),
        "rate":
        Decimal("0.0002"),
        "next_funding_time":
        Exchange.timestamp_normalize(
            datetime.datetime(2021,
                              12,
                              26,
                              21,
                              0,
                              tzinfo=datetime.timezone.utc)),
        "predicted_rate":
        Decimal("0.0"),
        "timestamp":
        Exchange.timestamp_normalize(
            datetime.datetime(2021,
                              12,
                              26,
                              20,
                              0,
                              tzinfo=datetime.timezone.utc)),
    }

    f = Funding(
        **data,
        raw=data,
    )
    f_dict = f.to_dict(numeric_type=float, none_to=None)

    assert f_dict["predicted_rate"] == data["predicted_rate"]
Example #6
0
    async def _funding(self, pairs: Iterable):
        """
            {
              "success": true,
              "result": [
                {
                  "future": "BTC-PERP",
                  "rate": 0.0025,
                  "time": "2019-06-02T08:00:00+00:00"
                }
              ]
            }
        """
        while True:
            for pair in pairs:
                if '-PERP' not in pair:
                    continue
                data = await self.http_conn.read(
                    f"https://ftx.com/api/funding_rates?future={pair}")
                data = json.loads(data, parse_float=Decimal)
                data2 = await self.http_conn.read(
                    f"https://ftx.com/api/futures/{pair}/stats")
                data2 = json.loads(data2, parse_float=Decimal)
                received = time()
                data['predicted_rate'] = Decimal(
                    data2['result']['nextFundingRate'])

                last_update = self._funding_cache.get(pair, None)
                update = str(data['result'][0]['rate']) + str(
                    data['result'][0]['time']) + str(data['predicted_rate'])
                if last_update and last_update == update:
                    continue
                else:
                    self._funding_cache[pair] = update

                f = Funding(self.id,
                            self.exchange_symbol_to_std_symbol(
                                data['result'][0]['future']),
                            None,
                            data['result'][0]['rate'],
                            self.timestamp_normalize(
                                data2['result']['nextFundingTime']),
                            self.timestamp_normalize(
                                data['result'][0]['time']),
                            predicted_rate=data['predicted_rate'],
                            raw=[data, data2])
                await self.callback(FUNDING, f, received)
                await asyncio.sleep(0.1)
            await asyncio.sleep(60)
Example #7
0
 async def _funding(self, msg: dict, timestamp: float):
     """
     {'table': 'funding',
      'action': 'partial',
      'keys': ['timestamp', 'symbol'],
      'types': {
          'timestamp': 'timestamp',
          'symbol': 'symbol',
          'fundingInterval': 'timespan',
          'fundingRate': 'float',
          'fundingRateDaily': 'float'
         },
      'foreignKeys': {
          'symbol': 'instrument'
         },
      'attributes': {
          'timestamp': 'sorted',
          'symbol': 'grouped'
         },
      'filter': {'symbol': 'XBTUSD'},
      'data': [{
          'timestamp': '2018-08-21T20:00:00.000Z',
          'symbol': 'XBTUSD',
          'fundingInterval': '2000-01-01T08:00:00.000Z',
          'fundingRate': Decimal('-0.000561'),
          'fundingRateDaily': Decimal('-0.001683')
         }]
     }
     """
     for data in msg['data']:
         ts = self.timestamp_normalize(data['timestamp'])
         interval = data['fundingInterval']
         f = Funding(
             self.id,
             self.exchange_symbol_to_std_symbol(data['symbol']),
             None,
             data['fundingRate'],
             self.timestamp_normalize(data['timestamp'] + timedelta(hours=interval.hour)),
             ts,
             raw=data
         )
         await self.callback(FUNDING, f, timestamp)
Example #8
0
    async def _funding(self, msg: dict, timestamp: float):
        """
        {
            "e": "markPriceUpdate",  // Event type
            "E": 1562305380000,      // Event time
            "s": "BTCUSDT",          // Symbol
            "p": "11185.87786614",   // Mark price
            "r": "0.00030000",       // Funding rate
            "T": 1562306400000       // Next funding time
        }

        BinanceFutures
        {
            "e": "markPriceUpdate",     // Event type
            "E": 1562305380000,         // Event time
            "s": "BTCUSDT",             // Symbol
            "p": "11185.87786614",      // Mark price
            "i": "11784.62659091"       // Index price
            "P": "11784.25641265",      // Estimated Settle Price, only useful in the last hour before the settlement starts
            "r": "0.00030000",          // Funding rate
            "T": 1562306400000          // Next funding time
        }
        """
        next_time = self.timestamp_normalize(
            msg['T']) if msg['T'] > 0 else None
        rate = Decimal(msg['r']) if msg['r'] else None
        if next_time is None:
            rate = None

        f = Funding(self.id,
                    self.exchange_symbol_to_std_symbol(msg['s']),
                    Decimal(msg['p']),
                    rate,
                    next_time,
                    self.timestamp_normalize(msg['E']),
                    predicted_rate=Decimal(msg['P'])
                    if 'P' in msg and msg['P'] is not None else None,
                    raw=msg)
        await self.callback(FUNDING, f, timestamp)
Example #9
0
    async def _funding(self, pairs):
        """
        {
            "status": "ok",
            "data": {
                "estimated_rate": "0.000100000000000000",
                "funding_rate": "-0.000362360011416593",
                "contract_code": "BTC-USD",
                "symbol": "BTC",
                "fee_asset": "BTC",
                "funding_time": "1603872000000",
                "next_funding_time": "1603900800000"
            },
            "ts": 1603866304635
        }
        """
        while True:
            for pair in pairs:
                data = await self.http_conn.read(f'https://api.hbdm.com/swap-api/v1/swap_funding_rate?contract_code={pair}')
                data = json.loads(data, parse_float=Decimal)
                received = time.time()
                update = (data['data']['funding_rate'], self.timestamp_normalize(int(data['data']['next_funding_time'])))
                if pair in self.funding_updates and self.funding_updates[pair] == update:
                    await asyncio.sleep(1)
                    continue
                self.funding_updates[pair] = update

                f = Funding(
                    self.id,
                    self.exchange_symbol_to_std_symbol(pair),
                    None,
                    Decimal(data['data']['funding_rate']),
                    self.timestamp_normalize(int(data['data']['next_funding_time'])),
                    self.timestamp_normalize(int(data['data']['funding_time'])),
                    predicted_rate=Decimal(data['data']['estimated_rate']),
                    raw=data
                )
                await self.callback(FUNDING, f, received)
                await asyncio.sleep(0.1)
Example #10
0
    async def _instrument_info(self, msg: dict, timestamp: float):
        """
        ### Snapshot type update
        {
        "topic": "instrument_info.100ms.BTCUSD",
        "type": "snapshot",
        "data": {
            "id": 1,
            "symbol": "BTCUSD",                           //instrument name
            "last_price_e4": 81165000,                    //the latest price
            "last_tick_direction": "ZeroPlusTick",        //the direction of last tick:PlusTick,ZeroPlusTick,MinusTick,
                                                          //ZeroMinusTick
            "prev_price_24h_e4": 81585000,                //the price of prev 24h
            "price_24h_pcnt_e6": -5148,                   //the current last price percentage change from prev 24h price
            "high_price_24h_e4": 82900000,                //the highest price of prev 24h
            "low_price_24h_e4": 79655000,                 //the lowest price of prev 24h
            "prev_price_1h_e4": 81395000,                 //the price of prev 1h
            "price_1h_pcnt_e6": -2825,                    //the current last price percentage change from prev 1h price
            "mark_price_e4": 81178500,                    //mark price
            "index_price_e4": 81172800,                   //index price
            "open_interest": 154418471,                   //open interest quantity - Attention, the update is not
                                                          //immediate - slowest update is 1 minute
            "open_value_e8": 1997561103030,               //open value quantity - Attention, the update is not
                                                          //immediate - the slowest update is 1 minute
            "total_turnover_e8": 2029370141961401,        //total turnover
            "turnover_24h_e8": 9072939873591,             //24h turnover
            "total_volume": 175654418740,                 //total volume
            "volume_24h": 735865248,                      //24h volume
            "funding_rate_e6": 100,                       //funding rate
            "predicted_funding_rate_e6": 100,             //predicted funding rate
            "cross_seq": 1053192577,                      //sequence
            "created_at": "2018-11-14T16:33:26Z",
            "updated_at": "2020-01-12T18:25:16Z",
            "next_funding_time": "2020-01-13T00:00:00Z",  //next funding time
                                                          //the rest time to settle funding fee
            "countdown_hour": 6                           //the remaining time to settle the funding fee
        },
        "cross_seq": 1053192634,
        "timestamp_e6": 1578853524091081                  //the timestamp when this information was produced
        }

        ### Delta type update
        {
        "topic": "instrument_info.100ms.BTCUSD",
        "type": "delta",
        "data": {
            "delete": [],
            "update": [
                {
                    "id": 1,
                    "symbol": "BTCUSD",
                    "prev_price_24h_e4": 81565000,
                    "price_24h_pcnt_e6": -4904,
                    "open_value_e8": 2000479681106,
                    "total_turnover_e8": 2029370495672976,
                    "turnover_24h_e8": 9066215468687,
                    "volume_24h": 735316391,
                    "cross_seq": 1053192657,
                    "created_at": "2018-11-14T16:33:26Z",
                    "updated_at": "2020-01-12T18:25:25Z"
                }
            ],
            "insert": []
        },
        "cross_seq": 1053192657,
        "timestamp_e6": 1578853525691123
        }
        """
        update_type = msg['type']

        if update_type == 'snapshot':
            updates = [msg['data']]
        else:
            updates = msg['data']['update']

        for info in updates:
            if msg['topic'] in self._instrument_info_cache and self._instrument_info_cache[msg['topic']] == updates:
                continue
            else:
                self._instrument_info_cache[msg['topic']] = updates

            ts = int(msg['timestamp_e6']) / 1_000_000

            if 'open_interest' in info:
                oi = OpenInterest(
                    self.id,
                    self.exchange_symbol_to_std_symbol(info['symbol']),
                    Decimal(info['open_interest']),
                    ts,
                    raw=info
                )
                await self.callback(OPEN_INTEREST, oi, timestamp)

            if 'index_price_e4' in info:
                i = Index(
                    self.id,
                    self.exchange_symbol_to_std_symbol(info['symbol']),
                    Decimal(info['index_price_e4']) * Decimal('1e-4'),
                    ts,
                    raw=info
                )
                await self.callback(INDEX, i, timestamp)

            if 'funding_rate_e6' in info:
                f = Funding(
                    self.id,
                    self.exchange_symbol_to_std_symbol(info['symbol']),
                    None,
                    Decimal(info['funding_rate_e6']) * Decimal('1e-6'),
                    info['next_funding_time'].timestamp(),
                    ts,
                    predicted_rate=Decimal(info['predicted_funding_rate_e6']) * Decimal('1e-6'),
                    raw=info
                )
                await self.callback(FUNDING, f, timestamp)
Example #11
0
    async def _ticker(self, msg: dict, timestamp: float):
        '''
        {
            "params" : {
                "data" : {
                    "timestamp" : 1550652954406,
                    "stats" : {
                        "volume" : null,
                        "low" : null,
                        "high" : null
                    },
                    "state" : "open",
                    "settlement_price" : 3960.14,
                    "open_interest" : 0.12759952124659626,
                    "min_price" : 3943.21,
                    "max_price" : 3982.84,
                    "mark_price" : 3940.06,
                    "last_price" : 3906,
                    "instrument_name" : "BTC-PERPETUAL",
                    "index_price" : 3918.51,
                    "funding_8h" : 0.01520525,
                    "current_funding" : 0.00499954,
                    "best_bid_price" : 3914.97,
                    "best_bid_amount" : 40,
                    "best_ask_price" : 3996.61,
                    "best_ask_amount" : 50
                    },
                "channel" : "ticker.BTC-PERPETUAL.raw"
            },
            "method" : "subscription",
            "jsonrpc" : "2.0"}
        '''
        pair = self.exchange_symbol_to_std_symbol(
            msg['params']['data']['instrument_name'])
        ts = self.timestamp_normalize(msg['params']['data']['timestamp'])
        t = Ticker(self.id,
                   pair,
                   Decimal(msg["params"]["data"]['best_bid_price']),
                   Decimal(msg["params"]["data"]['best_ask_price']),
                   ts,
                   raw=msg)
        await self.callback(TICKER, t, timestamp)

        if "current_funding" in msg["params"]["data"] and "funding_8h" in msg[
                "params"]["data"]:
            f = Funding(self.id,
                        pair,
                        Decimal(msg['params']['data']['mark_price']),
                        Decimal(msg["params"]["data"]["current_funding"]),
                        None,
                        ts,
                        raw=msg)
            await self.callback(FUNDING, f, timestamp)

        oi = msg['params']['data']['open_interest']
        if pair in self._open_interest_cache and oi == self._open_interest_cache[
                pair]:
            return
        self._open_interest_cache[pair] = oi
        o = OpenInterest(self.id, pair, Decimal(oi), ts, raw=msg)
        await self.callback(OPEN_INTEREST, o, timestamp)