aboutsummaryrefslogtreecommitdiff
path: root/portfolio.py
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-11 22:40:30 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-02-11 22:40:30 +0100
commit5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a (patch)
treee12aa9ec9a5c543442aa512ee0d485ccf9f02906 /portfolio.py
parent1aa7d4fa2ec3c2b3268bef31a666ca6e1aaa6563 (diff)
downloadTrader-5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a.tar.gz
Trader-5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a.tar.zst
Trader-5a72ded790f8b5e7c9b38a3cc91c12fbfb6cb97a.zip
Add missing tests
Diffstat (limited to 'portfolio.py')
-rw-r--r--portfolio.py55
1 files changed, 28 insertions, 27 deletions
diff --git a/portfolio.py b/portfolio.py
index b629966..e98689e 100644
--- a/portfolio.py
+++ b/portfolio.py
@@ -1,4 +1,5 @@
1import time 1import time
2from datetime import datetime
2from decimal import Decimal as D, ROUND_DOWN 3from decimal import Decimal as D, ROUND_DOWN
3# Put your poloniex api key in market.py 4# Put your poloniex api key in market.py
4from json import JSONDecodeError 5from json import JSONDecodeError
@@ -272,7 +273,7 @@ class Trade:
272 if self.base_currency == self.currency: 273 if self.base_currency == self.currency:
273 return None 274 return None
274 275
275 if self.value_from < self.value_to: 276 if abs(self.value_from) < abs(self.value_to):
276 return "acquire" 277 return "acquire"
277 else: 278 else:
278 return "dispose" 279 return "dispose"
@@ -301,19 +302,16 @@ class Trade:
301 if tick in [0, 1, 3, 4, 6]: 302 if tick in [0, 1, 3, 4, 6]:
302 print("{}, tick {}, waiting".format(order, tick)) 303 print("{}, tick {}, waiting".format(order, tick))
303 elif tick == 2: 304 elif tick == 2:
304 self.prepare_order(compute_value=lambda x, y: (x[y] + x["average"]) / 2) 305 new_order = self.prepare_order(compute_value=lambda x, y: (x[y] + x["average"]) / 2)
305 new_order = self.orders[-1]
306 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order)) 306 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order))
307 elif tick ==5: 307 elif tick ==5:
308 self.prepare_order(compute_value=lambda x, y: (x[y]*2 + x["average"]) / 3) 308 new_order = self.prepare_order(compute_value=lambda x, y: (x[y]*2 + x["average"]) / 3)
309 new_order = self.orders[-1]
310 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order)) 309 print("{}, tick {}, cancelling and adjusting to {}".format(order, tick, new_order))
311 elif tick >= 7: 310 elif tick >= 7:
312 if tick == 7: 311 if tick == 7:
313 print("{}, tick {}, fallbacking to market value".format(order, tick)) 312 print("{}, tick {}, fallbacking to market value".format(order, tick))
314 if (tick - 7) % 3 == 0: 313 if (tick - 7) % 3 == 0:
315 self.prepare_order(compute_value="default") 314 new_order = self.prepare_order(compute_value="default")
316 new_order = self.orders[-1]
317 print("{}, tick {}, market value, cancelling and adjusting to {}".format(order, tick, new_order)) 315 print("{}, tick {}, market value, cancelling and adjusting to {}".format(order, tick, new_order))
318 316
319 if new_order is not None: 317 if new_order is not None:
@@ -322,7 +320,7 @@ class Trade:
322 320
323 def prepare_order(self, compute_value="default"): 321 def prepare_order(self, compute_value="default"):
324 if self.action is None: 322 if self.action is None:
325 return 323 return None
326 ticker = h.get_ticker(self.currency, self.base_currency, self.market) 324 ticker = h.get_ticker(self.currency, self.base_currency, self.market)
327 inverted = ticker["inverted"] 325 inverted = ticker["inverted"]
328 if inverted: 326 if inverted:
@@ -387,11 +385,13 @@ class Trade:
387 385
388 if delta <= 0: 386 if delta <= 0:
389 print("Less to do than already filled: {}".format(delta)) 387 print("Less to do than already filled: {}".format(delta))
390 return 388 return None
391 389
392 self.orders.append(Order(self.order_action(inverted), 390 order = Order(self.order_action(inverted),
393 delta, rate, base_currency, self.trade_type, 391 delta, rate, base_currency, self.trade_type,
394 self.market, self, close_if_possible=close_if_possible)) 392 self.market, self, close_if_possible=close_if_possible)
393 self.orders.append(order)
394 return order
395 395
396 def __repr__(self): 396 def __repr__(self):
397 return "Trade({} -> {} in {}, {})".format( 397 return "Trade({} -> {} in {}, {})".format(
@@ -419,6 +419,8 @@ class Order:
419 self.status = "pending" 419 self.status = "pending"
420 self.trade = trade 420 self.trade = trade
421 self.close_if_possible = close_if_possible 421 self.close_if_possible = close_if_possible
422 self.id = None
423 self.fetch_cache_timestamp = None
422 424
423 def __repr__(self): 425 def __repr__(self):
424 return "Order({} {} {} at {} {} [{}]{})".format( 426 return "Order({} {} {} at {} {} [{}]{})".format(
@@ -439,6 +441,10 @@ class Order:
439 return "margin" 441 return "margin"
440 442
441 @property 443 @property
444 def open(self):
445 return self.status == "open"
446
447 @property
442 def pending(self): 448 def pending(self):
443 return self.status == "pending" 449 return self.status == "pending"
444 450
@@ -446,10 +452,6 @@ class Order:
446 def finished(self): 452 def finished(self):
447 return self.status == "closed" or self.status == "canceled" or self.status == "error" 453 return self.status == "closed" or self.status == "canceled" or self.status == "error"
448 454
449 @property
450 def id(self):
451 return self.results[0]["id"]
452
453 def run(self): 455 def run(self):
454 symbol = "{}/{}".format(self.amount.currency, self.base_currency) 456 symbol = "{}/{}".format(self.amount.currency, self.base_currency)
455 amount = round(self.amount, self.market.order_precision(symbol)).value 457 amount = round(self.amount, self.market.order_precision(symbol)).value
@@ -457,26 +459,27 @@ class Order:
457 if TradeStore.debug: 459 if TradeStore.debug:
458 print("market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( 460 print("market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(
459 symbol, self.action, amount, self.rate, self.account)) 461 symbol, self.action, amount, self.rate, self.account))
460 self.status = "open"
461 self.results.append({"debug": True, "id": -1}) 462 self.results.append({"debug": True, "id": -1})
462 else: 463 else:
463 try: 464 try:
464 self.results.append(self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account)) 465 self.results.append(self.market.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account))
465 self.status = "open"
466 except Exception as e: 466 except Exception as e:
467 self.status = "error" 467 self.status = "error"
468 print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format( 468 print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(
469 symbol, self.action, amount, self.rate, self.account)) 469 symbol, self.action, amount, self.rate, self.account))
470 self.error_message = str("{}: {}".format(e.__class__.__name__, e)) 470 self.error_message = str("{}: {}".format(e.__class__.__name__, e))
471 print(self.error_message) 471 print(self.error_message)
472 return
473 self.id = self.results[0]["id"]
474 self.status = "open"
472 475
473 def get_status(self): 476 def get_status(self):
474 if TradeStore.debug: 477 if TradeStore.debug:
475 return self.status 478 return self.status
476 # other states are "closed" and "canceled" 479 # other states are "closed" and "canceled"
477 if self.status == "open": 480 if not self.finished:
478 self.fetch() 481 self.fetch()
479 if self.status != "open": 482 if self.finished:
480 self.mark_finished_order() 483 self.mark_finished_order()
481 return self.status 484 return self.status
482 485
@@ -487,15 +490,15 @@ class Order:
487 if self.trade_type == "short" and self.action == "buy" and self.close_if_possible: 490 if self.trade_type == "short" and self.action == "buy" and self.close_if_possible:
488 self.market.close_margin_position(self.amount.currency, self.base_currency) 491 self.market.close_margin_position(self.amount.currency, self.base_currency)
489 492
490 fetch_cache_timestamp = None
491 def fetch(self, force=False): 493 def fetch(self, force=False):
492 if TradeStore.debug or (not force and self.fetch_cache_timestamp is not None 494 if TradeStore.debug or (not force and self.fetch_cache_timestamp is not None
493 and time.time() - self.fetch_cache_timestamp < 10): 495 and time.time() - self.fetch_cache_timestamp < 10):
494 return 496 return
495 self.fetch_cache_timestamp = time.time() 497 self.fetch_cache_timestamp = time.time()
496 498
497 self.results.append(self.market.fetch_order(self.id)) 499 result = self.market.fetch_order(self.id)
498 result = self.results[-1] 500 self.results.append(result)
501
499 self.status = result["status"] 502 self.status = result["status"]
500 # Time at which the order started 503 # Time at which the order started
501 self.timestamp = result["datetime"] 504 self.timestamp = result["datetime"]
@@ -503,11 +506,9 @@ class Order:
503 506
504 # FIXME: consider open order with dust remaining as closed 507 # FIXME: consider open order with dust remaining as closed
505 508
506 @property
507 def dust_amount_remaining(self): 509 def dust_amount_remaining(self):
508 return self.remaining_amount < 0.001 510 return self.remaining_amount() < Amount(self.amount.currency, D("0.001"))
509 511
510 @property
511 def remaining_amount(self): 512 def remaining_amount(self):
512 if self.status == "open": 513 if self.status == "open":
513 self.fetch() 514 self.fetch()
@@ -536,7 +537,7 @@ class Order:
536 if TradeStore.debug: 537 if TradeStore.debug:
537 self.status = "canceled" 538 self.status = "canceled"
538 return 539 return
539 self.market.cancel_order(self.result['id']) 540 self.market.cancel_order(self.id)
540 self.fetch() 541 self.fetch()
541 542
542class Mouvement: 543class Mouvement:
@@ -552,6 +553,6 @@ class Mouvement:
552 # rate * total = total_in_base 553 # rate * total = total_in_base
553 self.total_in_base = Amount(base_currency, hash_["total"]) 554 self.total_in_base = Amount(base_currency, hash_["total"])
554 555
555if __name__ == '__main__': 556if __name__ == '__main__': # pragma: no cover
556 from market import market 557 from market import market
557 h.print_orders(market) 558 h.print_orders(market)