]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git/blobdiff - portfolio.py
Fix vanishing orders
[perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git] / portfolio.py
index 9c586769575cf1ef33794856a161be40274fce01..9e98c43ab3e3b656eed3db87208d5a626370a228 100644 (file)
@@ -1,7 +1,7 @@
 from datetime import datetime
 from retry import retry
 from decimal import Decimal as D, ROUND_DOWN
-from ccxt import ExchangeError, InsufficientFunds, ExchangeNotAvailable, InvalidOrder, OrderNotCached, OrderNotFound, RequestTimeout
+from ccxt import ExchangeError, InsufficientFunds, ExchangeNotAvailable, InvalidOrder, OrderNotCached, OrderNotFound, RequestTimeout, InvalidNonce
 
 class Computation:
     computations = {
@@ -381,6 +381,14 @@ class Trade:
         self.orders.append(order)
         return order
 
+    def reopen_same_order(self, order):
+        new_order = Order(order.action, order.amount, order.rate,
+                order.base_currency, order.trade_type, self.market,
+                self, close_if_possible=order.close_if_possible)
+        self.orders.append(new_order)
+        new_order.run()
+        return new_order
+
     def as_json(self):
         return {
                 "action": self.action,
@@ -477,7 +485,7 @@ class Order:
     def finished(self):
         return self.status.startswith("closed") or self.status == "canceled" or self.status == "error"
 
-    @retry((InsufficientFunds, RetryException))
+    @retry((InsufficientFunds, RetryException, InvalidNonce))
     def run(self):
         self.tries += 1
         symbol = "{}/{}".format(self.amount.currency, self.base_currency)
@@ -496,6 +504,14 @@ class Order:
                 self.status = "closed"
                 self.mark_finished_order()
                 return
+            except InvalidNonce as e:
+                if self.tries < 5:
+                    self.market.report.log_error(action, message="Retrying after invalid nonce", exception=e)
+                    raise e
+                else:
+                    self.market.report.log_error(action, message="Giving up {} after invalid nonce".format(self), exception=e)
+                    self.status = "error"
+                    return
             except RequestTimeout as e:
                 if not self.retrieve_order():
                     if self.tries < 5:
@@ -534,6 +550,15 @@ class Order:
             self.fetch()
         return self.status
 
+    def fix_disappeared_order(self):
+        if self.status.startswith("closed") and \
+                len(self.mouvements) == 1 and \
+                self.mouvements[0].total_in_base == 0:
+            self.status = "error_disappeared"
+            new_order = self.trade.reopen_same_order(self)
+            self.market.report.log_error("fetch",
+                    message="Order {} disappeared, recreating it as {}".format(self, new_order))
+
     def mark_finished_order(self):
         if self.status.startswith("closed") and self.market.debug:
             self.market.report.log_debug_action("Mark {} as finished".format(self))
@@ -557,6 +582,8 @@ class Order:
 
         self.fetch_mouvements()
 
+        self.fix_disappeared_order()
+
         self.mark_finished_order()
         # FIXME: consider open order with dust remaining as closed