-
Notifications
You must be signed in to change notification settings - Fork 0
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
Test comparable to combinatorial auction filtering #80
Conversation
I significantly changed the code to really run a simple combinatorial auction. This gives slightly different information than previously: Before I logged which orders would have provided more surplus on token pairs and would have resulted in filtering the top solution. Now, I log who would have won the combinatorial auction and how much more surplus would have been provided. Both information is useful so I might add the old stuff back. I want to find a cleaner way to do that though. Since the old information is close to some other competition surplus test I went for the code as in the PR. |
- aggregate orders on token pairs - compare winning solution to all solutions with just one order
- computes winners using combinatorial auction - change in winner implies top solution was filtered out - logs change in surplus - removes old test of just comparing the winner to other solutions
- add more debugging info - show which solutions are filtered and why - only use objective instead of surplus for single token pair solutions - make naming consistent: `aggregated_solutions` -> `aggregate_solutions` - add more test cases
e389306
to
b10c702
Compare
|
||
|
||
class CombinatorialAuctionSurplusTest(BaseTest): | ||
"""Test how a combinatorial auctions would have settled the auction. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plural (auctions) not needed in the comment
- Aggregate surplus on the different directed sell token-buy token pairs for all solutions in | ||
the competition. | ||
- Compute a baseline for surplus on all token pairs from those solutions. | ||
- Filter solutions which to not provide at least as much surplus as the baseline on all token |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "to not" -> do not.
Also, phrase "on all token pairs" could be read as follows: a solver should deal with all token pairs and provide the most surplus in all of them. Maybe add "on all token pairs that the solution touches" ?
""" | ||
|
||
solutions = competition_data["solutions"] | ||
solution = competition_data["solutions"][-1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe rename to winning_solution
?
It would also help to not confuse things with the for-loop variable in line 60
int(prices[token_pair[0]]), | ||
10**36, | ||
) | ||
elif trade.get_surplus_token() == trade.data.buy_token: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it possible there is a third case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. Should I rewrite as else
instead of elif
? Or add some error message in case both checks fail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrote this as if "is sell order": ... else:
) | ||
for solution in solutions | ||
] | ||
aggregate_solution = aggregate_solutions[-1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, a renaming of the variable would help.
surplus_dict[token_pair] = min( | ||
surplus_dict[token_pair], solution["objective"]["total"] | ||
) | ||
# surplus_dict[token_pair] = solution["objective"]["total"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's remove this comment
result: dict[tuple[str, str], tuple[Fraction, int]] = {} | ||
for i, aggregate_solution in enumerate(aggregate_solutions): | ||
if len(aggregate_solution) == 1: | ||
token_pair, surplus = list(aggregate_solution.items())[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the next line are not the easiest to read but they make sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some comments to make it easier to understand. Still a bit messy since I am using (surplus, index)
tuples.
A simpler design would be nice.
) -> list[list[int]]: | ||
"""Filter out solutions which do not provide enough surplus. | ||
Only solutions are considered for ranking that supply more surplus than any of the single | ||
aggregate order solutions. The function returns a list of bools where False means the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment about what the function returns is not accurate.
Also, maybe we could make what the function returns easier to understand?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed the comment and added some rational for making it this complicated.
A simpler design would be nice though.
"Combinatorial auction surplus test:", | ||
f"Tx Hash: {competition_data['transactionHash']}", | ||
f"Winning Solver: {solution['solver']}", | ||
f"Winning surplus: {aggregate_solution}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The surplus is a fraction here and so the printing is not easy to read. Would be good to convert this to a decimal in ETH.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I convert this to float now. It looks extremely ugly though. I am a fan of using Fraction
in the actual computation though. (I already made a big concession by using ETH and not wei as unit 😜)
Tested locally and seems to be working. Will do one more pass to double-check everything but it looks good! Added a few minor comments here and there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some minor comments that would be good to be addressed.
- fixed comments - renamed variables - added comments - simplified buy and sell order cases - simplified some default value dict access
just experimental since it looks a bit ugly
also removed unnecessary pylint disable
def run(self, tx_hash: str) -> bool: | ||
""" | ||
Wrapper function for the whole test. Checks if solver competition data is retrievable | ||
and runs EBBO test, else returns True to add to list of unchecked hashes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Runs EBBO test..
Maybe fix this.
else returns True...
is this a typo or is this the convention here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed it. The same error is present in some other test. Will fix that later.
|
||
# convert surplus to float for logging | ||
winning_aggregate_surplus_float = { | ||
token_pair: float(surplus) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we maybe reduce the number of decimals to 4? I guess we are not doing it in other tests but it would make things more readable.
Something like round(float_variable,4)
should do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a more general function to process those dicts before logging.
Looks good! Added some minor comments, and I guess adding the test in the |
info logs remain the same for a better overview
result[solver][token_pair] = aggregate_solutions[solution_index][token_pair] | ||
return result | ||
|
||
def convert_fractions_to_floats(self, obj: Any, precision: int = 4) -> Any: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Things look good. Let's merge and observe! Can you create a new release btw once this is merged as there 2-3 PRs merged already so a release makes sense. |
We are thinking about implementing combinatorial auctions. This would include filtering out solutions which do not provide more surplus on individual sell token-buy token pairs compared to solutions only including that token pair.
The test in this PR checks if the winning solution would have been filtered out based on this criterion.
One difference to the competition surplus test is that the test in this PR checks token pairs and not orders.
Potentially we want to check more in this test. E.g.
Todo