def import_transaction( account: models.Account, fiat_record: pd.Series, token_record: pd.Series, ) -> Tuple[models.Transaction, bool]: raw_record = _to_raw_record((fiat_record, token_record)) executed_at = _parse_utc_datetime(fiat_record["UTC_Time"]) symbol = token_record["Coin"] fiat_currency = fiat_record["Coin"] raw_fiat_value = to_decimal(fiat_record["Change"]) fiat_value = raw_fiat_value from_currency = models.currency_enum_from_string(fiat_currency) if fiat_currency != models.Currency(account.currency).label: to_currency = account.currency exchange_rate = prices.get_closest_exchange_rate( executed_at.date(), from_currency, to_currency ) if exchange_rate is None: raise CurrencyMismatch( "Couldn't convert the fiat to account currency, missing exchange rate" ) else: fiat_value *= exchange_rate.value raw_record += f" exchange rate: {exchange_rate.value}" if fiat_currency == "USD": fiat_value_usd = raw_fiat_value else: to_currency = models.Currency.USD exchange_rate = prices.get_closest_exchange_rate( executed_at.date(), from_currency, to_currency ) if exchange_rate is None: raise CurrencyMismatch( "Couldn't convert the fiat to USD, missing exchange rate" ) fiat_value_usd = raw_fiat_value * exchange_rate.value quantity = to_decimal(token_record["Change"]) with decimal.localcontext() as c: c.prec = 10 price = decimal.Decimal(-fiat_value_usd / quantity) return ( *accounts.AccountRepository().add_transaction_crypto_asset( account, symbol, executed_at, quantity, price, fiat_value_usd, fiat_value, fiat_value, ), raw_record, )
def import_transaction( account: models.Account, transaction_record: pd.Series, import_all_assets, ) -> Tuple[models.Transaction, bool]: executed_at = transaction_record["Datetime"] isin = transaction_record["ISIN"] local_value = transaction_record["Local value"] total_in_account_currency = transaction_record["Total"] value_in_account_currency = transaction_record["Value"] transaction_costs = transaction_record["Transaction costs"].astype(str) order_id = transaction_record["Order ID"] quantity = transaction_record["Quantity"] price = transaction_record["Price"] account_currency = transaction_record["Value currency"] local_currency = transaction_record["Local value currency"] product = transaction_record["Product"] if models.currency_enum_from_string(account_currency) != account.currency: raise CurrencyMismatch("Currency of import didn't match the account") exchange_mic = transaction_record["Venue"] exchange_ref = transaction_record["Reference"] try: exchange = stock_exchanges.ExchangeRepository().get( exchange_mic, exchange_ref) except Exception as e: logger.error(e) raise e def to_decimal(pd_f): return decimal.Decimal(pd_f.astype(str)) transaction_costs = decimal.Decimal(transaction_costs) if transaction_costs.is_nan(): transaction_costs = None return accounts.AccountRepository().add_transaction( account, isin=isin, exchange=exchange, executed_at=executed_at, quantity=to_decimal(quantity), price=to_decimal(price), transaction_costs=transaction_costs, local_value=to_decimal(local_value), value_in_account_currency=to_decimal(value_in_account_currency), total_in_account_currency=to_decimal(total_in_account_currency), order_id=order_id, asset_defaults={ "local_currency": local_currency, "name": product }, import_all_assets=import_all_assets, )
def test_adding_account(self, nickname, currency): self.client.force_login(self.user) response = self.client.post( reverse(self.VIEW_NAME), { "currency": currency, "nickname": nickname, "description": "", }, ) self.assertEqual(response.status_code, 201) self.assertEqual(models.Account.objects.count(), 2) account = models.Account.objects.get( currency=models.currency_enum_from_string(currency), nickname=nickname, ) self.assertEqual(account.user, self.user)
def import_fiat_transfers(account, records): account_repository = accounts.AccountRepository() successful_records = [] for record in records.iloc: raw_record = record.to_csv() event_type = models.EventType.DEPOSIT if record["Operation"] == "Withdrawal": event_type = models.EventType.WITHDRAWAL executed_at = _parse_utc_datetime(record["UTC_Time"]) fiat_currency = record["Coin"] fiat_value = to_decimal(record["Change"]) if fiat_currency != models.Currency(account.currency).label: from_currency = models.currency_enum_from_string(fiat_currency) to_currency = account.currency exchange_rate = prices.get_closest_exchange_rate( executed_at.date(), from_currency, to_currency ) if exchange_rate is None: raise CurrencyMismatch( "Couldn't convert the fiat to account currency, missing exchange rate" ) else: fiat_value *= exchange_rate.value raw_record += f", exchange rate: {exchange_rate.value}" event, created = account_repository.add_event( account, amount=fiat_value, executed_at=executed_at, event_type=event_type, ) successful_records.append( { "record": raw_record, "event": event, "transaction": None, "created": created, } ) return successful_records
def validate_to_currency(self, value): try: return models.currency_enum_from_string(value) except ValueError: raise serializers.ValidationError( f"{value} is not a valid currency symbol")
def _to_currency(currency_raw: str) -> Optional[models.Currency]: try: return models.currency_enum_from_string(currency_raw) except ValueError: return
def get_or_create_asset( isin: str, exchange: models.Exchange, asset_defaults, add_untracked_if_not_found, user, ): repository = AssetRepository(exchange) asset = repository.get(isin) if asset: return asset if exchange.name != OTHER_OR_NA_EXCHANGE_NAME: exchange_code = exchange.identifiers.get( id_type=models.ExchangeIDType.CODE).value else: exchange_code = "" asset_records = query_asset(isin) for record in asset_records: if record["Exchange"] == exchange_code: asset_type_raw = record["Type"] if asset_defaults["local_currency"] != record["Currency"]: # There could be multiple assets registered with the same ISIN, but different currencies. continue currency = models.currency_enum_from_string(record["Currency"]) asset = repository.add( isin=isin, symbol=record["Code"], currency=currency, country=record["Country"], name=record["Name"], tracked=True, user=user, asset_type=_to_asset_type(asset_type_raw), ) print("created asset") return asset else: if len(asset_records): record = asset_records[0] asset_type_raw = record["Type"] currency = models.currency_enum_from_string( asset_defaults["local_currency"]) if add_untracked_if_not_found: asset = repository.add( isin=isin, symbol=record["Code"], currency=currency, country=record["Country"], name=record["Name"], tracked=False, user=user, asset_type=_to_asset_type(asset_type_raw), ) return asset logging.warn( f"failed to find stock data for isin: {isin}, exchange: {exchange}, exchange_code: {exchange_code}" ) else: if add_untracked_if_not_found: currency = models.currency_enum_from_string( asset_defaults["local_currency"]) asset = repository.add( isin=isin, symbol=isin, currency=currency, country="Unknown", name=asset_defaults["name"], tracked=False, user=user, asset_type=models.AssetType.STOCK, ) return asset logging.warn( f"failed to find stock data (there were assets but no exchange match) for isin: {isin}, exchange: {exchange}, exchange_code: {exchange_code}" )