Beispiel #1
0
    def _deserialize_asset_movement(
        raw_movement: Dict[str, Any], ) -> AssetMovement:
        """Process a deposit/withdrawal user transaction from Bitstamp and
        deserialize it.

        Can raise DeserializationError.

        From Bitstamp documentation, deposits/withdrawals can have a fee
        (the amount is expected to be in the currency involved)
        https://www.bitstamp.net/fee-schedule/

        Endpoint docs:
        https://www.bitstamp.net/api/#user-transactions
        """
        type_ = deserialize_int_from_str(raw_movement['type'],
                                         'bitstamp asset movement')
        category: AssetMovementCategory
        if type_ == 0:
            category = AssetMovementCategory.DEPOSIT
        elif type_ == 1:
            category = AssetMovementCategory.WITHDRAWAL
        else:
            raise AssertionError(
                f'Unexpected Bitstamp asset movement case: {type_}.')

        timestamp = deserialize_timestamp_from_bitstamp_date(
            raw_movement['datetime'])
        amount: FVal
        fee_asset: Asset
        for symbol in BITSTAMP_ASSET_MOVEMENT_SYMBOLS:
            amount = deserialize_asset_amount(raw_movement.get(symbol, '0'))
            if amount != ZERO:
                fee_asset = asset_from_bitstamp(symbol)
                break

        if amount == ZERO:
            raise DeserializationError(
                'Could not deserialize Bitstamp asset movement from user transaction. '
                f'Unexpected asset amount combination found in: {raw_movement}.',
            )

        asset_movement = AssetMovement(
            timestamp=timestamp,
            location=Location.BITSTAMP,
            category=category,
            address=None,  # requires query "crypto_transactions" endpoint
            transaction_id=None,  # requires query "crypto_transactions" endpoint
            asset=fee_asset,
            amount=abs(amount),
            fee_asset=fee_asset,
            fee=deserialize_fee(raw_movement['fee']),
            link=str(raw_movement['id']),
        )
        return asset_movement
Beispiel #2
0
    def _deserialize_trade(
            self,
            raw_trade: Dict[str, Any],
    ) -> Trade:
        """Process a trade user transaction from Bitstamp and deserialize it.

        Can raise DeserializationError.
        """
        timestamp = deserialize_timestamp_from_bitstamp_date(raw_trade['datetime'])
        trade_pair_data = self._get_trade_pair_data_from_transaction(raw_trade)
        base_asset_amount = deserialize_asset_amount(
            raw_trade[trade_pair_data.base_asset_symbol],
        )
        quote_asset_amount = deserialize_asset_amount(
            raw_trade[trade_pair_data.quote_asset_symbol],
        )
        rate = deserialize_price(raw_trade[trade_pair_data.pair])
        fee_currency = trade_pair_data.quote_asset
        if base_asset_amount >= ZERO:
            trade_type = TradeType.BUY
        else:
            if quote_asset_amount < 0:
                raise DeserializationError(
                    f'Unexpected bitstamp trade format. Both base and quote '
                    f'amounts are negative: {raw_trade}',
                )
            trade_type = TradeType.SELL

        trade = Trade(
            timestamp=timestamp,
            location=Location.BITSTAMP,
            base_asset=trade_pair_data.base_asset,
            quote_asset=trade_pair_data.quote_asset,
            trade_type=trade_type,
            amount=AssetAmount(abs(base_asset_amount)),
            rate=rate,
            fee=deserialize_fee(raw_trade['fee']),
            fee_currency=fee_currency,
            link=str(raw_trade['id']),
            notes='',
        )
        return trade
Beispiel #3
0
    def _deserialize_trade(
            self,
            raw_trade: Dict[str, Any],
    ) -> Trade:
        """Process a trade user transaction from Bitstamp and deserialize it.

        Can raise DeserializationError.
        """
        timestamp = deserialize_timestamp_from_bitstamp_date(raw_trade['datetime'])
        trade_pair_data = self._get_trade_pair_data_from_transaction(raw_trade)
        base_asset_amount = deserialize_asset_amount(
            raw_trade[trade_pair_data.base_asset_symbol],
        )
        quote_asset_amount = deserialize_asset_amount(
            raw_trade[trade_pair_data.quote_asset_symbol],
        )

        if base_asset_amount >= ZERO:
            trade_type = TradeType.BUY
            amount = base_asset_amount
            fee_currency = trade_pair_data.quote_asset
        else:
            trade_type = TradeType.SELL
            amount = quote_asset_amount
            fee_currency = trade_pair_data.base_asset

        trade = Trade(
            timestamp=timestamp,
            location=Location.BITSTAMP,
            pair=trade_pair_data.trade_pair,
            trade_type=trade_type,
            amount=amount,
            rate=deserialize_price(raw_trade[trade_pair_data.pair]),
            fee=deserialize_fee(raw_trade['fee']),
            fee_currency=fee_currency,
            link=str(raw_trade['id']),
            notes='',
        )
        return trade
Beispiel #4
0
    def _deserialize_asset_movement(
            self,
            raw_movement: Dict[str, Any],
    ) -> AssetMovement:
        """Process a deposit/withdrawal user transaction from Bitstamp and
        deserialize it.

        Can raise DeserializationError.

        From Bitstamp documentation, deposits/withdrawals can have a fee
        (the amount is expected to be in the currency involved)
        https://www.bitstamp.net/fee-schedule/

        Bitstamp support confirmed the following withdrawal JSON:
        {
            "fee": "0.00050000",
            "btc_usd": "0.00",
            "datetime": "2020-12-04 09:30:00.000000",
            "usd": "0.0",
            "btc": "-0.50000000",
            "type": "1",
            "id": 123456789,
            "eur": "0.0"
        }
        NB: any asset key not related with the pair is discarded (e.g. 'eur').
        """
        type_ = raw_movement['type']
        category: AssetMovementCategory
        if type_ == 0:
            category = AssetMovementCategory.DEPOSIT
        elif type_ == 1:
            category = AssetMovementCategory.WITHDRAWAL
        else:
            raise AssertionError(f'Unexpected Bitstamp asset movement case: {type_}.')

        timestamp = deserialize_timestamp_from_bitstamp_date(raw_movement['datetime'])
        trade_pair_data = self._get_trade_pair_data_from_transaction(raw_movement)
        base_asset_amount = deserialize_asset_amount(
            raw_movement[trade_pair_data.base_asset_symbol],
        )
        quote_asset_amount = deserialize_asset_amount(
            raw_movement[trade_pair_data.quote_asset_symbol],
        )
        amount: FVal
        fee_asset: Asset
        if base_asset_amount != ZERO and quote_asset_amount == ZERO:
            amount = base_asset_amount
            fee_asset = trade_pair_data.base_asset
        elif base_asset_amount == ZERO and quote_asset_amount != ZERO:
            amount = quote_asset_amount
            fee_asset = trade_pair_data.quote_asset
        else:
            raise DeserializationError(
                'Could not deserialize Bitstamp asset movement from user transaction. '
                f'Unexpected asset amount combination found in: {raw_movement}.',
            )

        asset_movement = AssetMovement(
            timestamp=timestamp,
            location=Location.BITSTAMP,
            category=category,
            address=None,  # requires query "crypto_transactions" endpoint
            transaction_id=None,  # requires query "crypto_transactions" endpoint
            asset=fee_asset,
            amount=abs(amount),
            fee_asset=fee_asset,
            fee=deserialize_fee(raw_movement['fee']),
            link=str(raw_movement['id']),
        )
        return asset_movement
Beispiel #5
0
                log.error(msg)
                self.msg_aggregator.add_error(
                    f'Got remote error while querying Bistamp trades: {msg}',
                )
                no_results: Union[List[Trade], List[AssetMovement]] = []  # type: ignore
                return no_results

            has_results = False
            is_result_timesamp_gt_end_ts = False
            result: Union[Trade, AssetMovement]
            for raw_result in response_list:
                if raw_result['type'] not in raw_result_type_filter:
                    continue
                try:
                    result_timestamp = deserialize_timestamp_from_bitstamp_date(
                        raw_result['datetime'],
                    )

                    if result_timestamp > end_ts:
                        is_result_timesamp_gt_end_ts = True  # prevent extra request
                        break

                    result = deserialization_method(raw_result)

                except DeserializationError as e:
                    msg = str(e)
                    log.error(
                        f'Error processing a Bitstamp {case_pretty}.',
                        raw_result=raw_result,
                        error=msg,
                    )