diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-21 15:17:48 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-21 15:37:24 +0100 |
commit | deb8924cc60f0d64575657399f4fe112ff1cfb31 (patch) | |
tree | 66dbef501b99f962882fce9ac0f67855650674cd /portfolio.py | |
parent | f0e4f1828138f86cee54d9f8c4414228840207aa (diff) | |
download | Trader-deb8924cc60f0d64575657399f4fe112ff1cfb31.tar.gz Trader-deb8924cc60f0d64575657399f4fe112ff1cfb31.tar.zst Trader-deb8924cc60f0d64575657399f4fe112ff1cfb31.zip |
Add compute value lambdas for currency conversion
Diffstat (limited to 'portfolio.py')
-rw-r--r-- | portfolio.py | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/portfolio.py b/portfolio.py index 4991dce..5211dd8 100644 --- a/portfolio.py +++ b/portfolio.py | |||
@@ -89,14 +89,14 @@ class Amount: | |||
89 | self.ticker_cache = {} | 89 | self.ticker_cache = {} |
90 | self.ticker_cache_timestamp = time.time() | 90 | self.ticker_cache_timestamp = time.time() |
91 | 91 | ||
92 | def in_currency(self, other_currency, market, action="average"): | 92 | def in_currency(self, other_currency, market, action=None, compute_value="average"): |
93 | if other_currency == self.currency: | 93 | if other_currency == self.currency: |
94 | return self | 94 | return self |
95 | asset_ticker = Trade.get_ticker(self.currency, other_currency, market) | 95 | asset_ticker = Trade.get_ticker(self.currency, other_currency, market) |
96 | if asset_ticker is not None: | 96 | if asset_ticker is not None: |
97 | return Amount( | 97 | return Amount( |
98 | other_currency, | 98 | other_currency, |
99 | self.value * asset_ticker[action], | 99 | self.value * Trade.compute_value(asset_ticker, action, compute_value=compute_value), |
100 | linked_to=self, | 100 | linked_to=self, |
101 | ticker=asset_ticker) | 101 | ticker=asset_ticker) |
102 | else: | 102 | else: |
@@ -175,12 +175,12 @@ class Balance: | |||
175 | return cls(currency, hash_["total"], hash_["free"], hash_["used"]) | 175 | return cls(currency, hash_["total"], hash_["free"], hash_["used"]) |
176 | 176 | ||
177 | @classmethod | 177 | @classmethod |
178 | def in_currency(cls, other_currency, market, action="average", type="total"): | 178 | def in_currency(cls, other_currency, market, compute_value="average", type="total"): |
179 | amounts = {} | 179 | amounts = {} |
180 | for currency in cls.known_balances: | 180 | for currency in cls.known_balances: |
181 | balance = cls.known_balances[currency] | 181 | balance = cls.known_balances[currency] |
182 | other_currency_amount = getattr(balance, type)\ | 182 | other_currency_amount = getattr(balance, type)\ |
183 | .in_currency(other_currency, market, action=action) | 183 | .in_currency(other_currency, market, compute_value=compute_value) |
184 | amounts[currency] = other_currency_amount | 184 | amounts[currency] = other_currency_amount |
185 | return amounts | 185 | return amounts |
186 | 186 | ||
@@ -213,16 +213,34 @@ class Balance: | |||
213 | return amounts | 213 | return amounts |
214 | 214 | ||
215 | @classmethod | 215 | @classmethod |
216 | def prepare_trades(cls, market, base_currency="BTC"): | 216 | def prepare_trades(cls, market, base_currency="BTC", compute_value=None): |
217 | cls.fetch_balances(market) | 217 | cls.fetch_balances(market) |
218 | values_in_base = cls.in_currency(base_currency, market) | 218 | values_in_base = cls.in_currency(base_currency, market) |
219 | total_base_value = sum(values_in_base.values()) | 219 | total_base_value = sum(values_in_base.values()) |
220 | new_repartition = cls.dispatch_assets(total_base_value) | 220 | new_repartition = cls.dispatch_assets(total_base_value) |
221 | Trade.compute_trades(values_in_base, new_repartition, market=market) | 221 | # Recompute it in case we have new currencies |
222 | values_in_base = cls.in_currency(base_currency, market) | ||
223 | Trade.compute_trades(values_in_base, new_repartition, market=market, compute_value=compute_value) | ||
222 | 224 | ||
223 | def __repr__(self): | 225 | def __repr__(self): |
224 | return "Balance({} [{}/{}/{}])".format(self.currency, str(self.free), str(self.used), str(self.total)) | 226 | return "Balance({} [{}/{}/{}])".format(self.currency, str(self.free), str(self.used), str(self.total)) |
225 | 227 | ||
228 | 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 = { | ||
236 | "default": lambda x, y: x[y], | ||
237 | "average_inverse": average_inverse, | ||
238 | "average": lambda x, y: x["average"], | ||
239 | "bid": lambda x, y: x["bid"], | ||
240 | "ask": lambda x, y: x["ask"], | ||
241 | } | ||
242 | |||
243 | |||
226 | class Trade: | 244 | class Trade: |
227 | trades = {} | 245 | trades = {} |
228 | 246 | ||
@@ -282,7 +300,7 @@ class Trade: | |||
282 | return cls.get_ticker(c1, c2, market) | 300 | return cls.get_ticker(c1, c2, market) |
283 | 301 | ||
284 | @classmethod | 302 | @classmethod |
285 | def compute_trades(cls, values_in_base, new_repartition, market=None): | 303 | def compute_trades(cls, values_in_base, new_repartition, market=None, compute_value=None): |
286 | base_currency = sum(values_in_base.values()).currency | 304 | base_currency = sum(values_in_base.values()).currency |
287 | for currency in Balance.currencies(): | 305 | for currency in Balance.currencies(): |
288 | if currency == base_currency: | 306 | if currency == base_currency: |
@@ -293,7 +311,8 @@ class Trade: | |||
293 | currency, | 311 | currency, |
294 | market=market | 312 | market=market |
295 | ) | 313 | ) |
296 | cls.trades[currency].prepare_order() | 314 | if compute_value is not None: |
315 | cls.trades[currency].prepare_order(compute_value=compute_value) | ||
297 | return cls.trades | 316 | return cls.trades |
298 | 317 | ||
299 | @property | 318 | @property |
@@ -314,7 +333,7 @@ class Trade: | |||
314 | else: | 333 | else: |
315 | return "bid" if not inverted else "ask" | 334 | return "bid" if not inverted else "ask" |
316 | 335 | ||
317 | def prepare_order(self): | 336 | def prepare_order(self, compute_value="default"): |
318 | if self.action is None: | 337 | if self.action is None: |
319 | return | 338 | return |
320 | ticker = self.value_from.ticker | 339 | ticker = self.value_from.ticker |
@@ -322,7 +341,9 @@ class Trade: | |||
322 | 341 | ||
323 | if not inverted: | 342 | if not inverted: |
324 | value_from = self.value_from.linked_to | 343 | value_from = self.value_from.linked_to |
325 | value_to = self.value_to.in_currency(self.currency, self.market) | 344 | # The ticker will most probably be inverted, but we want the average |
345 | # of the initial value | ||
346 | value_to = self.value_to.in_currency(self.currency, self.market, compute_value="average_inverse") | ||
326 | delta = abs(value_to - value_from) | 347 | delta = abs(value_to - value_from) |
327 | currency = self.base_currency | 348 | currency = self.base_currency |
328 | else: | 349 | else: |
@@ -330,11 +351,17 @@ class Trade: | |||
330 | delta = abs(self.value_to - self.value_from) | 351 | delta = abs(self.value_to - self.value_from) |
331 | currency = self.currency | 352 | currency = self.currency |
332 | 353 | ||
333 | rate = ticker[self.order_action(inverted)] | 354 | rate = Trade.compute_value(ticker, self.order_action(inverted), compute_value=compute_value) |
334 | 355 | ||
335 | self.orders.append(Order(self.order_action(inverted), delta, rate, currency)) | 356 | self.orders.append(Order(self.order_action(inverted), delta, rate, currency)) |
336 | 357 | ||
337 | @classmethod | 358 | @classmethod |
359 | def compute_value(cls, ticker, action, compute_value="default"): | ||
360 | if type(compute_value) == str: | ||
361 | compute_value = Computation.computations[compute_value] | ||
362 | return compute_value(ticker, action) | ||
363 | |||
364 | @classmethod | ||
338 | def all_orders(cls): | 365 | def all_orders(cls): |
339 | return sum(map(lambda v: v.orders, cls.trades.values()), []) | 366 | return sum(map(lambda v: v.orders, cls.trades.values()), []) |
340 | 367 | ||
@@ -401,7 +428,7 @@ class Order: | |||
401 | return self.status | 428 | return self.status |
402 | 429 | ||
403 | def print_orders(market, base_currency="BTC"): | 430 | def print_orders(market, base_currency="BTC"): |
404 | Balance.prepare_trades(market, base_currency=base_currency) | 431 | Balance.prepare_trades(market, base_currency=base_currency, compute_value="average") |
405 | for currency, balance in Balance.known_balances.items(): | 432 | for currency, balance in Balance.known_balances.items(): |
406 | print(balance) | 433 | print(balance) |
407 | for currency, trade in Trade.trades.items(): | 434 | for currency, trade in Trade.trades.items(): |