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
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
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
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"