]>
Commit | Line | Data |
---|---|---|
269ec87c | 1 | import ccxt |
4c51aa71 IB |
2 | # Put your poloniex api key in market.py |
3 | from market import market | |
269ec87c | 4 | |
987bd3d3 IB |
5 | def static_var(varname, value): |
6 | def decorate(func): | |
7 | setattr(func, varname, value) | |
8 | return func | |
9 | return decorate | |
10 | ||
269ec87c | 11 | max_digits = 18 |
269ec87c IB |
12 | |
13 | repartition_pertenthousand = { | |
14 | "BTC": 2857, | |
15 | "ZEC": 3701, | |
16 | "DOGE": 1805, | |
17 | "DGB": 1015, | |
18 | "SC": 623, | |
19 | } | |
20 | ||
269ec87c IB |
21 | |
22 | def formatted_price(value): | |
23 | return round(value / 10**max_digits, 8) | |
24 | ||
987bd3d3 | 25 | @static_var("cache", {}) |
269ec87c | 26 | def get_ticker(c1, c2, market): |
987bd3d3 IB |
27 | def invert(ticker): |
28 | return { | |
48bedc24 | 29 | "inverted": True, |
987bd3d3 IB |
30 | "bid": float(1/ticker["ask"]), |
31 | "ask": float(1/ticker["bid"]), | |
48bedc24 IB |
32 | "bidA": float(1/ticker["askA"]), |
33 | "askA": float(1/ticker["bidA"]), | |
987bd3d3 | 34 | } |
48bedc24 IB |
35 | def augment_ticker(ticker): |
36 | # FIXME: need to do better than just a multiplier | |
37 | ticker.update({ | |
38 | "inverted": False, | |
39 | "bidA": ticker["bid"] * 0.99, | |
40 | "askA": ticker["ask"] * 1.01, | |
41 | }) | |
987bd3d3 IB |
42 | |
43 | if (c1, c2, market.__class__) in get_ticker.cache: | |
44 | return get_ticker.cache[(c1, c2, market.__class__)] | |
45 | if (c2, c1, market.__class__) in get_ticker.cache: | |
46 | return invert(get_ticker.cache[(c2, c1, market.__class__)]) | |
47 | ||
269ec87c | 48 | try: |
987bd3d3 | 49 | get_ticker.cache[(c1, c2, market.__class__)] = market.fetch_ticker("{}/{}".format(c1, c2)) |
48bedc24 | 50 | augment_ticker(get_ticker.cache[(c1, c2, market.__class__)]) |
269ec87c IB |
51 | except ccxt.ExchangeError: |
52 | try: | |
987bd3d3 | 53 | get_ticker.cache[(c2, c1, market.__class__)] = market.fetch_ticker("{}/{}".format(c2, c1)) |
48bedc24 | 54 | augment_ticker(get_ticker.cache[(c2, c1, market.__class__)]) |
269ec87c | 55 | except ccxt.ExchangeError: |
987bd3d3 IB |
56 | get_ticker.cache[(c1, c2, market.__class__)] = None |
57 | return get_ticker(c1, c2, market) | |
269ec87c | 58 | |
73e77742 IB |
59 | def fetch_balances(market): |
60 | balances = {} | |
61 | fetched_balance = market.fetch_balance() | |
62 | for key, value in fetched_balance["total"].items(): | |
63 | if value > 0: | |
64 | balances[key] = int(value * 10**max_digits) | |
65 | return balances | |
66 | ||
269ec87c IB |
67 | def assets_value(assets, market, base_currency="BTC"): |
68 | repartition_in_base_currency = {} | |
69 | for currency, asset_value in assets.items(): | |
70 | if currency == base_currency: | |
71 | repartition_in_base_currency[currency] = asset_value | |
72 | else: | |
73 | asset_ticker = get_ticker(currency, base_currency, market) | |
74 | if asset_ticker is None: | |
75 | raise Exception("This asset is not available in the chosen market") | |
48bedc24 | 76 | repartition_in_base_currency[currency] = int(asset_ticker["bidA"] * asset_value) |
269ec87c IB |
77 | return repartition_in_base_currency |
78 | ||
79 | def dispatch_assets(base_currency_value, repartition_pertenthousand, market, base_currency="BTC"): | |
80 | sum_pertenthousand = sum([v for k, v in repartition_pertenthousand.items()]) | |
81 | repartition_in_base_currency = {} | |
82 | for currency, ptt in repartition_pertenthousand.items(): | |
83 | repartition_in_base_currency[currency] = int(ptt * base_currency_value / sum_pertenthousand) | |
84 | return repartition_in_base_currency | |
85 | ||
86 | def give_orders(current_assets, repartition_pertenthousand, market, base_currency="BTC"): | |
87 | value_in_base = assets_value(current_assets, market, base_currency=base_currency) | |
88 | total_base_value = sum([ v for k, v in value_in_base.items()]) | |
89 | ||
90 | new_repartition = dispatch_assets(total_base_value, repartition_pertenthousand, market, base_currency=base_currency) | |
91 | mouvements = {} | |
92 | ||
93 | for key in set(value_in_base.keys()).union(set(new_repartition.keys())): | |
94 | mouvements[key] = value_in_base.get(key, 0) - new_repartition.get(key, 0) | |
95 | ||
96 | print("assets before repartition:") | |
97 | for currency, value in current_assets.items(): | |
98 | print("holding {} {}".format( | |
99 | formatted_price(value), | |
100 | currency)) | |
101 | print("------------") | |
102 | for currency, value in mouvements.items(): | |
103 | if currency == base_currency: | |
104 | continue | |
105 | asset_ticker = get_ticker(currency, base_currency, market) | |
106 | if value > 0: | |
107 | action = "sell" | |
108 | currency_price = int(value / asset_ticker["bid"]) | |
109 | else: | |
110 | action = "buy" | |
111 | currency_price = int(value / asset_ticker["ask"]) | |
112 | if value != 0: | |
113 | print("need to {} {} {}'s worth of {}, i.e. {} {}".format( | |
114 | action, | |
115 | formatted_price(abs(value)), | |
116 | base_currency, | |
117 | currency, | |
118 | formatted_price(abs(currency_price)), | |
119 | currency)) | |
120 | print("------------\nassets after repartition:") | |
121 | for currency, value in new_repartition.items(): | |
122 | print("holding {} {}".format(formatted_price(value), currency)) | |
123 | ||
73e77742 | 124 | current_assets = fetch_balances(market) |
269ec87c | 125 | give_orders(current_assets, repartition_pertenthousand, market) |