-
Notifications
You must be signed in to change notification settings - Fork 89
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
PriceImprovement fee policy #2277
Conversation
max_volume_factor: _, | ||
quote: _, | ||
}) => { | ||
todo!() |
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.
How the quote should be used 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 think the cleanest solution would probably to adjust fee_from_surplus()
such that it computes the surplus compared to a given reference price. Then you could pass in the user signed limit prices for FeePolicy::Surplus
or the quoted amounts for FeePolicy::PriceImprovement
.
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 me know if I got it wrong 4a0e5ff
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.
Yes, this is exactly what I had in mind. I would just call the new arguments sth like reference_(buy|sell)_amount
and add a doc comment explaining the meaning of the reference amounts.
max_volume_factor: _, | ||
quote: _, | ||
}) => { | ||
todo!() |
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 think the cleanest solution would probably to adjust fee_from_surplus()
such that it computes the surplus compared to a given reference price. Then you could pass in the user signed limit prices for FeePolicy::Surplus
or the quoted amounts for FeePolicy::PriceImprovement
.
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.
Good first step!
Note, that there is an ongoing discussion whether it should be called PriceImprovement or QuoteDeviation (https://cowservices.slack.com/archives/C05N1FNP3MX/p1704971316558629)
PriceImprovement { | ||
factor: f64, | ||
max_volume_factor: f64, | ||
quote: Quote, |
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 really like that the quote becomes part of the fee policy enum. This makes it very clear how to use it.
Co-authored-by: Felix Leupold <[email protected]>
Co-authored-by: Martin Beckmann <[email protected]>
} | ||
}) => self.calculate_fee( | ||
self.order().sell.amount.0, | ||
self.order().buy.amount.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.
I am not sure this works for scaling partially fillable sell orders. Will need to go over it once more tomorrow, with a fresh mind.
# Conflicts: # crates/autopilot/src/domain/fee/mod.rs
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 think it would actually be great if we could get driver based integration tests running before adding more fee policies.
@@ -90,3 +95,48 @@ pub enum Policy { | |||
factor: f64, | |||
}, | |||
} | |||
|
|||
#[derive(Debug)] | |||
pub enum PolicyRaw { |
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'm a bit surprised by this type. I don't find the word "raw" very descriptive nor appealing and it's missing documentation for why it exists (on top of FeePolicy
). It looks like the only difference is the quote (which in only part of the other struct).
Is there any way we can get around defining two almost identical domain types or can we differentiate better between the two?
Maybe PolicyRaw is more like an incomplete Policy (maybe a PolicyBuilder), that can be converted into a full policy .with(quote)
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.
Yeah, totally makes sense. Renamed both the struct and the function.
} | ||
|
||
impl PolicyRaw { | ||
pub fn to_domain(&self, quote: &domain::Quote) -> Policy { |
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.
isn't PolicyRaw already a domain object?
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 protocol_fees = self.protocol_fee.get(&order, quote); | ||
Some(boundary::order::to_domain(order, protocol_fees)) |
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 think it would read slightly nicer if ProtocolFee
would return the domain order type.
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.
Fixed
quote.sell_amount, | ||
quote.buy_amount, |
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 think here we need to use whatever is better (quote or limit price)
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.
database/README.md
Outdated
sell_amount | numeric | | quote's sell amount | ||
buy_amount | numeric | | quote's buy amount |
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.
Don't we already store this information in order_quotes? Do we want to duplicate 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 think these will be different values defining user
price exchange rate, compared to order_quotes
where the amm
price exchange rate is saved.
The user
price exchange rate takes fee into account.
Here I wrote about an example.
I think we are somewhat close to finishing this PR (at least roughly we know what needs to be done). However, it's hard to review it with high confidence that it's correct and that it doesn't break the existing functionality (since it tackles most of the tasks from #2287). Do you think it makes sense to split this PR into multiple PRs and try to write tests for each of them? |
let sell_amount = quote.sell_amount.max(self.order().sell.amount.0); | ||
let buy_amount = quote.buy_amount.min(self.order().buy.amount.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.
Isn't this turned around? We want to take what's better for the trader between quote and limit (where I have to sell less and where I get to buy more)? I really think we should do a test case to cover this.
fee_policy_skip_market_orders: bool, | ||
} | ||
|
||
impl ProtocolFee { | ||
pub fn new(policy: Policy, fee_policy_skip_market_orders: bool) -> Self { | ||
pub fn new(policy: PolicyBuilder, fee_policy_skip_market_orders: bool) -> Self { |
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.
Sorry for being flip floppy here, but now that I look at it isn't this more like a config object (without any need for logic on it)? This way we could leave all logic inside the ProtocolFee
component?
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 merge the changes from main
branch, so we can make sure the quote_fee_amount
is included in the Quote
we send to the driver (it should be added to the quote_sell_amount
)?
# Conflicts: # crates/autopilot/src/domain/fee/mod.rs # crates/autopilot/src/solvable_orders.rs
CLA Assistant Lite bot: I have read the CLA Document and I hereby sign the CLA 1 out of 2 committers have signed the CLA. |
This pull request has been marked as stale because it has been inactive a while. Please update this pull request or it will be automatically closed. |
# Conflicts: # crates/autopilot/src/domain/fee/mod.rs
Reminder: Please update the DB Readme. Caused by: |
Splitting the PR into parts to properly follow #2287 |
Description
Partly closes #2287
How to test
TBD