def propose_trades_for_partial_rebalancing(
self,
market_state: MarketState,
coins_to_rebalance: FrozenSet[str],
) -> List[AbstractTrade]:
"""TODO: Trade directly from X to Y without going through fiat.
"""
ideal_fiat_value_per_coin = self._ideal_fiat_value_per_coin(market_state)
est_values = market_state.estimate_values(market_state.balances, self.fiat)
# 1) Fan in to fiat, selling excess value in coins we want to rebalance
trades_to_fiat = []
for sell_coin in sorted(coins_to_rebalance):
if sell_coin == self.fiat:
continue
value = est_values.get(sell_coin, 0)
delta = value - ideal_fiat_value_per_coin
if delta > 0:
trades_to_fiat.append(
AbstractTrade(sell_coin, self.fiat, self.fiat, delta),
)
# 2) Simulate trades and estimate portfolio state afterwards
est_balances_after_trades = simulate_trades(
trades_to_fiat,
market_state,
)
est_values_after_trades = market_state.estimate_values(
est_balances_after_trades,
self.fiat,
)
fiat_after_trades = est_balances_after_trades[self.fiat]
fiat_to_redistribute = fiat_after_trades - ideal_fiat_value_per_coin
if fiat_to_redistribute <= 0:
return trades_to_fiat
# 3) Find coins in which we don't hold enough value
possible_buys = set()
for buy_coin in self._possible_investments(market_state):
value = est_values_after_trades.get(buy_coin, 0)
if ideal_fiat_value_per_coin > value:
possible_buys.add(buy_coin)
fiat_to_redistribute_per_coin = fiat_to_redistribute / len(possible_buys)
# 4) Plan trades, fanning back out from fiat to others
trades_from_fiat = []
for buy_coin in sorted(possible_buys):
value = est_values_after_trades.get(buy_coin, 0)
delta = ideal_fiat_value_per_coin - value
if delta > 0:
available_fiat = min(fiat_to_redistribute_per_coin, delta)
trades_from_fiat.append(
AbstractTrade(self.fiat, buy_coin, self.fiat, available_fiat),
)
return trades_to_fiat + trades_from_fiat
评论列表
文章目录