from decimal import Decimal as D, ROUND_DOWN
from json import JSONDecodeError
from simplejson.errors import JSONDecodeError as SimpleJSONDecodeError
-from ccxt import ExchangeError, ExchangeNotAvailable
+from ccxt import ExchangeError, InsufficientFunds, ExchangeNotAvailable, InvalidOrder
+from retry import retry
import requests
# FIXME: correctly handle web call timeouts
new_order.run()
self.market.report.log_order(order, tick, new_order=new_order)
- def prepare_order(self, compute_value="default"):
+ def prepare_order(self, close_if_possible=None, compute_value="default"):
if self.action is None:
return None
ticker = self.market.get_ticker(self.currency, self.base_currency)
delta = delta - filled
# I already sold 4 BTC, only 5 left
- close_if_possible = (self.value_to == 0)
+ if close_if_possible is None:
+ close_if_possible = (self.value_to == 0)
if delta <= 0:
self.market.report.log_error("prepare_order", message="Less to do than already filled: {}".format(delta))
self.close_if_possible = close_if_possible
self.id = None
self.fetch_cache_timestamp = None
+ self.tries = 0
def as_json(self):
return {
def finished(self):
return self.status == "closed" or self.status == "canceled" or self.status == "error"
+ @retry(InsufficientFunds)
def run(self):
+ self.tries += 1
symbol = "{}/{}".format(self.amount.currency, self.base_currency)
amount = round(self.amount, self.market.ccxt.order_precision(symbol)).value
symbol, self.action, amount, self.rate, self.account))
self.results.append({"debug": True, "id": -1})
else:
+ action = "market.ccxt.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(symbol, self.action, amount, self.rate, self.account)
try:
self.results.append(self.market.ccxt.create_order(symbol, 'limit', self.action, amount, price=self.rate, account=self.account))
- except ExchangeNotAvailable:
+ except InvalidOrder:
# Impossible to honor the order (dust amount)
self.status = "closed"
self.mark_finished_order()
return
+ except InsufficientFunds as e:
+ if self.tries < 5:
+ self.market.report.log_error(action, message="Retrying with reduced amount", exception=e)
+ self.amount = self.amount * D("0.99")
+ raise e
+ else:
+ self.market.report.log_error(action, message="Giving up {}".format(self), exception=e)
+ self.status = "error"
+ return
except Exception as e:
self.status = "error"
- action = "market.ccxt.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(symbol, self.action, amount, self.rate, self.account)
self.market.report.log_error(action, exception=e)
return
self.id = self.results[0]["id"]
return
self.fetch_cache_timestamp = time.time()
- result = self.market.ccxt.fetch_order(self.id)
+ result = self.market.ccxt.fetch_order(self.id, symbol=self.amount.currency)
self.results.append(result)
self.status = result["status"]
self.status = "canceled"
return
self.market.ccxt.cancel_order(self.id)
- self.fetch()
+ self.fetch(force=True)
class Mouvement:
def __init__(self, currency, base_currency, hash_):