Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
from typing import List, Sequence
from .finance_fx_revaluation_types import ForeignBalance, FxRevaluation, RevaluedBalance
from .money_add import add_money, subtract_money ← from money.add ^1.0.0 · built alongside by fune
from .money_amount import money ← from money.amount ^1.0.0 · built alongside by fune
from .money_convert import convert_money ← from money.convert ^1.0.0 · built alongside by fune
from .money_convert_types import ExchangeRate
def fx_revaluation(
balances: Sequence[ForeignBalance], rates: Sequence[ExchangeRate], functional_currency: str
) -> FxRevaluation:
"""Revalue foreign-currency balances at the closing rates and report the
unrealised gain (positive) or loss (negative) on each and in total.
"""
net = money(0, functional_currency)
lines: List[RevaluedBalance] = []
for item in balances:
foreign = item.balance.currency
if foreign == functional_currency:
raise ValueError("account %s is already in %s" % (item.account, functional_currency))
if item.booked_value.currency != functional_currency:
raise ValueError("booked value of account %s must be in %s" % (item.account, functional_currency))
matching = [r for r in rates if r.base == foreign and r.quote == functional_currency]
if len(matching) == 0:
raise ValueError("no period-end rate from %s to %s" % (foreign, functional_currency))
if len(matching) > 1:
raise ValueError("more than one period-end rate from %s to %s" % (foreign, functional_currency))
revalued = convert_money(item.balance, matching[0], "half-up")
gain_loss = subtract_money(revalued, item.booked_value)
lines.append(
RevaluedBalance(
account=item.account,
balance=item.balance,
booked_value=item.booked_value,
revalued_value=revalued,
gain_loss=gain_loss,
)
)
net = add_money(net, gain_loss)
return FxRevaluation(lines=lines, net_gain_loss=net)