Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

post_processing: add token_k_value and TVL to p_df #45

Open
AngelaKTE opened this issue Feb 1, 2021 · 19 comments
Open

post_processing: add token_k_value and TVL to p_df #45

AngelaKTE opened this issue Feb 1, 2021 · 19 comments
Assignees
Labels
viz all issues refering to data visualization & results

Comments

@AngelaKTE
Copy link
Contributor

  • various plots need token_k_value/TVL over time
  • add column providing token_k_value = token_k_balance * token_k_price
  • add column providing TVL = sum of all token_k_value
@AngelaKTE AngelaKTE added the viz all issues refering to data visualization & results label Feb 1, 2021
@AngelaKTE AngelaKTE self-assigned this Feb 1, 2021
AngelaKTE added a commit that referenced this issue Feb 2, 2021
- added token_k_value
- added TVL
- should automatically pull list of tokens from pool to be simulated
@AngelaKTE AngelaKTE mentioned this issue Feb 2, 2021
@AngelaKTE
Copy link
Contributor Author

  • add column "total_token_balances" = sum of all token_k_balances (=Pool Size)
  • calculate "token_a_balance" + "token_b_balance" + "token_c_balance" + ...

@AngelaKTE
Copy link
Contributor Author

  • all columns added to one big dataframe "p_df"

Ramarti added a commit that referenced this issue Feb 19, 2021
post_processing(): rewrite and added new columns as requested in #45
@markusbkoch
Copy link

  • add column "total_token_balances" = sum of all token_k_balances (=Pool Size)

If I understand correctly, if you're looking for a metric of the "pool size" may I suggest the invariant instead?

image

The sum of token balances can be misleading. Even in the 80/20 ETH/DAI pool (0x8b6e6E), it is dominated by the DAI balance. That's why TVL and total_token_balance have a ~perfect correlation: total_token_balance ~= token_dai_balance = 20% * TVL.
image

See how using the invariant makes things more clear. Despite the TVL growing from under 60M to over 120M, the invariant only grew from ~184k to ~188k. Meaning the growth in TVL was dominated by the price increase of the underlying tokens (namely ETH in this case), with growth of the pool itself playing a lesser role.
image

@mzargham
Copy link

mzargham commented Mar 6, 2021

I agree with @markusbkoch. An additional note, the invariant view also makes it relatively easy to see the impact of add/remove liquidity events as different from the the steady growth in the "invariant"

side note, we use the term "invariant" as the price regulation in the bonding surface is derived from holding this function V invariant for swaps but in practice, the fees cause the value of V to increase for swaps. This is how the LPs make money over time. On the other hand the add and remove liquidity mechanisms explicitly increase and decrease V, while preserving price. Furthermore, the awesome balancer feature "asymmetric" liquidity add/remove is actually a composition of a swap and a liquidity add.

@markusbkoch markusbkoch mentioned this issue Mar 6, 2021
@markusbkoch
Copy link

I really like the last plot in the notebook when you swap total_token_balances for the invariant. It highlights Z's point about <steady growth during long periods without join/exits> vs. <abrupt change upon join/exits>
image

@AngelaKTE
Copy link
Contributor Author

  • add column "total_token_balances" = sum of all token_k_balances (=Pool Size)

If I understand correctly, if you're looking for a metric of the "pool size" may I suggest the invariant instead?

image

The sum of token balances can be misleading. Even in the 80/20 ETH/DAI pool (0x8b6e6E), it is dominated by the DAI balance. That's why TVL and total_token_balance have a ~perfect correlation: total_token_balance ~= token_dai_balance = 20% * TVL.
image

See how using the invariant makes things more clear. Despite the TVL growing from under 60M to over 120M, the invariant only grew from ~184k to ~188k. Meaning the growth in TVL was dominated by the price increase of the underlying tokens (namely ETH in this case), with growth of the pool itself playing a lesser role.
image

@markusbkoch
I have a question on the correct implementation of the Invariant here.

  • Invariant is the product of all (token_(symbol)balance **token(symbol)_weight)
  • however, we frequently find two versions of the weight value, and I'm uncertain which one to use (and implement) in the model
    a) the weight in percent: 80 WETH / 20 DAI in our case
    b) the weight as decimal: 0.8 WETH/ 0.2 DAI (which you obviously use for the plots)

Which one is correct, and why?

@markusbkoch
Copy link

markusbkoch commented Mar 8, 2021

The white paper defines it in terms of the normalized weights (such that the sum of all normalized weights is 1) - so 0.8 and 0.2 in that case.

As for the why, it's not explicitly stated in the white paper, but from eq 10 in this proof we see that Wn must be a number between 0 and 1 (since 0<Vn<V by definition).

@AngelaKTE
Copy link
Contributor Author

Update post-processing:

  • remove "total_token_balances" column and post-processing

  • add column "pool_size_V" = product of all (token_(symbol)balance **token(symbol)_weight) - see above

  • "pool_size_V" = product of all (token_(symbol)balance **token(symbol)_weight) - see above

@AngelaKTE
Copy link
Contributor Author

  • add column "total_token_balances" = sum of all token_k_balances (=Pool Size)

If I understand correctly, if you're looking for a metric of the "pool size" may I suggest the invariant instead?

image

The sum of token balances can be misleading. Even in the 80/20 ETH/DAI pool (0x8b6e6E), it is dominated by the DAI balance. That's why TVL and total_token_balance have a ~perfect correlation: total_token_balance ~= token_dai_balance = 20% * TVL.
image

See how using the invariant makes things more clear. Despite the TVL growing from under 60M to over 120M, the invariant only grew from ~184k to ~188k. Meaning the growth in TVL was dominated by the price increase of the underlying tokens (namely ETH in this case), with growth of the pool itself playing a lesser role.
image

What do you think about stating it as metric "Pool Size V"? @markusbkoch
Sure it's the Invariant, but since it changes due to most state updates, this term causes confusion.

@mzargham
Copy link

mzargham commented Mar 8, 2021

Sure it's the Invariant, but since it changes due to most state updates, this term causes confusion.

I agreed the term "invariant" causes confusion. I think this is a good opportunity to clarify it though. The practical reason why the function is called "invariant" is because the basic mechanism for swapping one token for another is derived from asserting $V(X^+) = V(X)$ where $X$ is the state space of the pool. However, the inclusion of the fees changes in a careful way changes this to a directionally controlled 'differential variant' $V(X^+)&gt; V(X)$ for all swaps. This is how the LPs make money. So to your point it is not "invariant" its actually a "variant". (further reading on invariants and variant here (https://www.cs.cmu.edu/~aplatzer/logic/diffinv.html#differential-invariant).

In my paper on using state space models to derive economic properties, i called $V(X)$ the 'value function' and likened it to a Lyapunov function. Lyapunov functions are advanced control theory math tools for deriving and proving equilibria. Furthermore, their standard form is continuous time, but it also has a version in discrete time.

The functions $V(X)$ we are using are "energy conservation" functions, which is part of the reason the term "invariant" is still a meaningful intuition. It is not that the energy cannot go up, actually it does go up, but that energy is captured from somewhere. It is absolutely critical that the $V(X)$ function never go up, UNLESS the energy it captures comes from somewhere, in this case it comes from applying the fee (which we can think of as a friction) on the swap mechanism. The frictionless swap preserves $V(X)$ but the swap with friction is a bit like charging up a ballon by rubbing it on a carpet. We've not violated the conservation of energy invariant, we've simply collected energy from outside.

When a liquidity provider adds liquidity they are explicitly "charging up" increasing $V(X)$ for a right to discharge it in the future, but thanks to ongoing collection of energy through the friction of fees, it becomes a viable long term investment, despite the fact that there may be impermanent loss due to the fluctuation in the relative prices of the tokens within the pool.

I hope this helps improve your understanding of both where the term invariant came from (derivation of the swap mechanism), and why we still use it (the energy conservation analogy).

@VasilySumanov
Copy link
Collaborator

@mzargham thank you for such a detailed description!
For me, the energy conservation analogy perfectly helps in-depth understanding of this term.

@AngelaKTE
Copy link
Contributor Author

Aha! This is a very good mental model (energy)! Given that, this irritation with the Invariant is most welcome.

Initially, we were looking for a better metric to express "liquidity" or "market cap", since these metrics are not well defined (sometimes refering to $USD value, sometimes a more general term for "size"),
and thus are not helpful to demonstrate the interconnectedness of balance, weights, and ratio.

The Invariant certainly is.
After reading your paper, I'd like to rethink the first part of "Understanding Balancer Pools" (the article) - to not only offer another metric but to put more emphasis on "provable system properties" and the engineering perspective.
Which is the whole purpose of this project. :)

@Ramarti
Copy link
Collaborator

Ramarti commented Mar 8, 2021

Hi @markusbkoch and @AngelaKTE

I added invariant calculation like this:

# Calculate Invariant column
    df['invariant'] = 1
    for s in symbols:
        df['invariant'] *= (df[f'token_{s}_balance'] ** df[f'token_{s}_weight'])

The results i get are...invariant. Am I missing something?

image

@markusbkoch
Copy link

The results i get are...invariant. Am I missing something?

It's just that the range of the primary y axis is too wide. See the plot in my comment above (but notice the invariant in that case is in the secondary y-axis). Before the recent massive drop in liquidity, the invariant was within the 180k-190k range.
image

If you want to go as far in the x axis (ie, after the drop), maybe try log scale in the primary y axis?

@Ramarti
Copy link
Collaborator

Ramarti commented Mar 9, 2021

The results i get are...invariant. Am I missing something?

It's just that the range of the primary y axis is too wide. See the plot in my comment above (but notice the invariant in that case is in the secondary y-axis). Before the recent massive drop in liquidity, the invariant was within the 180k-190k range.
image

If you want to go as far in the x axis (ie, after the drop), maybe try log scale in the primary y axis?

Right, fixed thank you!

@AngelaKTE
Copy link
Contributor Author

  • invariant implemented to V1.0 simulation output (post-processing)
  • total_token_balances removed from simulation output

@AngelaKTE AngelaKTE reopened this Mar 11, 2021
@AngelaKTE
Copy link
Contributor Author

Sure it's the Invariant, but since it changes due to most state updates, this term causes confusion.

I agreed the term "invariant" causes confusion. I think this is a good opportunity to clarify it though. The practical reason why the function is called "invariant" is because the basic mechanism for swapping one token for another is derived from asserting $V(X^+) = V(X)$ where $X$ is the state space of the pool. However, the inclusion of the fees changes in a careful way changes this to a directionally controlled 'differential variant' $V(X^+)&gt; V(X)$ for all swaps. This is how the LPs make money. So to your point it is not "invariant" its actually a "variant". (further reading on invariants and variant here (https://www.cs.cmu.edu/~aplatzer/logic/diffinv.html#differential-invariant).

In my paper on using state space models to derive economic properties, i called $V(X)$ the 'value function' and likened it to a Lyapunov function. Lyapunov functions are advanced control theory math tools for deriving and proving equilibria. Furthermore, their standard form is continuous time, but it also has a version in discrete time.

The functions $V(X)$ we are using are "energy conservation" functions, which is part of the reason the term "invariant" is still a meaningful intuition. It is not that the energy cannot go up, actually it does go up, but that energy is captured from somewhere. It is absolutely critical that the $V(X)$ function never go up, UNLESS the energy it captures comes from somewhere, in this case it comes from applying the fee (which we can think of as a friction) on the swap mechanism. The frictionless swap preserves $V(X)$ but the swap with friction is a bit like charging up a ballon by rubbing it on a carpet. We've not violated the conservation of energy invariant, we've simply collected energy from outside.

When a liquidity provider adds liquidity they are explicitly "charging up" increasing $V(X)$ for a right to discharge it in the future, but thanks to ongoing collection of energy through the friction of fees, it becomes a viable long term investment, despite the fact that there may be impermanent loss due to the fluctuation in the relative prices of the tokens within the pool.

I hope this helps improve your understanding of both where the term invariant came from (derivation of the swap mechanism), and why we still use it (the energy conservation analogy).

@mzargham I wonder how weights changes fit in here, since it violates energy conservation? Depending on the current value distribution, a change of weights (without adapting balances) will either destroy energy (black hole?) - or more energy is available, like in nuclear fission.
Either way since it changes the "energy" distribution, it's a major disruption. How would you put it into words?

@VasilySumanov
Copy link
Collaborator

@AngelaKTE I think dynamic weights changing in the live pool does not violate energy conservation but re-distributes energy between pool components. Let's imagine AMM that has an external controller that changes weights trying to minimize arbitrage gap -> 0 (tracking prices on external markets "ideally" and de-facto changing weights according to these changes).

So, basically invariant wouldn't be changed, but weights of components will.

@AngelaKTE
Copy link
Contributor Author

I've created a tiny series of weights and the impact on Invariant V, please take a look at how Invariant V changes.
https://github.com/TokenEngineeringCommunity/BalancerPools_Model/blob/NBupdate/WeightsChanges.ipynb

However, I get your point, I think it's just not redistributing energy within the pool, rather charging up/off according to external signals.

I've added all our fresh insights to this article, feel free to comment @everyone:
https://docs.google.com/document/d/1M5EpOhmO91nI00LCvzyNBa4I1EKm-0ztq8g_-r6W7wM/edit?usp=sharing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
viz all issues refering to data visualization & results
Projects
None yet
Development

No branches or pull requests

6 participants