Skip to content

Commit

Permalink
Changed the return type for matmul operator on monetary objects
Browse files Browse the repository at this point in the history
  • Loading branch information
jbaron committed Aug 22, 2024
1 parent be738e6 commit 25f1ba8
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 21 deletions.
2 changes: 1 addition & 1 deletion roboquant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
`Account`, `Asset` and `Event`.
"""

__version__ = "0.9.1"
__version__ = "0.9.2"

import logging

Expand Down
4 changes: 2 additions & 2 deletions roboquant/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def mkt_value(self) -> Wallet:

def convert(self, x: Wallet | Amount) -> float:
"""convert a wallet or amount into the base currency of the account"""
return x.convert(self.base_currency, self.last_update)
return x.convert_to(self.base_currency, self.last_update)

def position_value(self, asset: Asset) -> float:
"""Return position value denoted in the base currency of the account."""
Expand All @@ -84,7 +84,7 @@ def long_positions(self) -> dict[Asset, Position]:

def contract_value(self, asset: Asset, size: Decimal, price: float) -> float:
"""Contract value denoted in the base currency of hte account"""
return asset.contract_amount(size, price).convert(self.base_currency, self.last_update)
return asset.contract_amount(size, price).convert_to(self.base_currency, self.last_update)

def equity(self) -> Wallet:
"""Return the equity of the account.
Expand Down
20 changes: 11 additions & 9 deletions roboquant/monetary.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,13 @@ def __add__(self, other: "Amount") -> "Wallet":
"""
return Wallet(self, other)

def __matmul__(self, other: Currency) -> float:
return self.convert(other, datetime.now(tz=timezone.utc))
def __matmul__(self, other: Currency) -> "Amount":
time = datetime.now(tz=timezone.utc)
return Amount(other, self.convert_to(other, time))

def convert(self, currency: Currency, time: datetime) -> float:
"""Convert this amount to another currency and return that value.
If a conversion is required, it will invoke the registered `Amount.converter`.
def convert_to(self, currency: Currency, time: datetime) -> float:
"""Convert this amount to another currency and return the monetary value.
If an exchange rate is required, it will invoke the registered `Amount.converter` under the hood.
"""
if currency == self.currency:
return self.value
Expand Down Expand Up @@ -217,17 +218,18 @@ def __sub__(self, other: "Amount | Wallet"):
result[k] -= v
return result

def __matmul__(self, other: Currency) -> float:
return self.convert(other, datetime.now(tz=timezone.utc))
def __matmul__(self, other: Currency) -> Amount:
time = datetime.now(tz=timezone.utc)
return Amount(other, self.convert_to(other, time))

def deepcopy(self) -> "Wallet":
result = Wallet()
result.update(self)
return result

def convert(self, currency: Currency, time: datetime) -> float:
def convert_to(self, currency: Currency, time: datetime) -> float:
"""convert all the amounts hold in this wallet to a single currency and return the value"""
return sum(amount.convert(currency, time) for amount in self.amounts())
return sum(amount.convert_to(currency, time) for amount in self.amounts())

def __repr__(self) -> str:
return " + ".join([f"{a}" for a in self.amounts()])
8 changes: 4 additions & 4 deletions tests/unit/test_account.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ def test_account_init(self):
self.assertEqual(acc.buying_power.value, 0.0)
self.assertEqual(acc.buying_power.currency, USD)
self.assertEqual(acc.base_currency, USD)
self.assertEqual(acc.unrealized_pnl().convert(USD, now), 0.0)
self.assertEqual(acc.mkt_value().convert(USD, now), 0.0)
self.assertEqual(acc.unrealized_pnl().convert_to(USD, now), 0.0)
self.assertEqual(acc.mkt_value().convert_to(USD, now), 0.0)
self.assertEqual(acc.equity_value(), 1_000.0)

def test_account_positions(self):
Expand All @@ -31,9 +31,9 @@ def test_account_positions(self):
acc.positions[symbol] = Position(Decimal(10), price, price)
prices[symbol] = price

self.assertAlmostEqual(acc.mkt_value().convert(USD, now), 1450.0)
self.assertAlmostEqual(acc.mkt_value().convert_to(USD, now), 1450.0)
self.assertAlmostEqual(acc.equity_value(), 2450.0)
self.assertAlmostEqual(acc.unrealized_pnl().convert(USD, now), 0.0)
self.assertAlmostEqual(acc.unrealized_pnl().convert_to(USD, now), 0.0)


if __name__ == "__main__":
Expand Down
13 changes: 8 additions & 5 deletions tests/unit/test_monetary.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,20 @@ def test_conversion(self):
now = datetime.now()
Amount.register_converter(One2OneConversion())
one_dollar = Amount(USD, 1.0)
self.assertEqual(1.0, one_dollar.convert(EUR, now))
self.assertEqual(1.0, one_dollar.convert_to(EUR, now))

Amount.register_converter(NoConversion())
self.assertRaises(NotImplementedError, lambda: one_dollar.convert(EUR, now))
self.assertRaises(NotImplementedError, lambda: one_dollar.convert_to(EUR, now))

def test_static_conversion(self):
now = datetime.now()
converter = StaticConversion(USD, {EUR: 0.9, GBP: 0.8, JPY: 150})
Amount.register_converter(converter)
amt1 = Amount(GBP, 100.0)
self.assertAlmostEqual(112.5, amt1.convert(EUR, now))
self.assertAlmostEqual(112.5, amt1.convert_to(EUR, now))

start = 100@EUR
self.assertAlmostEqual(start, 100@EUR@USD@EUR)

Amount.register_converter(NoConversion())

Expand All @@ -59,10 +62,10 @@ def test_ecb_conversion(self):
converter = ECBConversion()
Amount.register_converter(converter)
amt1 = Amount(GBP, 100.0)
self.assertAlmostEqual(117.8856, amt1.convert(EUR, now), 4)
self.assertAlmostEqual(117.8856, amt1.convert_to(EUR, now), 4)

# convert an amount to its own currency
self.assertEqual(amt1.value, amt1@amt1.currency)
self.assertEqual(amt1.value, (amt1@amt1.currency).value)

Amount.register_converter(NoConversion())

Expand Down

0 comments on commit 25f1ba8

Please sign in to comment.