]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git/blobdiff - market.py
Add processors
[perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Trader.git] / market.py
index 931de09e350c1a37b0bcd54baf312d433641a527..3381d1e2643e03cb35019cbd14eb29f0f9108cbf 100644 (file)
--- 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)