1 from ccxt
import ExchangeError
3 from decimal
import Decimal
as D
, ROUND_DOWN
4 # Put your poloniex api key in market.py
5 from market
import market
6 from json
import JSONDecodeError
9 # FIXME: correctly handle web call timeouts
13 URL
= "https://cryptoportfolio.io/wp-content/uploads/portfolio/json/cryptoportfolio.json"
18 def repartition(cls
, liquidity
="medium"):
19 cls
.parse_cryptoportfolio()
20 liquidities
= cls
.liquidities
[liquidity
]
21 cls
.last_date
= sorted(liquidities
.keys())[-1]
22 return liquidities
[cls
.last_date
]
25 def get_cryptoportfolio(cls
):
27 r
= requests
.get(cls
.URL
)
31 cls
.data
= r
.json(parse_int
=D
, parse_float
=D
)
32 except JSONDecodeError
:
36 def parse_cryptoportfolio(cls
):
38 cls
.get_cryptoportfolio()
40 def filter_weights(weight_hash
):
41 if weight_hash
[1][0] == 0:
43 if weight_hash
[0] == "_row":
48 def clean_weights_(h
):
49 if h
[0].endswith("s"):
50 return [h
[0][0:-1], (h
[1][i
], "short")]
52 return [h
[0], (h
[1][i
], "long")]
55 def parse_weights(portfolio_hash
):
56 weights_hash
= portfolio_hash
["weights"]
58 for i
in range(len(weights_hash
["_row"])):
59 weights
[weights_hash
["_row"][i
]] = dict(filter(
61 map(clean_weights(i
), weights_hash
.items())))
64 high_liquidity
= parse_weights(cls
.data
["portfolio_1"])
65 medium_liquidity
= parse_weights(cls
.data
["portfolio_2"])
68 "medium": medium_liquidity
,
69 "high": high_liquidity
,
73 def __init__(self
, currency
, value
, linked_to
=None, ticker
=None, rate
=None):
74 self
.currency
= currency
76 self
.linked_to
= linked_to
80 def in_currency(self
, other_currency
, market
, rate
=None, action
=None, compute_value
="average"):
81 if other_currency
== self
.currency
:
89 asset_ticker
= Trade
.get_ticker(self
.currency
, other_currency
, market
)
90 if asset_ticker
is not None:
91 rate
= Trade
.compute_value(asset_ticker
, action
, compute_value
=compute_value
)
99 raise Exception("This asset is not available in the chosen market")
101 def __round__(self
, n
=8):
102 return Amount(self
.currency
, self
.value
.quantize(D(1)/D(10**n
), rounding
=ROUND_DOWN
))
105 return Amount(self
.currency
, abs(self
.value
))
107 def __add__(self
, other
):
108 if other
.currency
!= self
.currency
and other
.value
* self
.value
!= 0:
109 raise Exception("Summing amounts must be done with same currencies")
110 return Amount(self
.currency
, self
.value
+ other
.value
)
112 def __radd__(self
, other
):
116 return self
.__add
__(other
)
118 def __sub__(self
, other
):
121 if other
.currency
!= self
.currency
and other
.value
* self
.value
!= 0:
122 raise Exception("Summing amounts must be done with same currencies")
123 return Amount(self
.currency
, self
.value
- other
.value
)
125 def __mul__(self
, value
):
126 if not isinstance(value
, (int, float, D
)):
127 raise TypeError("Amount may only be multiplied by numbers")
128 return Amount(self
.currency
, self
.value
* value
)
130 def __rmul__(self
, value
):
131 return self
.__mul
__(value
)
133 def __floordiv__(self
, value
):
134 if not isinstance(value
, (int, float, D
)):
135 raise TypeError("Amount may only be multiplied by integers")
136 return Amount(self
.currency
, self
.value
/ value
)
138 def __truediv__(self
, value
):
139 return self
.__floordiv
__(value
)
141 def __lt__(self
, other
):
143 return self
.value
< 0
144 if self
.currency
!= other
.currency
:
145 raise Exception("Comparing amounts must be done with same currencies")
146 return self
.value
< other
.value
148 def __le__(self
, other
):
149 return self
== other
or self
< other
151 def __gt__(self
, other
):
152 return not self
<= other
154 def __ge__(self
, other
):
155 return not self
< other
157 def __eq__(self
, other
):
159 return self
.value
== 0
160 if self
.currency
!= other
.currency
:
161 raise Exception("Comparing amounts must be done with same currencies")
162 return self
.value
== other
.value
164 def __ne__(self
, other
):
165 return not self
== other
168 return Amount(self
.currency
, - self
.value
)
171 if self
.linked_to
is None:
172 return "{:.8f} {}".format(self
.value
, self
.currency
)
174 return "{:.8f} {} [{}]".format(self
.value
, self
.currency
, self
.linked_to
)
177 if self
.linked_to
is None:
178 return "Amount({:.8f} {})".format(self
.value
, self
.currency
)
180 return "Amount({:.8f} {} -> {})".format(self
.value
, self
.currency
, repr(self
.linked_to
))
185 def __init__(self
, currency
, hash_
):
186 self
.currency
= currency
188 "exchange_total", "exchange_used", "exchange_free",
189 "margin_total", "margin_borrowed", "margin_free"]:
190 setattr(self
, key
, Amount(currency
, hash_
.get(key
, 0)))
192 self
.margin_position_type
= hash_
.get("margin_position_type")
194 if hash_
.get("margin_borrowed_base_currency") is not None:
195 base_currency
= hash_
["margin_borrowed_base_currency"]
197 "margin_liquidation_price",
198 "margin_pending_gain",
199 "margin_lending_fees",
200 "margin_borrowed_base_price"
202 setattr(self
, key
, Amount(base_currency
, hash_
.get(key
, 0)))
205 def in_currency(cls
, other_currency
, market
, compute_value
="average", type="total"):
207 for currency
in cls
.known_balances
:
208 balance
= cls
.known_balances
[currency
]
209 other_currency_amount
= getattr(balance
, type)\
210 .in_currency(other_currency
, market
, compute_value
=compute_value
)
211 amounts
[currency
] = other_currency_amount
216 return cls
.known_balances
.keys()
219 def fetch_balances(cls
, market
):
220 all_balances
= market
.fetch_all_balances()
221 for currency
, balance
in all_balances
.items():
222 if balance
["exchange_total"] != 0 or balance
["margin_total"] != 0 or \
223 currency
in cls
.known_balances
:
224 cls
.known_balances
[currency
] = cls(currency
, balance
)
225 return cls
.known_balances
228 def dispatch_assets(cls
, amount
, repartition
=None):
229 if repartition
is None:
230 repartition
= Portfolio
.repartition()
231 sum_ratio
= sum([v
[0] for k
, v
in repartition
.items()])
233 for currency
, (ptt
, trade_type
) in repartition
.items():
234 amounts
[currency
] = ptt
* amount
/ sum_ratio
235 if trade_type
== "short":
236 amounts
[currency
] = - amounts
[currency
]
237 if currency
not in cls
.known_balances
:
238 cls
.known_balances
[currency
] = cls(currency
, {})
242 def prepare_trades(cls
, market
, base_currency
="BTC", compute_value
="average", debug
=False):
243 cls
.fetch_balances(market
)
244 values_in_base
= cls
.in_currency(base_currency
, market
, compute_value
=compute_value
)
245 total_base_value
= sum(values_in_base
.values())
246 new_repartition
= cls
.dispatch_assets(total_base_value
)
247 # Recompute it in case we have new currencies
248 values_in_base
= cls
.in_currency(base_currency
, market
, compute_value
=compute_value
)
249 Trade
.compute_trades(values_in_base
, new_repartition
, market
=market
, debug
=debug
)
252 def update_trades(cls
, market
, base_currency
="BTC", compute_value
="average", only
=None, debug
=False):
253 cls
.fetch_balances(market
)
254 values_in_base
= cls
.in_currency(base_currency
, market
, compute_value
=compute_value
)
255 total_base_value
= sum(values_in_base
.values())
256 new_repartition
= cls
.dispatch_assets(total_base_value
)
257 Trade
.compute_trades(values_in_base
, new_repartition
, only
=only
, market
=market
, debug
=debug
)
260 def prepare_trades_to_sell_all(cls
, market
, base_currency
="BTC", compute_value
="average", debug
=False):
261 cls
.fetch_balances(market
)
262 values_in_base
= cls
.in_currency(base_currency
, market
, compute_value
=compute_value
)
263 total_base_value
= sum(values_in_base
.values())
264 new_repartition
= cls
.dispatch_assets(total_base_value
, repartition
={ base_currency: (1, "long") }
)
265 Trade
.compute_trades(values_in_base
, new_repartition
, market
=market
, debug
=debug
)
268 if self
.exchange_total
> 0:
269 if self
.exchange_free
> 0 and self
.exchange_used
> 0:
270 exchange
= " Exch: [✔{} + ❌{} = {}]".format(str(self
.exchange_free
), str(self
.exchange_used
), str(self
.exchange_total
))
271 elif self
.exchange_free
> 0:
272 exchange
= " Exch: [✔{}]".format(str(self
.exchange_free
))
274 exchange
= " Exch: [❌{}]".format(str(self
.exchange_used
))
278 if self
.margin_total
> 0:
279 if self
.margin_free
!= 0 and self
.margin_borrowed
!= 0:
280 margin
= " Margin: [✔{} + borrowed {} = {}]".format(str(self
.margin_free
), str(self
.margin_borrowed
), str(self
.margin_total
))
281 elif self
.margin_free
!= 0:
282 margin
= " Margin: [✔{}]".format(str(self
.margin_free
))
284 margin
= " Margin: [borrowed {}]".format(str(self
.margin_borrowed
))
285 elif self
.margin_total
< 0:
286 margin
= " Margin: [{} @@ {}/{}]".format(str(self
.margin_total
),
287 str(self
.margin_borrowed_base_price
),
288 str(self
.margin_lending_fees
))
292 if self
.margin_total
!= 0 and self
.exchange_total
!= 0:
293 total
= " Total: [{}]".format(str(self
.total
))
297 return "Balance({}".format(self
.currency
) + "".join([exchange
, margin
, total
]) + ")"
301 "default": lambda x
, y
: x
[y
],
302 "average": lambda x
, y
: x
["average"],
303 "bid": lambda x
, y
: x
["bid"],
304 "ask": lambda x
, y
: x
["ask"],
311 def __init__(self
, value_from
, value_to
, currency
, market
=None):
312 # We have value_from of currency, and want to finish with value_to of
313 # that currency. value_* may not be in currency's terms
314 self
.currency
= currency
315 self
.value_from
= value_from
316 self
.value_to
= value_to
319 assert self
.value_from
.currency
== self
.value_to
.currency
320 if self
.value_from
!= 0:
321 assert self
.value_from
.linked_to
is not None and self
.value_from
.linked_to
.currency
== self
.currency
322 elif self
.value_from
.linked_to
is None:
323 self
.value_from
.linked_to
= Amount(self
.currency
, 0)
324 self
.base_currency
= self
.value_from
.currency
328 def fetch_fees(cls
, market
):
329 if market
.__class
__ not in cls
.fees_cache
:
330 cls
.fees_cache
[market
.__class
__] = market
.fetch_fees()
331 return cls
.fees_cache
[market
.__class
__]
334 ticker_cache_timestamp
= time
.time()
336 def get_ticker(cls
, c1
, c2
, market
, refresh
=False):
340 "average": (1/ticker
["bid"] + 1/ticker
["ask"]) / 2,
343 def augment_ticker(ticker
):
346 "average": (ticker
["bid"] + ticker
["ask"] ) / 2,
349 if time
.time() - cls
.ticker_cache_timestamp
> 5:
350 cls
.ticker_cache
= {}
351 cls
.ticker_cache_timestamp
= time
.time()
353 if (c1
, c2
, market
.__class
__) in cls
.ticker_cache
:
354 return cls
.ticker_cache
[(c1
, c2
, market
.__class
__)]
355 if (c2
, c1
, market
.__class
__) in cls
.ticker_cache
:
356 return invert(cls
.ticker_cache
[(c2
, c1
, market
.__class
__)])
359 cls
.ticker_cache
[(c1
, c2
, market
.__class
__)] = market
.fetch_ticker("{}/{}".format(c1
, c2
))
360 augment_ticker(cls
.ticker_cache
[(c1
, c2
, market
.__class
__)])
361 except ExchangeError
:
363 cls
.ticker_cache
[(c2
, c1
, market
.__class
__)] = market
.fetch_ticker("{}/{}".format(c2
, c1
))
364 augment_ticker(cls
.ticker_cache
[(c2
, c1
, market
.__class
__)])
365 except ExchangeError
:
366 cls
.ticker_cache
[(c1
, c2
, market
.__class
__)] = None
367 return cls
.get_ticker(c1
, c2
, market
)
370 def compute_trades(cls
, values_in_base
, new_repartition
, only
=None, market
=None, debug
=False):
371 cls
.debug
= cls
.debug
or debug
372 base_currency
= sum(values_in_base
.values()).currency
373 for currency
in Balance
.currencies():
374 if currency
== base_currency
:
376 value_from
= values_in_base
.get(currency
, Amount(base_currency
, 0))
377 value_to
= new_repartition
.get(currency
, Amount(base_currency
, 0))
378 if value_from
.value
* value_to
.value
< 0:
379 trade_1
= cls(value_from
, Amount(base_currency
, 0), currency
, market
=market
)
380 if only
is None or trade_1
.action
== only
:
381 cls
.trades
.append(trade_1
)
382 trade_2
= cls(Amount(base_currency
, 0), value_to
, currency
, market
=market
)
383 if only
is None or trade_2
.action
== only
:
384 cls
.trades
.append(trade_2
)
392 if only
is None or trade
.action
== only
:
393 cls
.trades
.append(trade
)
397 def prepare_orders(cls
, only
=None, compute_value
="default"):
398 for trade
in cls
.trades
:
399 if only
is None or trade
.action
== only
:
400 trade
.prepare_order(compute_value
=compute_value
)
403 def move_balances(cls
, market
):
404 needed_in_margin
= {}
405 for trade
in cls
.trades
:
406 if trade
.trade_type
== "short":
407 if trade
.value_to
.currency
not in needed_in_margin
:
408 needed_in_margin
[trade
.value_to
.currency
] = 0
409 needed_in_margin
[trade
.value_to
.currency
] += abs(trade
.value_to
)
410 for currency
, needed
in needed_in_margin
.items():
411 current_balance
= Balance
.known_balances
[currency
].margin_free
412 delta
= (needed
- current_balance
).value
413 # FIXME: don't remove too much if there are open margin position
416 print("market.transfer_balance({}, {}, 'exchange', 'margin')".format(currency
, delta
))
418 market
.transfer_balance(currency
, delta
, "exchange", "margin")
421 print("market.transfer_balance({}, {}, 'margin', 'exchange')".format(currency
, -delta
))
423 market
.transfer_balance(currency
, -delta
, "margin", "exchange")
427 if self
.value_from
== self
.value_to
:
429 if self
.base_currency
== self
.currency
:
432 if self
.value_from
< self
.value_to
:
437 def order_action(self
, inverted
):
438 if (self
.value_from
< self
.value_to
) != inverted
:
444 def trade_type(self
):
445 if self
.value_from
+ self
.value_to
< 0:
451 def filled_amount(self
):
453 for order
in self
.orders
:
454 filled_amount
+= order
.filled_amount
457 def update_order(self
, order
, tick
):
459 if tick
in [0, 1, 3, 4, 6]:
460 print("{}, tick {}, waiting".format(order
, tick
))
462 self
.prepare_order(compute_value
=lambda x
, y
: (x
[y
] + x
["average"]) / 2)
463 new_order
= self
.orders
[-1]
464 print("{}, tick {}, cancelling and adjusting to {}".format(order
, tick
, new_order
))
466 self
.prepare_order(compute_value
=lambda x
, y
: (x
[y
]*2 + x
["average"]) / 3)
467 new_order
= self
.orders
[-1]
468 print("{}, tick {}, cancelling and adjusting to {}".format(order
, tick
, new_order
))
471 print("{}, tick {}, fallbacking to market value".format(order
, tick
))
472 if (tick
- 7) % 3 == 0:
473 self
.prepare_order(compute_value
="default")
474 new_order
= self
.orders
[-1]
475 print("{}, tick {}, market value, cancelling and adjusting to {}".format(order
, tick
, new_order
))
477 if new_order
is not None:
481 def prepare_order(self
, compute_value
="default"):
482 if self
.action
is None:
484 ticker
= Trade
.get_ticker(self
.currency
, self
.base_currency
, self
.market
)
485 inverted
= ticker
["inverted"]
487 ticker
= ticker
["original"]
488 rate
= Trade
.compute_value(ticker
, self
.order_action(inverted
), compute_value
=compute_value
)
491 delta_in_base
= abs(self
.value_from
- self
.value_to
)
492 # 9 BTC's worth of move (10 - 1 or 1 - 10 depending on case)
495 currency
= self
.base_currency
497 if self
.action
== "dispose":
498 # I have 10 BTC worth of FOO, and I want to sell 9 BTC worth of it
499 # At rate 1 Foo = 0.1 BTC
500 value_from
= self
.value_from
.linked_to
501 # value_from = 100 FOO
502 value_to
= self
.value_to
.in_currency(self
.currency
, self
.market
, rate
=1/self
.value_from
.rate
)
503 # value_to = 10 FOO (1 BTC * 1/0.1)
504 delta
= abs(value_to
- value_from
)
506 # Action: "sell" "90 FOO" at rate "0.1" "BTC" on "market"
508 # Note: no rounding error possible: if we have value_to == 0, then delta == value_from
510 delta
= delta_in_base
.in_currency(self
.currency
, self
.market
, rate
=1/rate
)
511 # I want to buy 9 / 0.1 FOO
512 # Action: "buy" "90 FOO" at rate "0.1" "BTC" on "market"
514 currency
= self
.currency
516 delta
= delta_in_base
518 # I have 10 BTC worth of FOO, and I want to sell 9 BTC worth of it
519 # At rate 1 Foo = 0.1 BTC
520 # Action: "buy" "9 BTC" at rate "1/0.1" "FOO" on market
522 # I want to buy 9 / 0.1 FOO
523 # Action: "sell" "9 BTC" at rate "1/0.1" "FOO" on "market"
524 if self
.value_to
== 0:
525 rate
= self
.value_from
.linked_to
.value
/ self
.value_from
.value
526 # Recompute the rate to avoid any rounding error
528 close_if_possible
= (self
.value_to
== 0)
530 if delta
<= self
.filled_amount
:
531 print("Less to do than already filled: {} <= {}".format(delta
,
535 self
.orders
.append(Order(self
.order_action(inverted
),
536 delta
- self
.filled_amount
, rate
, currency
, self
.trade_type
,
537 self
.market
, self
, close_if_possible
=close_if_possible
))
540 def compute_value(cls
, ticker
, action
, compute_value
="default"):
545 if isinstance(compute_value
, str):
546 compute_value
= Computation
.computations
[compute_value
]
547 return compute_value(ticker
, action
)
550 def all_orders(cls
, state
=None):
551 all_orders
= sum(map(lambda v
: v
.orders
, cls
.trades
), [])
555 return list(filter(lambda o
: o
.status
== state
, all_orders
))
559 for order
in cls
.all_orders(state
="pending"):
563 def follow_orders(cls
, verbose
=True, sleep
=None):
565 sleep
= 7 if cls
.debug
else 30
567 while len(cls
.all_orders(state
="open")) > 0:
570 for order
in cls
.all_orders(state
="open"):
571 if order
.get_status() != "open":
573 print("finished {}".format(order
))
575 order
.trade
.update_order(order
, tick
)
577 print("All orders finished")
580 def update_all_orders_status(cls
):
581 for order
in cls
.all_orders(state
="open"):
585 return "Trade({} -> {} in {}, {})".format(
592 def print_all_with_order(cls
):
593 for trade
in cls
.trades
:
594 trade
.print_with_order()
596 def print_with_order(self
):
598 for order
in self
.orders
:
599 print("\t", order
, sep
="")
602 def __init__(self
, action
, amount
, rate
, base_currency
, trade_type
, market
,
603 trade
, close_if_possible
=False):
607 self
.base_currency
= base_currency
609 self
.trade_type
= trade_type
612 self
.status
= "pending"
614 self
.close_if_possible
= close_if_possible
615 self
.debug
= trade
.debug
618 return "Order({} {} {} at {} {} [{}]{})".format(
625 " ✂" if self
.close_if_possible
else "",
630 if self
.trade_type
== "long":
637 return self
.status
== "pending"
641 return self
.status
== "closed" or self
.status
== "canceled" or self
.status
== "error"
645 return self
.results
[0]["id"]
648 symbol
= "{}/{}".format(self
.amount
.currency
, self
.base_currency
)
649 amount
= round(self
.amount
, self
.market
.order_precision(symbol
)).value
652 print("market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(
653 symbol
, self
.action
, amount
, self
.rate
, self
.account
))
655 self
.results
.append({"debug": True, "id": -1}
)
658 self
.results
.append(self
.market
.create_order(symbol
, 'limit', self
.action
, amount
, price
=self
.rate
, account
=self
.account
))
660 except Exception as e
:
661 self
.status
= "error"
662 print("error when running market.create_order('{}', 'limit', '{}', {}, price={}, account={})".format(
663 symbol
, self
.action
, amount
, self
.rate
, self
.account
))
664 self
.error_message
= str("{}: {}".format(e
.__class
__.__name
__, e
))
665 print(self
.error_message
)
667 def get_status(self
):
670 # other states are "closed" and "canceled"
671 if self
.status
== "open":
673 if self
.status
!= "open":
674 self
.mark_finished_order()
677 def mark_finished_order(self
):
680 if self
.status
== "closed":
681 if self
.trade_type
== "short" and self
.action
== "buy" and self
.close_if_possible
:
682 self
.market
.close_margin_position(self
.amount
.currency
, self
.base_currency
)
684 fetch_cache_timestamp
= None
685 def fetch(self
, force
=False):
686 if self
.debug
or (not force
and self
.fetch_cache_timestamp
is not None
687 and time
.time() - self
.fetch_cache_timestamp
< 10):
689 self
.fetch_cache_timestamp
= time
.time()
691 self
.results
.append(self
.market
.fetch_order(self
.id))
692 result
= self
.results
[-1]
693 self
.status
= result
["status"]
694 # Time at which the order started
695 self
.timestamp
= result
["datetime"]
696 self
.fetch_mouvements()
698 # FIXME: consider open order with dust remaining as closed
701 def dust_amount_remaining(self
):
702 return self
.remaining_amount
< 0.001
705 def remaining_amount(self
):
706 if self
.status
== "open":
708 return self
.amount
- self
.filled_amount
711 def filled_amount(self
):
712 if self
.status
== "open":
714 filled_amount
= Amount(self
.amount
.currency
, 0)
715 for mouvement
in self
.mouvements
:
716 filled_amount
+= mouvement
.total
719 def fetch_mouvements(self
):
720 mouvements
= self
.market
.privatePostReturnOrderTrades({"orderNumber": self.id}
)
723 for mouvement_hash
in mouvements
:
724 self
.mouvements
.append(Mouvement(self
.amount
.currency
,
725 self
.base_currency
, mouvement_hash
))
729 self
.status
= "canceled"
731 self
.market
.cancel_order(self
.result
['id'])
735 def __init__(self
, currency
, base_currency
, hash_
):
736 self
.currency
= currency
737 self
.base_currency
= base_currency
738 self
.id = hash_
["id"]
739 self
.action
= hash_
["type"]
740 self
.fee_rate
= D(hash_
["fee"])
741 self
.date
= datetime
.strptime(hash_
["date"], '%Y-%m-%d %H:%M:%S')
742 self
.rate
= D(hash_
["rate"])
743 self
.total
= Amount(currency
, hash_
["amount"])
744 # rate * total = total_in_base
745 self
.total_in_base
= Amount(base_currency
, hash_
["total"])
747 def print_orders(market
, base_currency
="BTC"):
748 Balance
.prepare_trades(market
, base_currency
=base_currency
, compute_value
="average")
749 Trade
.prepare_orders(compute_value
="average")
750 for currency
, balance
in Balance
.known_balances
.items():
752 Trade
.print_all_with_order()
754 def make_orders(market
, base_currency
="BTC"):
755 Balance
.prepare_trades(market
, base_currency
=base_currency
)
756 for trade
in Trade
.trades
:
758 for order
in trade
.orders
:
759 print("\t", order
, sep
="")
762 def process_sell_all_sell(market
, base_currency
="BTC", debug
=False):
763 Balance
.prepare_trades_to_sell_all(market
, debug
=debug
)
764 Trade
.prepare_orders(compute_value
="average")
765 print("------------------")
766 for currency
, balance
in Balance
.known_balances
.items():
768 print("------------------")
769 Trade
.print_all_with_order()
770 print("------------------")
772 Trade
.follow_orders()
774 def process_sell_all_buy(market
, base_currency
="BTC", debug
=False):
775 Balance
.prepare_trades(market
, debug
=debug
)
776 Trade
.prepare_orders()
777 print("------------------")
778 for currency
, balance
in Balance
.known_balances
.items():
780 print("------------------")
781 Trade
.print_all_with_order()
782 print("------------------")
783 Trade
.move_balances(market
)
785 Trade
.follow_orders()
787 if __name__
== '__main__':