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
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)
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)
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)
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"]
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)
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)
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)
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)
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)
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)