def choose_pair( self, timestamp: Timestamp, price_query: Callable[[Asset, Asset, Timestamp], FVal], ) -> TradePair: """Choose a random pair to trade from the available pairs at the selected timestamp""" choices = set(list(self.asset_pairs['result'].keys())) found = False while len(choices) != 0: pair = random.choice(tuple(choices)) choices.remove(pair) pair = kraken_to_world_pair(pair) base, quote = pair_get_assets(pair) kbase = base.to_kraken() kquote = quote.to_kraken() if kbase in self.balances_dict or kquote in self.balances_dict: # Before choosing make sure that at the selected timestamp both of # the pair assets exist (had a price) if not assets_exist_at_time(base, quote, timestamp, price_query): continue found = True break if not found: raise ValueError( 'Could not find a pair to trade with the current funds') return trade_pair_from_assets(base, quote)
def kraken_to_world_pair(pair: str) -> TradePair: """Turns a pair from kraken to our pair type Can throw: - UknownAsset if one of the assets of the pair are not known - UnprocessableKrakenPair if the pair can't be processed and split into its base/quote assets """ # handle dark pool pairs if pair[-2:] == '.d': pair = pair[:-2] if pair[0:3] in KRAKEN_ASSETS: base_asset_str = pair[0:3] quote_asset_str = pair[3:] elif pair[0:4] in KRAKEN_ASSETS: base_asset_str = pair[0:4] quote_asset_str = pair[4:] else: raise UnprocessableTradePair(pair) base_asset = asset_from_kraken(base_asset_str) quote_asset = asset_from_kraken(quote_asset_str) return trade_pair_from_assets(base_asset, quote_asset)
def choose_pair( self, timestamp: Timestamp, price_query: Callable[[Asset, Asset, Timestamp], FVal], ) -> TradePair: """Choose a random pair to trade from the available pairs at the selected timestamp""" choices = set(self._symbols_to_pair.keys()) found = False while len(choices) != 0: pair = random.choice(tuple(choices)) choices.remove(pair) binance_pair = self._symbols_to_pair[pair] bbase = binance_pair.binance_base_asset bquote = binance_pair.binance_quote_asset try: base = asset_from_binance(bbase) quote = asset_from_binance(bquote) except UnsupportedAsset: continue if bbase in self.balances_dict or bquote in self.balances_dict: if bbase in DISALLOWED_ASSETS or bquote in DISALLOWED_ASSETS: continue # Before choosing make sure that at the selected timestamp both of # the pair assets exist (had a price) if not assets_exist_at_time(base, quote, timestamp, price_query): continue found = True break if not found: raise ValueError('Could not find a pair to trade with the current funds') return trade_pair_from_assets(base, quote)
def kraken_to_world_pair(pair: str) -> TradePair: """Turns a pair from kraken to our pair type Can throw: - UknownAsset if one of the assets of the pair are not known - DeserializationError if one of the assets is not a sting - UnprocessableTradePair if the pair can't be processed and split into its base/quote assets """ # handle dark pool pairs if pair[-2:] == '.d': pair = pair[:-2] if len(pair) == 6 and pair[0:3] in ('EUR', 'USD', 'AUD'): # This is for the FIAT to FIAT pairs that kraken introduced base_asset_str = pair[0:3] quote_asset_str = pair[3:] elif pair == 'ETHDAI': return trade_pair_from_assets(base=A_ETH, quote=A_DAI) elif pair == 'ETH2.SETH': return trade_pair_from_assets(base=A_ETH2, quote=A_ETH) elif pair[0:2] in KRAKEN_TO_WORLD: base_asset_str = pair[0:2] quote_asset_str = pair[2:] elif pair[0:3] in KRAKEN_TO_WORLD: base_asset_str = pair[0:3] quote_asset_str = pair[3:] elif pair[0:3] in ('XBT', 'ETH', 'XDG', 'LTC', 'XRP'): # Some assets can have the 'X' prefix omitted for some pairs base_asset_str = pair[0:3] quote_asset_str = pair[3:] elif pair[0:4] in KRAKEN_TO_WORLD: base_asset_str = pair[0:4] quote_asset_str = pair[4:] elif pair[0:5] in KRAKEN_TO_WORLD: base_asset_str = pair[0:5] quote_asset_str = pair[5:] else: raise UnprocessableTradePair(pair) base_asset = asset_from_kraken(base_asset_str) quote_asset = asset_from_kraken(quote_asset_str) return trade_pair_from_assets(base_asset, quote_asset)
def kraken_to_world_pair(pair: str) -> TradePair: """Turns a pair from kraken to our pair type Can throw: - UknownAsset if one of the assets of the pair are not known - UnprocessableKrakenPair if the pair can't be processed and split into its base/quote assets """ # handle dark pool pairs if pair[-2:] == '.d': pair = pair[:-2] if pair == 'ETHDAI': return trade_pair_from_assets(base=A_ETH, quote=A_DAI) elif pair[0:2] in KRAKEN_TO_WORLD: base_asset_str = pair[0:2] quote_asset_str = pair[2:] elif pair[0:3] in KRAKEN_TO_WORLD: base_asset_str = pair[0:3] quote_asset_str = pair[3:] elif pair[0:3] in ('XBT', 'ETH', 'XDG'): # Some assets can have the 'X' prefix omitted for some pairs base_asset_str = pair[0:3] quote_asset_str = pair[3:] elif pair[0:4] in KRAKEN_TO_WORLD: base_asset_str = pair[0:4] quote_asset_str = pair[4:] elif pair[0:5] in KRAKEN_TO_WORLD: base_asset_str = pair[0:5] quote_asset_str = pair[5:] else: raise UnprocessableTradePair(pair) base_asset = asset_from_kraken(base_asset_str) quote_asset = asset_from_kraken(quote_asset_str) return trade_pair_from_assets(base_asset, quote_asset)
def bittrex_pair_to_world(given_pair: str) -> TradePair: """ Turns a pair written in the bittrex way to Rotkehlchen way Throws: - UnsupportedAsset due to asset_from_bittrex() - UnprocessableTradePair if the pair can't be split into its parts """ if not isinstance(given_pair, str): raise DeserializationError( f'Could not deserialize bittrex trade pair. Expected a string ' f'but found {type(given_pair)}', ) pair = TradePair(given_pair.replace('-', '_')) base_currency = asset_from_bittrex(get_pair_position_str(pair, 'first')) quote_currency = asset_from_bittrex(get_pair_position_str(pair, 'second')) # Since in Bittrex the base currency is the cost currency, iow in Bittrex # for BTC_ETH we buy ETH with BTC and sell ETH for BTC, we need to turn it # into the Rotkehlchen way which is following the base/quote approach. pair = trade_pair_from_assets(quote_currency, base_currency) return pair
def trade_from_binance( binance_trade: Dict, binance_symbols_to_pair: Dict[str, BinancePair], ) -> Trade: """Turn a binance trade returned from trade history to our common trade history format From the official binance api docs (01/09/18): https://github.com/binance-exchange/binance-official-api-docs/blob/62ff32d27bb32d9cc74d63d547c286bb3c9707ef/rest-api.md#terminology base asset refers to the asset that is the quantity of a symbol. quote asset refers to the asset that is the price of a symbol. Throws: - UnsupportedAsset due to asset_from_binance - DeserializationError due to unexpected format of dict entries - KeyError due to dict entries missing an expected entry """ amount = deserialize_asset_amount(binance_trade['qty']) rate = deserialize_price(binance_trade['price']) if binance_trade['symbol'] not in binance_symbols_to_pair: raise DeserializationError( f'Error reading a binance trade. Could not find ' f'{binance_trade["symbol"]} in binance_symbols_to_pair', ) binance_pair = binance_symbols_to_pair[binance_trade['symbol']] timestamp = deserialize_timestamp_from_binance(binance_trade['time']) base_asset = asset_from_binance(binance_pair.binance_base_asset) quote_asset = asset_from_binance(binance_pair.binance_quote_asset) if binance_trade['isBuyer']: order_type = TradeType.BUY # e.g. in RDNETH we buy RDN by paying ETH else: order_type = TradeType.SELL fee_currency = asset_from_binance(binance_trade['commissionAsset']) fee = deserialize_fee(binance_trade['commission']) log.debug( 'Processing binance Trade', sensitive_log=True, amount=amount, rate=rate, timestamp=timestamp, pair=binance_trade['symbol'], base_asset=base_asset, quote=quote_asset, order_type=order_type, commision_asset=binance_trade['commissionAsset'], fee=fee, ) return Trade( timestamp=timestamp, location=Location.BINANCE, pair=trade_pair_from_assets(base_asset, quote_asset), trade_type=order_type, amount=amount, rate=rate, fee=fee, fee_currency=fee_currency, link=str(binance_trade['id']), )
def trade_from_poloniex(poloniex_trade: Dict[str, Any], pair: TradePair) -> Trade: """Turn a poloniex trade returned from poloniex trade history to our common trade history format Throws: - UnsupportedAsset due to asset_from_poloniex() - DeserializationError due to the data being in unexpected format - UnprocessableTradePair due to the pair data being in an unexpected format """ try: trade_type = deserialize_trade_type(poloniex_trade['type']) amount = deserialize_asset_amount(poloniex_trade['amount']) rate = deserialize_price(poloniex_trade['rate']) perc_fee = deserialize_fee(poloniex_trade['fee']) base_currency = asset_from_poloniex(get_pair_position_str(pair, 'first')) quote_currency = asset_from_poloniex(get_pair_position_str(pair, 'second')) timestamp = deserialize_timestamp_from_poloniex_date(poloniex_trade['date']) except KeyError as e: raise DeserializationError( f'Poloniex trade deserialization error. Missing key entry for {str(e)} in trade dict', ) cost = rate * amount if trade_type == TradeType.BUY: fee = Fee(amount * perc_fee) fee_currency = quote_currency elif trade_type == TradeType.SELL: fee = Fee(cost * perc_fee) fee_currency = base_currency else: raise DeserializationError(f'Got unexpected trade type "{trade_type}" for poloniex trade') if poloniex_trade['category'] == 'settlement': if trade_type == TradeType.BUY: trade_type = TradeType.SETTLEMENT_BUY else: trade_type = TradeType.SETTLEMENT_SELL log.debug( 'Processing poloniex Trade', sensitive_log=True, timestamp=timestamp, order_type=trade_type, pair=pair, base_currency=base_currency, quote_currency=quote_currency, amount=amount, fee=fee, rate=rate, ) # Use the converted assets in our pair pair = trade_pair_from_assets(base_currency, quote_currency) # Since in Poloniex the base currency is the cost currency, iow in poloniex # for BTC_ETH we buy ETH with BTC and sell ETH for BTC, we need to turn it # into the Rotkehlchen way which is following the base/quote approach. pair = invert_pair(pair) return Trade( timestamp=timestamp, location=Location.POLONIEX, pair=pair, trade_type=trade_type, amount=amount, rate=rate, fee=fee, fee_currency=fee_currency, link=str(poloniex_trade['globalTradeID']), )
def test_trade_pair_from_assets(): pair = trade_pair_from_assets(A_BTC, A_EUR) assert pair == TradePair('BTC_EUR')