diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-18 01:43:19 +0100 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2018-01-18 02:00:44 +0100 |
commit | cfab619d9223fc824649a6fe16863931f5e43891 (patch) | |
tree | 8f699388253896a7f5ebcb87acf344e5771c97a1 /portfolio.py | |
parent | f2da658998b6e6605c6ae27ff338ef23b96dce25 (diff) | |
download | Trader-cfab619d9223fc824649a6fe16863931f5e43891.tar.gz Trader-cfab619d9223fc824649a6fe16863931f5e43891.tar.zst Trader-cfab619d9223fc824649a6fe16863931f5e43891.zip |
Move ticker to Trade class and add tests
Diffstat (limited to 'portfolio.py')
-rw-r--r-- | portfolio.py | 96 |
1 files changed, 49 insertions, 47 deletions
diff --git a/portfolio.py b/portfolio.py index 1d8bfd5..576a228 100644 --- a/portfolio.py +++ b/portfolio.py | |||
@@ -102,7 +102,7 @@ class Amount: | |||
102 | def in_currency(self, other_currency, market, action="average"): | 102 | def in_currency(self, other_currency, market, action="average"): |
103 | if other_currency == self.currency: | 103 | if other_currency == self.currency: |
104 | return self | 104 | return self |
105 | asset_ticker = self.get_ticker(other_currency, market) | 105 | asset_ticker = Trade.get_ticker(self.currency, other_currency, market) |
106 | if asset_ticker is not None: | 106 | if asset_ticker is not None: |
107 | return Amount( | 107 | return Amount( |
108 | other_currency, | 108 | other_currency, |
@@ -113,41 +113,6 @@ class Amount: | |||
113 | else: | 113 | else: |
114 | raise Exception("This asset is not available in the chosen market") | 114 | raise Exception("This asset is not available in the chosen market") |
115 | 115 | ||
116 | def get_ticker(self, c2, market, refresh=False): | ||
117 | c1 = self.currency | ||
118 | |||
119 | def invert(ticker): | ||
120 | return { | ||
121 | "inverted": True, | ||
122 | "average": (float(1/ticker["bid"]) + float(1/ticker["ask"]) ) / 2, | ||
123 | "notInverted": ticker, | ||
124 | } | ||
125 | def augment_ticker(ticker): | ||
126 | ticker.update({ | ||
127 | "inverted": False, | ||
128 | "average": (ticker["bid"] + ticker["ask"] ) / 2, | ||
129 | }) | ||
130 | |||
131 | if time.time() - self.ticker_cache_timestamp > 5: | ||
132 | self.ticker_cache = {} | ||
133 | self.ticker_cache_timestamp = time.time() | ||
134 | elif not refresh: | ||
135 | if (c1, c2, market.__class__) in self.ticker_cache: | ||
136 | return self.ticker_cache[(c1, c2, market.__class__)] | ||
137 | if (c2, c1, market.__class__) in self.ticker_cache: | ||
138 | return invert(self.ticker_cache[(c2, c1, market.__class__)]) | ||
139 | |||
140 | try: | ||
141 | self.ticker_cache[(c1, c2, market.__class__)] = market.fetch_ticker("{}/{}".format(c1, c2)) | ||
142 | augment_ticker(self.ticker_cache[(c1, c2, market.__class__)]) | ||
143 | except ccxt.ExchangeError: | ||
144 | try: | ||
145 | self.ticker_cache[(c2, c1, market.__class__)] = market.fetch_ticker("{}/{}".format(c2, c1)) | ||
146 | augment_ticker(self.ticker_cache[(c2, c1, market.__class__)]) | ||
147 | except ccxt.ExchangeError: | ||
148 | self.ticker_cache[(c1, c2, market.__class__)] = None | ||
149 | return self.get_ticker(c2, market) | ||
150 | |||
151 | def __abs__(self): | 116 | def __abs__(self): |
152 | return Amount(self.currency, 0, int_val=abs(self._value)) | 117 | return Amount(self.currency, 0, int_val=abs(self._value)) |
153 | 118 | ||
@@ -212,7 +177,6 @@ class Amount: | |||
212 | 177 | ||
213 | class Balance: | 178 | class Balance: |
214 | known_balances = {} | 179 | known_balances = {} |
215 | trades = {} | ||
216 | 180 | ||
217 | def __init__(self, currency, total_value, free_value, used_value): | 181 | def __init__(self, currency, total_value, free_value, used_value): |
218 | self.currency = currency | 182 | self.currency = currency |
@@ -288,8 +252,52 @@ class Trade: | |||
288 | self.base_currency = self.value_from.currency | 252 | self.base_currency = self.value_from.currency |
289 | 253 | ||
290 | if market is not None: | 254 | if market is not None: |
255 | self.market = market | ||
291 | self.prepare_order(market) | 256 | self.prepare_order(market) |
292 | 257 | ||
258 | fees_cache = {} | ||
259 | @classmethod | ||
260 | def fetch_fees(cls, market): | ||
261 | if market.__class__ not in cls.fees_cache: | ||
262 | cls.fees_cache[market.__class__] = market.fetch_fees() | ||
263 | return cls.fees_cache[market.__class__] | ||
264 | |||
265 | ticker_cache = {} | ||
266 | ticker_cache_timestamp = time.time() | ||
267 | @classmethod | ||
268 | def get_ticker(cls, c1, c2, market, refresh=False): | ||
269 | def invert(ticker): | ||
270 | return { | ||
271 | "inverted": True, | ||
272 | "average": (float(1/ticker["bid"]) + float(1/ticker["ask"]) ) / 2, | ||
273 | "original": ticker, | ||
274 | } | ||
275 | def augment_ticker(ticker): | ||
276 | ticker.update({ | ||
277 | "inverted": False, | ||
278 | "average": (ticker["bid"] + ticker["ask"] ) / 2, | ||
279 | }) | ||
280 | |||
281 | if time.time() - cls.ticker_cache_timestamp > 5: | ||
282 | cls.ticker_cache = {} | ||
283 | cls.ticker_cache_timestamp = time.time() | ||
284 | elif not refresh: | ||
285 | if (c1, c2, market.__class__) in cls.ticker_cache: | ||
286 | return cls.ticker_cache[(c1, c2, market.__class__)] | ||
287 | if (c2, c1, market.__class__) in cls.ticker_cache: | ||
288 | return invert(cls.ticker_cache[(c2, c1, market.__class__)]) | ||
289 | |||
290 | try: | ||
291 | cls.ticker_cache[(c1, c2, market.__class__)] = market.fetch_ticker("{}/{}".format(c1, c2)) | ||
292 | augment_ticker(cls.ticker_cache[(c1, c2, market.__class__)]) | ||
293 | except ccxt.ExchangeError: | ||
294 | try: | ||
295 | cls.ticker_cache[(c2, c1, market.__class__)] = market.fetch_ticker("{}/{}".format(c2, c1)) | ||
296 | augment_ticker(cls.ticker_cache[(c2, c1, market.__class__)]) | ||
297 | except ccxt.ExchangeError: | ||
298 | cls.ticker_cache[(c1, c2, market.__class__)] = None | ||
299 | return cls.get_ticker(c1, c2, market) | ||
300 | |||
293 | @classmethod | 301 | @classmethod |
294 | def compute_trades(cls, values_in_base, new_repartition, market=None): | 302 | def compute_trades(cls, values_in_base, new_repartition, market=None): |
295 | base_currency = sum(values_in_base.values()).currency | 303 | base_currency = sum(values_in_base.values()).currency |
@@ -316,7 +324,7 @@ class Trade: | |||
316 | else: | 324 | else: |
317 | return "sell" | 325 | return "sell" |
318 | 326 | ||
319 | def ticker_action(self, inverted): | 327 | def order_action(self, inverted): |
320 | if self.value_from < self.value_to: | 328 | if self.value_from < self.value_to: |
321 | return "ask" if not inverted else "bid" | 329 | return "ask" if not inverted else "bid" |
322 | else: | 330 | else: |
@@ -334,13 +342,13 @@ class Trade: | |||
334 | delta = abs(value_to - value_from) | 342 | delta = abs(value_to - value_from) |
335 | currency = self.base_currency | 343 | currency = self.base_currency |
336 | else: | 344 | else: |
337 | ticker = ticker["notInverted"] | 345 | ticker = ticker["original"] |
338 | delta = abs(self.value_to - self.value_from) | 346 | delta = abs(self.value_to - self.value_from) |
339 | currency = self.currency | 347 | currency = self.currency |
340 | 348 | ||
341 | rate = ticker[self.ticker_action(inverted)] | 349 | rate = ticker[self.order_action(inverted)] |
342 | 350 | ||
343 | self.orders.append(Order(self.ticker_action(inverted), delta, rate, currency)) | 351 | self.orders.append(Order(self.order_action(inverted), delta, rate, currency)) |
344 | 352 | ||
345 | @classmethod | 353 | @classmethod |
346 | def all_orders(cls): | 354 | def all_orders(cls): |
@@ -408,12 +416,6 @@ class Order: | |||
408 | self.status = result["status"] | 416 | self.status = result["status"] |
409 | return self.status | 417 | return self.status |
410 | 418 | ||
411 | @static_var("cache", {}) | ||
412 | def fetch_fees(market): | ||
413 | if market.__class__ not in fetch_fees.cache: | ||
414 | fetch_fees.cache[market.__class__] = market.fetch_fees() | ||
415 | return fetch_fees.cache[market.__class__] | ||
416 | |||
417 | def print_orders(market, base_currency="BTC"): | 419 | def print_orders(market, base_currency="BTC"): |
418 | Balance.prepare_trades(market, base_currency=base_currency) | 420 | Balance.prepare_trades(market, base_currency=base_currency) |
419 | for currency, trade in Trade.trades.items(): | 421 | for currency, trade in Trade.trades.items(): |