예제 #1
0
 def calc_simulated_position(self, balance: dict,
                             long_fills: [dict]) -> dict:
     """
     balance = {'BTC': {'free': float, 'locked': float, 'onhand': float}, ...}
     long_pfills = [{order...}, ...]
     """
     psize_long = round_dn(balance[self.coin]["onhand"], self.qty_step)
     long_pfills, short_pfills = get_position_fills(psize_long, 0.0,
                                                    self.fills)
     pprice_long = calc_pprice_long(psize_long,
                                    long_pfills) if psize_long else 0.0
     if psize_long * pprice_long < self.min_cost:
         psize_long, pprice_long, long_pfills = 0.0, 0.0, []
     position = {
         "long": {
             "size": psize_long,
             "price": pprice_long,
             "liquidation_price": 0.0,
         },
         "short": {
             "size": 0.0,
             "price": 0.0,
             "liquidation_price": 0.0
         },
         "wallet_balance":
         balance[self.quot]["onhand"] +
         balance[self.coin]["onhand"] * pprice_long,
     }
     return position
예제 #2
0
 def calc_simulated_position(self, balance: dict,
                             long_fills: [dict]) -> dict:
     '''
     balance = {'BTC': {'free': float, 'locked': float, 'onhand': float}, ...}
     long_pfills = [{order...}, ...]
     '''
     long_psize = round_dn(balance[self.coin]['onhand'], self.qty_step)
     long_pfills, shrt_pfills = get_position_fills(long_psize, 0.0,
                                                   self.fills)
     long_pprice = calc_long_pprice(long_psize,
                                    long_pfills) if long_psize else 0.0
     if long_psize * long_pprice < self.min_cost:
         long_psize, long_pprice, long_pfills = 0.0, 0.0, []
     position = {
         'long': {
             'size': long_psize,
             'price': long_pprice,
             'liquidation_price': 0.0
         },
         'shrt': {
             'size': 0.0,
             'price': 0.0,
             'liquidation_price': 0.0
         },
         'wallet_balance':
         balance[self.quot]['onhand'] +
         balance[self.coin]['onhand'] * long_pprice
     }
     return position
예제 #3
0
 def calc_orders(self):
     default_orders = super().calc_orders()
     orders = []
     remaining_cost = self.balance[self.quot]["onhand"]
     for order in sorted(default_orders,
                         key=lambda x: calc_diff(x["price"], self.price)):
         if order["price"] > min(
                 self.max_price,
                 round_dn(self.price * self.price_multiplier_up,
                          self.price_step),
         ):
             print(f'price {order["price"]} too high')
             continue
         if order["price"] < max(
                 self.min_price,
                 round_up(self.price * self.price_multiplier_dn,
                          self.price_step),
         ):
             print(f'price {order["price"]} too low')
             continue
         if order["side"] == "buy":
             cost = qty_to_cost(order["qty"], order["price"], self.inverse,
                                self.c_mult)
             if cost > remaining_cost:
                 adjusted_qty = round_dn(remaining_cost / order["price"],
                                         self.qty_step)
                 min_entry_qty = calc_min_entry_qty(
                     order["price"],
                     self.inverse,
                     self.qty_step,
                     self.min_qty,
                     self.min_cost,
                 )
                 if adjusted_qty >= min_entry_qty:
                     orders.append({**order, **{"qty": adjusted_qty}})
                     remaining_cost = 0.0
             else:
                 orders.append(order)
                 remaining_cost -= cost
         else:
             orders.append(order)
     return orders
예제 #4
0
def calc_recursive_entry_long(
    balance,
    psize,
    pprice,
    highest_bid,
    ema_band_lower,
    inverse,
    qty_step,
    price_step,
    min_qty,
    min_cost,
    c_mult,
    initial_qty_pct,
    initial_eprice_ema_dist,
    ddown_factor,
    rentry_pprice_dist,
    rentry_pprice_dist_wallet_exposure_weighting,
    wallet_exposure_limit,
    auto_unstuck_ema_dist,
    auto_unstuck_wallet_exposure_threshold,
):
    ientry_price = max(
        price_step,
        min(
            highest_bid,
            round_dn(ema_band_lower * (1 - initial_eprice_ema_dist),
                     price_step)),
    )
    min_entry_qty = calc_min_entry_qty(ientry_price, inverse, qty_step,
                                       min_qty, min_cost)
    ientry_qty = max(
        min_entry_qty,
        round_(
            cost_to_qty(balance, ientry_price, inverse, c_mult) *
            wallet_exposure_limit * initial_qty_pct,
            qty_step,
        ),
    )
    if psize == 0.0:
        # normal ientry
        return ientry_qty, ientry_price, "long_ientry_normal"
    elif psize < ientry_qty * 0.8:
        # partial ientry
        entry_qty = max(min_entry_qty, round_(ientry_qty - psize, qty_step))
        return entry_qty, ientry_price, "long_ientry_partial"
    else:
        wallet_exposure = qty_to_cost(psize, pprice, inverse, c_mult) / balance
        if wallet_exposure >= wallet_exposure_limit * 1.001:
            # no entry if wallet_exposure within 0.1% of limit
            return 0.0, 0.0, ""
        threshold = wallet_exposure_limit * (
            1 - auto_unstuck_wallet_exposure_threshold)
        if auto_unstuck_wallet_exposure_threshold != 0.0 and wallet_exposure > threshold * 0.99:
            # auto unstuck mode
            entry_price = round_dn(
                min([
                    highest_bid, pprice,
                    ema_band_lower * (1 - auto_unstuck_ema_dist)
                ]), price_step)
            entry_qty = find_entry_qty_bringing_wallet_exposure_to_target(
                balance, psize, pprice, wallet_exposure_limit, entry_price,
                inverse, qty_step, c_mult)
            min_entry_qty = calc_min_entry_qty(entry_price, inverse, qty_step,
                                               min_qty, min_cost)
            return (max(entry_qty,
                        min_entry_qty), entry_price, "long_unstuck_entry")
        else:
            # normal reentry
            ratio = wallet_exposure / wallet_exposure_limit
            entry_price = round_dn(
                pprice *
                (1 - rentry_pprice_dist *
                 (1 + ratio * rentry_pprice_dist_wallet_exposure_weighting)),
                price_step,
            )
            entry_price = min(highest_bid, entry_price)
            min_entry_qty = calc_min_entry_qty(entry_price, inverse, qty_step,
                                               min_qty, min_cost)
            entry_qty = max(min_entry_qty,
                            round_(psize * ddown_factor, qty_step))
            wallet_exposure_if_filled = calc_wallet_exposure_if_filled(
                balance, psize, pprice, entry_qty, entry_price, inverse,
                c_mult, qty_step)
            if wallet_exposure_if_filled > wallet_exposure_limit * 1.01:
                entry_qty = find_entry_qty_bringing_wallet_exposure_to_target(
                    balance,
                    psize,
                    pprice,
                    wallet_exposure_limit,
                    entry_price,
                    inverse,
                    qty_step,
                    c_mult,
                )
                entry_qty = max(entry_qty, min_entry_qty)
            return entry_qty, entry_price, "long_rentry"