Пример #1
0
def s_join_swap_pool_amount_out(params, step, history, current_state,
                                input_params: JoinSwapPoolAmountOutInput,
                                output_params: JoinSwapPoolAmountOutOutput):
    pool = current_state['pool'].copy()
    max_token_in_amount = input_params.max_token_in.symbol
    tokens_in_symbol = input_params.max_token_in.symbol
    pool_amount_out = input_params.pool_amount_out
    swap_fee = pool['swap_fee']

    total_weight = calculate_total_denorm_weight(pool)

    join_swap = BalancerMath.calc_single_in_given_pool_out(
        token_balance_in=Decimal(pool['tokens'][tokens_in_symbol].balance),
        token_weight_in=Decimal(
            pool['tokens'][tokens_in_symbol].denorm_weight),
        pool_supply=Decimal(pool['pool_shares']),
        total_weight=total_weight,
        pool_amount_out=pool_amount_out,
        swap_fee=Decimal(swap_fee))

    _, pool = s_pool_update_fee(pool, {tokens_in_symbol: join_swap.fee})

    token_in_amount = join_swap.result
    if token_in_amount > max_token_in_amount and VERBOSE:
        print(
            "WARNING: calculated that user should get {} pool shares but input specified that he should get {} pool shares instead."
            .format(pool_amount_out, max_token_in_amount))

    pool['pool_shares'] = Decimal(pool['pool_shares']) + pool_amount_out
    pool['tokens'][tokens_in_symbol].balance += token_in_amount

    return pool
Пример #2
0
def s_swap_exact_amount_in(params, step, history, current_state,
                           input_params: SwapExactAmountInInput,
                           output_params: SwapExactAmountInOutput) -> dict:
    pool = current_state['pool'].copy()
    # Parse action params
    token_in_symbol = input_params.token_in.symbol
    token_amount_in = input_params.token_in.amount
    token_out = input_params.min_token_out.symbol
    pool_token_in = pool['tokens'][token_in_symbol]
    swap_fee = pool['swap_fee']

    if not pool_token_in.bound:
        raise Exception('ERR_NOT_BOUND')
    out_record = pool['tokens'][token_out]
    if not out_record.bound:
        raise Exception('ERR_NOT_BOUND')

    if token_amount_in > Decimal(pool_token_in.balance) * MAX_IN_RATIO:
        raise Exception("ERR_MAX_IN_RATIO")

    swap_result = BalancerMath.calc_out_given_in(
        token_balance_in=pool_token_in.balance,
        token_weight_in=Decimal(pool_token_in.denorm_weight),
        token_balance_out=out_record.balance,
        token_weight_out=Decimal(out_record.denorm_weight),
        token_amount_in=token_amount_in,
        swap_fee=Decimal(swap_fee))

    _, pool = s_pool_update_fee(pool, {token_in_symbol: swap_result.fee})
    pool_in_balance = pool_token_in.balance + token_amount_in
    pool_token_in.balance = pool_in_balance
    pool_out_balance = out_record.balance - swap_result.result
    out_record.balance = pool_out_balance
    return pool
    def test_calc_spot_price_50_50_no_fee(self):
        w_50_50_no_fee_1 = {
            'tb_i': Decimal('10'),
            'tw_i': Decimal('20'),
            'tb_o': Decimal('5'),
            'tw_o': Decimal('20'),
            'fee': Decimal('0'),
            'price': Decimal('2')
        }
        price = BalancerMath.calc_spot_price(token_balance_in=w_50_50_no_fee_1['tb_i'], token_weight_in=w_50_50_no_fee_1['tw_i'],
                                             token_balance_out=w_50_50_no_fee_1['tb_o'], token_weight_out=w_50_50_no_fee_1['tw_o'],
                                             swap_fee=w_50_50_no_fee_1['fee'])

        self.assertEqual(price, w_50_50_no_fee_1['price'])
    def test_calc_spot_price_lbp_sim(self):
        # https://docs.google.com/spreadsheets/d/1t6VsMJF8lh4xuH_rfPNdT5DM3nY4orF9KFOj2HdMmuY/edit#gid=1392289526
        params = {
            'tb_i': Decimal('1333333'),
            'tw_i': Decimal('4'),
            'tb_o': Decimal('7500000'),
            'tw_o': Decimal('36'),
            'fee': Decimal('0.0001'),
            'price': Decimal('1.6')
        }
        price = BalancerMath.calc_spot_price(token_balance_in=params['tb_i'], token_weight_in=params['tw_i'],
                                             token_balance_out=params['tb_o'], token_weight_out=params['tw_o'], swap_fee=params['fee'])

        self.assertAlmostEqual(price, params['price'], 3)
Пример #5
0
def s_exit_swap_extern_amount_out(
        params, step, history, current_state,
        input_params: ExitSwapPoolExternAmountOutInput,
        output_params: ExitSwapPoolExternAmountOutOutput) -> dict:
    """
    Exit a pool by withdrawing liquidity for a single token_symbol.
    """
    pool = current_state['pool'].copy()
    swap_fee = pool['swap_fee']
    token_out_symbol = input_params.token_out.symbol
    # Check that all tokens_out are bound
    if not pool['tokens'][token_out_symbol].bound:
        raise Exception("ERR_NOT_BOUND")
    # Check that user is not trying to withdraw too many tokens
    token_amount_out = input_params.token_out.amount
    if token_amount_out > Decimal(
            pool['tokens'][token_out_symbol].balance) * MAX_OUT_RATIO:
        raise Exception("ERR_MAX_OUT_RATIO")

    total_weight = calculate_total_denorm_weight(pool)

    exit_swap = BalancerMath.calc_pool_in_given_single_out(
        token_balance_out=Decimal(pool['tokens'][token_out_symbol].balance),
        token_weight_out=Decimal(
            pool['tokens'][token_out_symbol].denorm_weight),
        pool_supply=Decimal(pool['pool_shares']),
        total_weight=Decimal(total_weight),
        token_amount_out=token_amount_out,
        swap_fee=Decimal(swap_fee))
    pool_amount_in = exit_swap.result

    _, pool = s_pool_update_fee(pool, {token_out_symbol: exit_swap.fee})

    if pool_amount_in == 0:
        raise Exception("ERR_MATH_APPROX")
    if pool_amount_in != output_params.pool_amount_in and VERBOSE:
        print(
            "WARNING: calculated that pool should get {} pool shares but input specified that pool should get {} pool shares instead"
            .format(pool_amount_in, output_params.pool_amount_in))

    # Decrease token_symbol (give it to user)
    pool['tokens'][token_out_symbol].balance -= token_amount_out
    # Burn the user's incoming pool shares - exit fee
    exit_fee = pool_amount_in * EXIT_FEE
    pool['pool_shares'] = Decimal(
        pool['pool_shares']) - pool_amount_in - exit_fee

    return pool
 def test_calc_out_given_in_fee(self):
     params = {
         'ta_i': Decimal('1'),
         'tb_i': Decimal('10'),
         'tw_i': Decimal('10'),
         'tb_o': Decimal('100'),
         'tw_o': Decimal('30'),
         'fee': Decimal('0.1'),
         'ta_o': Decimal('2.8317232565404336')
     }
     token_amount_out = BalancerMath.calc_out_given_in(token_amount_in=params['ta_i'], token_weight_in=params['tw_i'],
                                                       token_balance_in=params['tb_i'], token_weight_out=params['tw_o'],
                                                       token_balance_out=params['tb_o'],
                                                       swap_fee=params['fee'])
     self.assertAlmostEqual(token_amount_out.fee, Decimal('0.1'))
     self.assertAlmostEqual(token_amount_out.result, params['ta_o'], 7)
 def test_calc_out_given_in_no_fee(self):
     params = {
         'ta_i': Decimal('1'),
         'tb_i': Decimal('10'),
         'tw_i': Decimal('20'),
         'tb_o': Decimal('100'),
         'tw_o': Decimal('20'),
         'fee': Decimal('0'),
         'ta_o': Decimal('9.0909090909090909')
     }
     token_amount_out = BalancerMath.calc_out_given_in(token_amount_in=params['ta_i'], token_weight_in=params['tw_i'],
                                                       token_balance_in=params['tb_i'], token_weight_out=params['tw_o'],
                                                       token_balance_out=params['tb_o'],
                                                       swap_fee=params['fee'])
     self.assertAlmostEqual(token_amount_out.fee, Decimal('0'), 3)
     self.assertAlmostEqual(token_amount_out.result, params['ta_o'], 3)
    def test_calc_in_given_out(self):
        params = {
            'ta_o': Decimal('1'),
            'tb_i': Decimal('10'),
            'tw_i': Decimal('10'),
            'tb_o': Decimal('100'),
            'tw_o': Decimal('30'),
            'fee': Decimal('0.1'),
            'ta_i': Decimal('0.340112801426272844')
        }
        token_amount_in = BalancerMath.calc_in_given_out(token_amount_out=params['ta_o'], token_weight_in=params['tw_i'],
                                                         token_balance_in=params['tb_i'], token_weight_out=params['tw_o'],
                                                         token_balance_out=params['tb_o'],
                                                         swap_fee=params['fee'])

        self.assertAlmostEqual(token_amount_in.fee, Decimal('0.0340112801426272840754356244'), 7)
        self.assertAlmostEqual(token_amount_in.result, params['ta_i'], 7)
 def test_calc_pool_out_given_single_in(self):
     params = {
         'tb_i': Decimal('471000'),
         'tw_i': Decimal('36'),
         't_w': Decimal('40'),
         'p_s': Decimal('100'),
         'pa_o': Decimal('0.0019106349146009'),
         'ta_i': Decimal('10'),
         'fee': Decimal('0.001')
     }
     pool_amount_out = BalancerMath.calc_pool_out_given_single_in(token_balance_in=params['tb_i'],
                                                                  token_weight_in=params['tw_i'],
                                                                  pool_supply=params['p_s'],
                                                                  total_weight=params['t_w'],
                                                                  token_amount_in=params['ta_i'],
                                                                  swap_fee=params['fee'])
     self.assertAlmostEqual(pool_amount_out.fee, Decimal('0.001'), 7)
     self.assertAlmostEqual(pool_amount_out.result, params['pa_o'], 7)
 def test_calc_single_in_given_pool_out(self):
     params = {
         'tb_i': Decimal('471000'),
         'tw_i': Decimal('36'),
         'p_s': Decimal('100'),
         't_w': Decimal('40'),
         'pa_o': Decimal('10'),
         'ta_i': Decimal('52621.106362779467365737'),
         'fee': Decimal('0.001')
     }
     token_amount_in = BalancerMath.calc_single_in_given_pool_out(token_balance_in=params['tb_i'],
                                                                  token_weight_in=params['tw_i'],
                                                                  pool_supply=params['p_s'],
                                                                  total_weight=params['t_w'],
                                                                  pool_amount_out=params['pa_o'],
                                                                  swap_fee=params['fee'])
     self.assertAlmostEqual(token_amount_in.fee, Decimal('5.26211063623975586820477'), 7)
     self.assertAlmostEqual(token_amount_in.result, params['ta_i'], 5)
def generate_initial_state(initial_values_json: str, spot_price_base_currency: str) -> typing.Dict:
    with open(initial_values_json, "r") as f:
        initial_values = json.load(f, object_hook=token_finding_hook)
    # Figure out the tokens that are NOT the spot_price_base_currency
    other_tokens = [*initial_values['pool']['tokens'].keys()]
    other_tokens.remove(spot_price_base_currency)

    spot_prices = {}
    for t in other_tokens:
        base_token = initial_values['pool']['tokens'][spot_price_base_currency]
        other_token = initial_values['pool']['tokens'][t]

        spot_prices[t] = BalancerMath.calc_spot_price(token_balance_in=base_token.balance,
                                                      token_weight_in=Decimal(base_token.denorm_weight),
                                                      token_balance_out=other_token.balance,
                                                      token_weight_out=Decimal(other_token.denorm_weight),
                                                      swap_fee=Decimal(initial_values['pool']['swap_fee']))
    initial_values["spot_prices"] = spot_prices
    return initial_values
Пример #12
0
def calculate_spot_prices(pool: dict, ref_token: str):
    swap_fee = pool['swap_fee']
    balance_in = pool['tokens'][ref_token].balance
    weight_in = pool['tokens'][ref_token].weight
    spot_prices = {}
    for token in pool['tokens']:
        if token == ref_token:
            continue
        balance_out = pool['tokens'][token].balance
        weight_out = pool['tokens'][token].weight

        price = BalancerMath.calc_spot_price(
            token_balance_in=Decimal(balance_in),
            token_weight_in=Decimal(weight_in),
            token_balance_out=Decimal(balance_out),
            token_weight_out=Decimal(weight_out),
            swap_fee=Decimal(swap_fee))
        spot_prices[token] = price
    return spot_prices
    def test_calc_single_out_given_pool_in(self):
        params = {
            'tb_o': Decimal('471000'),
            'tw_o': Decimal('36'),
            'p_s': Decimal('100'),
            't_w': Decimal('40'),
            'pa_i': Decimal('10'),
            'ta_o': Decimal('52028.342757248973119087'),
            'fee': Decimal('0.001')
        }
        token_amount_out = BalancerMath.calc_single_out_given_pool_in(token_balance_out=params['tb_o'],
                                                                      token_weight_out=params['tw_o'],
                                                                      pool_supply=params['p_s'],
                                                                      total_weight=params['t_w'],
                                                                      pool_amount_in=params['pa_i'],
                                                                      swap_fee=params['fee'])

        self.assertAlmostEqual(token_amount_out.fee, Decimal('5.20335461122343328240886'), 7)
        self.assertAlmostEqual(token_amount_out.result, params['ta_o'], 6)
Пример #14
0
def s_swap_exact_amount_out(params, step, history, current_state,
                            input_params: SwapExactAmountOutInput,
                            output_params: SwapExactAmountOutOutput) -> dict:
    pool = current_state['pool'].copy()
    # Parse action params
    token_in_symbol = input_params.max_token_in.symbol
    token_amount_out = input_params.token_out.amount
    token_out_symbol = input_params.token_out.symbol
    pool_token_out = pool['tokens'][token_out_symbol]
    pool_token_in = pool['tokens'][token_in_symbol]
    swap_fee = pool['swap_fee']

    if not pool_token_out.bound:
        raise Exception('ERR_NOT_BOUND')
    if not pool_token_in.bound:
        raise Exception('ERR_NOT_BOUND')
    if token_amount_out > (pool_token_out.balance * MAX_OUT_RATIO):
        raise Exception("ERR_MAX_OUT_RATIO")

    swap_result = BalancerMath.calc_in_given_out(
        token_balance_in=Decimal(pool_token_in.balance),
        token_weight_in=Decimal(pool_token_in.denorm_weight),
        token_balance_out=Decimal(pool_token_out.balance),
        token_weight_out=Decimal(pool_token_out.denorm_weight),
        token_amount_out=token_amount_out,
        swap_fee=Decimal(swap_fee))
    token_amount_in = swap_result.result
    if token_amount_in > input_params.max_token_in.amount and VERBOSE:
        # raise Exception('ERR_LIMIT_IN')
        print(
            f"WARNING: token_amount_in {token_amount_in} > max {input_params.max_token_in.amount}"
        )

    _, pool = s_pool_update_fee(pool, {token_in_symbol: swap_result.fee})

    pool_token_in.balance = pool_token_in.balance + token_amount_in
    pool_token_out.balance = pool_token_out.balance - token_amount_out

    return pool
Пример #15
0
def s_exit_swap_pool_amount_in(
        params, step, history, current_state,
        input_params: ExitSwapPoolAmountInInput,
        output_params: ExitSwapPoolAmountInOutput) -> dict:
    pool = current_state['pool'].copy()
    swap_fee = pool['swap_fee']
    pool_token_out = pool['tokens'][output_params.token_out.symbol]
    if not pool_token_out.bound:
        raise Exception("ERR_NOT_BOUND")
    pool_amount_in = input_params.pool_amount_in
    total_weight = calculate_total_denorm_weight(pool)

    exit_swap = BalancerMath.calc_single_out_given_pool_in(
        token_balance_out=Decimal(pool_token_out.balance),
        token_weight_out=Decimal(pool_token_out.denorm_weight),
        pool_supply=Decimal(pool['pool_shares']),
        total_weight=Decimal(total_weight),
        pool_amount_in=pool_amount_in,
        swap_fee=Decimal(swap_fee))

    token_amount_out = exit_swap.result
    if token_amount_out > pool_token_out.balance * MAX_OUT_RATIO:
        raise Exception("ERR_MAX_OUT_RATIO")

    generated_fees = pool['generated_fees']
    generated_fees[output_params.token_out.symbol] = Decimal(
        generated_fees[output_params.token_out.symbol]) + exit_swap.fee

    pool['tokens'][output_params.token_out.symbol].balance -= token_amount_out

    # Burn the user's incoming pool shares - exit fee
    exit_fee = pool_amount_in * EXIT_FEE
    pool['pool_shares'] = Decimal(
        pool['pool_shares']) - pool_amount_in - exit_fee

    return pool
Пример #16
0
def s_join_swap_extern_amount_in(
        params, step, history, current_state,
        input_params: JoinSwapExternAmountInInput,
        output_params: JoinSwapExternAmountInOutput) -> dict:
    """
    Join a pool by providing liquidity for a single token_symbol.
    """
    pool = current_state['pool'].copy()
    tokens_in_symbol = input_params.token_in.symbol
    token_in_amount = input_params.token_in.amount
    pool_amount_out_expected = output_params.pool_amount_out
    swap_fee = pool['swap_fee']

    total_weight = calculate_total_denorm_weight(pool)

    join_swap = BalancerMath.calc_pool_out_given_single_in(
        token_balance_in=Decimal(pool['tokens'][tokens_in_symbol].balance),
        token_weight_in=Decimal(
            pool['tokens'][tokens_in_symbol].denorm_weight),
        pool_supply=Decimal(pool['pool_shares']),
        total_weight=total_weight,
        token_amount_in=token_in_amount,
        swap_fee=Decimal(swap_fee))

    _, pool = s_pool_update_fee(pool, {tokens_in_symbol: join_swap.fee})

    pool_amount_out = join_swap.result
    if pool_amount_out != pool_amount_out_expected and VERBOSE:
        print(
            "WARNING: calculated that user should get {} pool shares but input specified that he should get {} pool shares instead."
            .format(pool_amount_out, pool_amount_out_expected))

    pool['pool_shares'] = Decimal(pool['pool_shares']) + pool_amount_out
    pool['tokens'][tokens_in_symbol].balance += token_in_amount

    return pool