X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=market.py;h=3381d1e2643e03cb35019cbd14eb29f0f9108cbf;hb=9db7d156833cd384baa64b6148b5c646bfcc41f8;hp=931de09e350c1a37b0bcd54baf312d433641a527;hpb=f86ee14037646bedc3a3dee4a48f085308981757;p=perso%2FImmae%2FProjets%2FCryptomonnaies%2FCryptoportfolio%2FTrader.git diff --git a/market.py b/market.py index 931de09..3381d1e 100644 --- a/market.py +++ b/market.py @@ -1,7 +1,8 @@ -from ccxt import ExchangeError +from ccxt import ExchangeError, NotSupported import ccxt_wrapper as ccxt import time from store import * +from cachetools.func import ttl_cache class Market: debug = False @@ -20,6 +21,8 @@ class Market: @classmethod def from_config(cls, config, debug=False): + config["apiKey"] = config.pop("key") + ccxt_instance = ccxt.poloniexE(config) # For requests logging @@ -40,19 +43,17 @@ class Market: needed_in_margin = {} moving_to_margin = {} - for currency in self.balances.all: - if self.balances.all[currency].margin_free != 0: - needed_in_margin[currency] = 0 - for trade in self.trades.all: - if trade.value_to.currency not in needed_in_margin: - needed_in_margin[trade.value_to.currency] = 0 + for currency, balance in self.balances.all.items(): + needed_in_margin[currency] = balance.margin_in_position - balance.margin_pending_gain + for trade in self.trades.pending: + needed_in_margin.setdefault(trade.base_currency, 0) if trade.trade_type == "short": - needed_in_margin[trade.value_to.currency] += abs(trade.value_to) + needed_in_margin[trade.base_currency] -= trade.delta for currency, needed in needed_in_margin.items(): - current_balance = self.balances.all[currency].margin_free + current_balance = self.balances.all[currency].margin_available moving_to_margin[currency] = (needed - current_balance) delta = moving_to_margin[currency].value - if self.debug: + if self.debug and delta != 0: self.report.log_debug_action("Moving {} from exchange to margin".format(moving_to_margin[currency])) continue if delta > 0: @@ -63,14 +64,18 @@ class Market: self.balances.fetch_balances() - fees_cache = {} + @ttl_cache(ttl=3600) def fetch_fees(self): - if self.ccxt.__class__ not in self.fees_cache: - self.fees_cache[self.ccxt.__class__] = self.ccxt.fetch_fees() - return self.fees_cache[self.ccxt.__class__] + return self.ccxt.fetch_fees() + + @ttl_cache(maxsize=20, ttl=5) + def get_tickers(self, refresh=False): + try: + return self.ccxt.fetch_tickers() + except NotSupported: + return None - ticker_cache = {} - ticker_cache_timestamp = time.time() + @ttl_cache(maxsize=20, ttl=5) def get_ticker(self, c1, c2, refresh=False): def invert(ticker): return { @@ -83,26 +88,25 @@ class Market: "inverted": False, "average": (ticker["bid"] + ticker["ask"] ) / 2, }) + return ticker - if time.time() - self.ticker_cache_timestamp > 5: - self.ticker_cache = {} - self.ticker_cache_timestamp = time.time() - elif not refresh: - if (c1, c2, self.ccxt.__class__) in self.ticker_cache: - return self.ticker_cache[(c1, c2, self.ccxt.__class__)] - if (c2, c1, self.ccxt.__class__) in self.ticker_cache: - return invert(self.ticker_cache[(c2, c1, self.ccxt.__class__)]) - - try: - self.ticker_cache[(c1, c2, self.ccxt.__class__)] = self.ccxt.fetch_ticker("{}/{}".format(c1, c2)) - augment_ticker(self.ticker_cache[(c1, c2, self.ccxt.__class__)]) - except ExchangeError: + tickers = self.get_tickers() + if tickers is None: try: - self.ticker_cache[(c2, c1, self.ccxt.__class__)] = self.ccxt.fetch_ticker("{}/{}".format(c2, c1)) - augment_ticker(self.ticker_cache[(c2, c1, self.ccxt.__class__)]) + ticker = augment_ticker(self.ccxt.fetch_ticker("{}/{}".format(c1, c2))) except ExchangeError: - self.ticker_cache[(c1, c2, self.ccxt.__class__)] = None - return self.get_ticker(c1, c2) + try: + ticker = invert(augment_ticker(self.ccxt.fetch_ticker("{}/{}".format(c2, c1)))) + except ExchangeError: + ticker = None + else: + if "{}/{}".format(c1, c2) in tickers: + ticker = augment_ticker(tickers["{}/{}".format(c1, c2)]) + elif "{}/{}".format(c2, c1) in tickers: + ticker = invert(augment_ticker(tickers["{}/{}".format(c2, c1)])) + else: + ticker = None + return ticker def follow_orders(self, sleep=None): if sleep is None: @@ -124,27 +128,18 @@ class Market: order.trade.update_order(order, tick) self.report.log_stage("follow_orders_end") - def prepare_trades(self, base_currency="BTC", liquidity="medium", compute_value="average"): - self.report.log_stage("prepare_trades") - values_in_base = self.balances.in_currency(base_currency, compute_value=compute_value) - total_base_value = sum(values_in_base.values()) - new_repartition = self.balances.dispatch_assets(total_base_value, liquidity=liquidity) - # Recompute it in case we have new currencies - values_in_base = self.balances.in_currency(base_currency, compute_value=compute_value) - self.trades.compute_trades(values_in_base, new_repartition) - - def update_trades(self, base_currency="BTC", liquidity="medium", compute_value="average", only=None): - self.report.log_stage("update_trades") - values_in_base = self.balances.in_currency(base_currency, compute_value=compute_value) - total_base_value = sum(values_in_base.values()) - new_repartition = self.balances.dispatch_assets(total_base_value, liquidity=liquidity) - self.trades.compute_trades(values_in_base, new_repartition, only=only) + def prepare_trades(self, base_currency="BTC", liquidity="medium", + compute_value="average", repartition=None, only=None): - def prepare_trades_to_sell_all(self, base_currency="BTC", compute_value="average"): - self.report.log_stage("prepare_trades_to_sell_all") - values_in_base = self.balances.in_currency(base_currency, compute_value=compute_value) - total_base_value = sum(values_in_base.values()) - new_repartition = self.balances.dispatch_assets(total_base_value, repartition={ base_currency: (1, "long") }) - self.trades.compute_trades(values_in_base, new_repartition) + self.report.log_stage("prepare_trades", + base_currency=base_currency, liquidity=liquidity, + compute_value=compute_value, only=only, + repartition=repartition) + values_in_base = self.balances.in_currency(base_currency, + compute_value=compute_value) + total_base_value = sum(values_in_base.values()) + new_repartition = self.balances.dispatch_assets(total_base_value, + liquidity=liquidity, repartition=repartition) + self.trades.compute_trades(values_in_base, new_repartition, only=only)