kaizen-ai / kaizenflow

KaizenFlow is a framework for Bayesian reasoning and AI/ML stream computing
GNU General Public License v3.0
111 stars 77 forks source link

Implement DaoSwap optimization problem #80

Closed tamriq closed 1 year ago

tamriq commented 1 year ago

From whitepaper:

The general problem of determining the token equilibrium price and the allocation among the swap participants can be formulated in terms of the inequalities on quantities and prices corresponding to the orders and on the need that the total quantity exchanged of each token is preserved across the swaps, i.e., the quantity bought for each token is equal to the sold quantity.

The general solution of the DaoSwap problem is a set of non-linear equation with combinatorial constraints, which is of course NP-complete. It can still be solved in an effective way with solvers like ...

gpsaggese commented 1 year ago

I can work on this with @PomazkinG when he has bandwidth

PomazkinG commented 1 year ago

@gpsaggese I could use some help here

What I don't quite get is what do we want to maximize / minimize?

Typically the pulp solver accepts:

Now let's come back to our toy example:

My understanding is that we need to match the orders below. In other words find q_base_asterisk_1 and q_base_asterisk_2 such that all constraints are satisfied. Maybe another detailed natural language description or a formula would help me.

# We use exchange_rate for the limit price constraint.
exchange_rate = p_base / p_quote = known const 
# Toy orders: holders want to buy / sell the same about of BTC.
o_1 = (action="buy", q_base=5, base_token="BTC", limit_price=4, quote_token="ETH")
o_2 = (action="sell", q_base=5, base_token="BTC", limit_price=5, quote_token="ETH")
# Constraints.
# TODO(Grisha): do we need a constraint saying that sum(q_base_asterisk * to_ineq(action))  = 0?
# i.e. the quantity of bought and sold token is equal? 
cond_1 = exchange_rate <= limit_price(o_1)
if cond:
   0 <= q_base_asterisk(o_1) <= q_base(o_1)
else:
   q_base_asterisk(o_1) = 0
#
cond_2 = exchange_rate => limit_price(o_2)
if cond:
   0 <= q_base_asterisk(o_2) <= q_base(o_2)
else:
   q_base_asterisk(o_2) = 0
gpsaggese commented 1 year ago

Good question. That part is not clear from the paper.

The maximization constraint can be 1) "maximize the volume exchanged"; or 2) "maximize the total welfare" (i.e., the sum of the differences between what people are paying for and their reservation price) 3) something else

I would pick the constraint that it's easier to specify and helps convergence -- so maybe 1)

gpsaggese commented 1 year ago

Also yes you need to impose a constraint saying that "the ETH tokens bought are == to the tokens ETH sold".

The maximization constraint is needed otherwise a valid solution is always "nothing gets exchanged".

I think both DaoSwap (where the prices need to be determined) and DaoCross benefit from the maximization constraint.

Another problem is once we have prices how you determine how to match buyers and sellers? We can either do another optimization (like "bin-packing") or the simple priority queue approach might be enough to compute the matches, with some extensions for the more complicated cases of more tokens.

PomazkinG commented 1 year ago

After https://github.com/sorrentum/sorrentum/pull/94 is merged the plan is:

gpsaggese commented 1 year ago

Good plan.

Of course let's do baby steps: PR1: N orders with one base token first PR2: N orders with base / quote token (e.g., buy ETH vs BTC, sell ETH, buy BTC vs ETH, sell BTC) PR3: N orders with N tokens mixing everything

PomazkinG commented 1 year ago

As a workaround I install the pulp package manually in a tmp docker container to run the tests but later we should consider adding it (or another package) to a docker image (amp / defi)

PomazkinG commented 1 year ago

Extended for N tokens (only the 2 token case is tested for now) in https://github.com/sorrentum/sorrentum/pull/108

The next steps are:

Current progress and the plans are reflected in https://docs.google.com/document/d/1Kxu6gfUTtfLKaw2O_SBn_iBfpORhlRFMB4uJ4RpA4Hs/edit#heading=h.hnjzvh3d7tw8

gpsaggese commented 1 year ago

Fantastic job and perfect organization. You guys are coding machines.

PomazkinG commented 1 year ago

Question to @gpsaggese and/or @gitpaulsmith:

When solving the DaoCross optimization problem: I am trying to maximize the volume exchanged.

Where the volume is: sum(clearing_price_base_token * executed_quantity_base_token) for each order

e.g,:

The total exchanged volume is 32 = 8 2 (buy order) + 8 2 (sell order). Is it correct? It seems to me that I count the quantity of BTC twice, while the answer should be 16.

gpsaggese commented 1 year ago

We'll add a precise formula in the white paper, but you can double count things if it's simple, since maximizing is invariant by multiplying by a positive constant.

Not sure if we should use the $price quantity$ to maximize notional transacted or something like $max \sum_i q^(o_i)$ over the orders, where q^*(o_i) is the actual quantity exchanged for each order. The equation balancing between sell and buy will take care of making sure that the exchanged quantities are valid. Maybe we need to sum by different tokens accounting for the direction of buying and selling.

We can also try different approaches for the implementation to inform the theoretical part...

We'll think about it in any case.

DanilYachmenev commented 1 year ago

Seems to be implemented at defi/dao_cross/optimize.py Should we close?

gitpaulsmith commented 1 year ago

Done.