diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-21 15:57:13 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-21 15:57:36 +0100 |
commit | c2644ba8db6e3890458af6a244aa3217e2ac4797 (patch) | |
tree | 9f569244f534f49c1850ab4c30e171380f7850f7 | |
parent | deb8924cc60f0d64575657399f4fe112ff1cfb31 (diff) | |
download | Trader-c2644ba8db6e3890458af6a244aa3217e2ac4797.tar.gz Trader-c2644ba8db6e3890458af6a244aa3217e2ac4797.tar.zst Trader-c2644ba8db6e3890458af6a244aa3217e2ac4797.zip |
Store currency conversion rate and use it in trade computations
-rw-r--r-- | portfolio.py | 28 | ||||
-rw-r--r-- | test.py | 3 |
2 files changed, 17 insertions, 14 deletions
diff --git a/portfolio.py b/portfolio.py index 5211dd8..6d51989 100644 --- a/portfolio.py +++ b/portfolio.py | |||
@@ -80,25 +80,34 @@ class Portfolio: | |||
80 | class Amount: | 80 | class Amount: |
81 | MAX_DIGITS = 18 | 81 | MAX_DIGITS = 18 |
82 | 82 | ||
83 | def __init__(self, currency, value, linked_to=None, ticker=None): | 83 | def __init__(self, currency, value, linked_to=None, ticker=None, rate=None): |
84 | self.currency = currency | 84 | self.currency = currency |
85 | self.value = D(value) | 85 | self.value = D(value) |
86 | self.linked_to = linked_to | 86 | self.linked_to = linked_to |
87 | self.ticker = ticker | 87 | self.ticker = ticker |
88 | self.rate = rate | ||
88 | 89 | ||
89 | self.ticker_cache = {} | 90 | self.ticker_cache = {} |
90 | self.ticker_cache_timestamp = time.time() | 91 | self.ticker_cache_timestamp = time.time() |
91 | 92 | ||
92 | def in_currency(self, other_currency, market, action=None, compute_value="average"): | 93 | def in_currency(self, other_currency, market, rate=None, action=None, compute_value="average"): |
93 | if other_currency == self.currency: | 94 | if other_currency == self.currency: |
94 | return self | 95 | return self |
96 | if rate is not None: | ||
97 | return Amount( | ||
98 | other_currency, | ||
99 | self.value * rate, | ||
100 | linked_to=self, | ||
101 | rate=rate) | ||
95 | asset_ticker = Trade.get_ticker(self.currency, other_currency, market) | 102 | asset_ticker = Trade.get_ticker(self.currency, other_currency, market) |
96 | if asset_ticker is not None: | 103 | if asset_ticker is not None: |
104 | rate = Trade.compute_value(asset_ticker, action, compute_value=compute_value) | ||
97 | return Amount( | 105 | return Amount( |
98 | other_currency, | 106 | other_currency, |
99 | self.value * Trade.compute_value(asset_ticker, action, compute_value=compute_value), | 107 | self.value * rate, |
100 | linked_to=self, | 108 | linked_to=self, |
101 | ticker=asset_ticker) | 109 | ticker=asset_ticker, |
110 | rate=rate) | ||
102 | else: | 111 | else: |
103 | raise Exception("This asset is not available in the chosen market") | 112 | raise Exception("This asset is not available in the chosen market") |
104 | 113 | ||
@@ -226,15 +235,8 @@ class Balance: | |||
226 | return "Balance({} [{}/{}/{}])".format(self.currency, str(self.free), str(self.used), str(self.total)) | 235 | return "Balance({} [{}/{}/{}])".format(self.currency, str(self.free), str(self.used), str(self.total)) |
227 | 236 | ||
228 | class Computation: | 237 | class Computation: |
229 | def average_inverse(ticker, action): | ||
230 | if ticker["inverted"]: | ||
231 | return 1/ticker["original"]["average"] | ||
232 | else: | ||
233 | return ticker["average"] | ||
234 | |||
235 | computations = { | 238 | computations = { |
236 | "default": lambda x, y: x[y], | 239 | "default": lambda x, y: x[y], |
237 | "average_inverse": average_inverse, | ||
238 | "average": lambda x, y: x["average"], | 240 | "average": lambda x, y: x["average"], |
239 | "bid": lambda x, y: x["bid"], | 241 | "bid": lambda x, y: x["bid"], |
240 | "ask": lambda x, y: x["ask"], | 242 | "ask": lambda x, y: x["ask"], |
@@ -341,9 +343,7 @@ class Trade: | |||
341 | 343 | ||
342 | if not inverted: | 344 | if not inverted: |
343 | value_from = self.value_from.linked_to | 345 | value_from = self.value_from.linked_to |
344 | # The ticker will most probably be inverted, but we want the average | 346 | value_to = self.value_to.in_currency(self.currency, self.market, rate=1/self.value_from.rate) |
345 | # of the initial value | ||
346 | value_to = self.value_to.in_currency(self.currency, self.market, compute_value="average_inverse") | ||
347 | delta = abs(value_to - value_from) | 347 | delta = abs(value_to - value_from) |
348 | currency = self.base_currency | 348 | currency = self.base_currency |
349 | else: | 349 | else: |
@@ -40,6 +40,9 @@ class AmountTest(unittest.TestCase): | |||
40 | converted_amount = amount.in_currency("ETH", None, compute_value="ask") | 40 | converted_amount = amount.in_currency("ETH", None, compute_value="ask") |
41 | self.assertEqual(D("4"), converted_amount.value) | 41 | self.assertEqual(D("4"), converted_amount.value) |
42 | 42 | ||
43 | converted_amount = amount.in_currency("ETH", None, rate=D("0.02")) | ||
44 | self.assertEqual(D("0.2"), converted_amount.value) | ||
45 | |||
43 | def test__abs(self): | 46 | def test__abs(self): |
44 | amount = portfolio.Amount("SC", -120) | 47 | amount = portfolio.Amount("SC", -120) |
45 | self.assertEqual(120, abs(amount).value) | 48 | self.assertEqual(120, abs(amount).value) |