aboutsummaryrefslogtreecommitdiff
path: root/market.py
diff options
context:
space:
mode:
authorIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-01 13:14:41 +0100
committerIsmaël Bouya <ismael.bouya@normalesup.org>2018-03-01 13:14:41 +0100
commitaca4d4372553110ab5d76740ff536de83d5617b2 (patch)
treea9bfdca4226daf422273da97a9e139721469c9f1 /market.py
parent2033e7fef780298be2ec15455a0ec1d26515de55 (diff)
downloadTrader-aca4d4372553110ab5d76740ff536de83d5617b2.tar.gz
Trader-aca4d4372553110ab5d76740ff536de83d5617b2.tar.zst
Trader-aca4d4372553110ab5d76740ff536de83d5617b2.zip
Various fixes/improvementsv0.3
- Use pending gains to compute the move_balance - Use ttl_cache for tickers
Diffstat (limited to 'market.py')
-rw-r--r--market.py69
1 files changed, 36 insertions, 33 deletions
diff --git a/market.py b/market.py
index 0cb3e67..9122fc0 100644
--- a/market.py
+++ b/market.py
@@ -1,7 +1,8 @@
1from ccxt import ExchangeError 1from ccxt import ExchangeError, NotSupported
2import ccxt_wrapper as ccxt 2import ccxt_wrapper as ccxt
3import time 3import time
4from store import * 4from store import *
5from cachetools.func import ttl_cache
5 6
6class Market: 7class Market:
7 debug = False 8 debug = False
@@ -42,19 +43,17 @@ class Market:
42 needed_in_margin = {} 43 needed_in_margin = {}
43 moving_to_margin = {} 44 moving_to_margin = {}
44 45
45 for currency in self.balances.all: 46 for currency, balance in self.balances.all.items():
46 if self.balances.all[currency].margin_free != 0: 47 needed_in_margin[currency] = balance.margin_in_position - balance.margin_pending_gain
47 needed_in_margin[currency] = 0 48 for trade in self.trades.pending:
48 for trade in self.trades.all: 49 needed_in_margin.setdefault(trade.base_currency, 0)
49 if trade.value_to.currency not in needed_in_margin:
50 needed_in_margin[trade.value_to.currency] = 0
51 if trade.trade_type == "short": 50 if trade.trade_type == "short":
52 needed_in_margin[trade.value_to.currency] += abs(trade.value_to) 51 needed_in_margin[trade.base_currency] -= trade.delta
53 for currency, needed in needed_in_margin.items(): 52 for currency, needed in needed_in_margin.items():
54 current_balance = self.balances.all[currency].margin_free 53 current_balance = self.balances.all[currency].margin_available
55 moving_to_margin[currency] = (needed - current_balance) 54 moving_to_margin[currency] = (needed - current_balance)
56 delta = moving_to_margin[currency].value 55 delta = moving_to_margin[currency].value
57 if self.debug: 56 if self.debug and delta != 0:
58 self.report.log_debug_action("Moving {} from exchange to margin".format(moving_to_margin[currency])) 57 self.report.log_debug_action("Moving {} from exchange to margin".format(moving_to_margin[currency]))
59 continue 58 continue
60 if delta > 0: 59 if delta > 0:
@@ -65,14 +64,18 @@ class Market:
65 64
66 self.balances.fetch_balances() 65 self.balances.fetch_balances()
67 66
68 fees_cache = {} 67 @ttl_cache(ttl=3600)
69 def fetch_fees(self): 68 def fetch_fees(self):
70 if self.ccxt.__class__ not in self.fees_cache: 69 return self.ccxt.fetch_fees()
71 self.fees_cache[self.ccxt.__class__] = self.ccxt.fetch_fees() 70
72 return self.fees_cache[self.ccxt.__class__] 71 @ttl_cache(maxsize=20, ttl=5)
72 def get_tickers(self, refresh=False):
73 try:
74 return self.ccxt.fetch_tickers()
75 except NotSupported:
76 return None
73 77
74 ticker_cache = {} 78 @ttl_cache(maxsize=20, ttl=5)
75 ticker_cache_timestamp = time.time()
76 def get_ticker(self, c1, c2, refresh=False): 79 def get_ticker(self, c1, c2, refresh=False):
77 def invert(ticker): 80 def invert(ticker):
78 return { 81 return {
@@ -86,25 +89,25 @@ class Market:
86 "average": (ticker["bid"] + ticker["ask"] ) / 2, 89 "average": (ticker["bid"] + ticker["ask"] ) / 2,
87 }) 90 })
88 91
89 if time.time() - self.ticker_cache_timestamp > 5: 92 tickers = self.get_tickers()
90 self.ticker_cache = {} 93 if tickers is None:
91 self.ticker_cache_timestamp = time.time()
92 elif not refresh:
93 if (c1, c2, self.ccxt.__class__) in self.ticker_cache:
94 return self.ticker_cache[(c1, c2, self.ccxt.__class__)]
95 if (c2, c1, self.ccxt.__class__) in self.ticker_cache:
96 return invert(self.ticker_cache[(c2, c1, self.ccxt.__class__)])
97
98 try:
99 self.ticker_cache[(c1, c2, self.ccxt.__class__)] = self.ccxt.fetch_ticker("{}/{}".format(c1, c2))
100 augment_ticker(self.ticker_cache[(c1, c2, self.ccxt.__class__)])
101 except ExchangeError:
102 try: 94 try:
103 self.ticker_cache[(c2, c1, self.ccxt.__class__)] = self.ccxt.fetch_ticker("{}/{}".format(c2, c1)) 95 ticker = self.ccxt.fetch_ticker("{}/{}".format(c1, c2))
104 augment_ticker(self.ticker_cache[(c2, c1, self.ccxt.__class__)]) 96 augment_ticker(ticker)
105 except ExchangeError: 97 except ExchangeError:
106 self.ticker_cache[(c1, c2, self.ccxt.__class__)] = None 98 try:
107 return self.get_ticker(c1, c2) 99 ticker = invert(self.ccxt.fetch_ticker("{}/{}".format(c2, c1)))
100 except ExchangeError:
101 ticker = None
102 else:
103 if "{}/{}".format(c1, c2) in tickers:
104 ticker = tickers["{}/{}".format(c1, c2)]
105 augment_ticker(ticker)
106 elif "{}/{}".format(c2, c1) in tickers:
107 ticker = invert(tickers["{}/{}".format(c2, c1)])
108 else:
109 ticker = None
110 return ticker
108 111
109 def follow_orders(self, sleep=None): 112 def follow_orders(self, sleep=None):
110 if sleep is None: 113 if sleep is None: