-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
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:
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 {
"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:
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)