-
Notifications
You must be signed in to change notification settings - Fork 97
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
Feat: Add minAverageSellPrice for LO #736
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
1d1c83a
add minAverageSellPrice
jcompagni10 4cf7dd3
comments + fmt
jcompagni10 744bfc8
Merge remote-tracking branch 'origin/main' into feat/lo_slop_tolerance
jcompagni10 0abd365
Add param to SimulatePlaceLimitOrder
jcompagni10 9e6a99b
fix merge
jcompagni10 1848d68
fix tests
jcompagni10 f289c3e
fix: better test naming
jcompagni10 a5c3314
Merge remote-tracking branch 'origin/main' into feat/lo_slop_tolerance
jcompagni10 78730d7
fix proto version
jcompagni10 4fbfc01
Add additional test for MinAveragePrice > LimitSellPrice
jcompagni10 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -243,6 +243,57 @@ func (s *DexTestSuite) TestPlaceLimitOrderInsufficientFunds() { | |
s.assertAliceLimitSellFails(err, "TokenA", 0, 10) | ||
} | ||
|
||
func (s *DexTestSuite) TestPlaceLimitOrderGTCWithDustMinAvgPriceFails() { | ||
s.fundAliceBalances(1, 0) | ||
s.fundBobBalances(0, 1) | ||
// GIVEN LP liq at 148.37-148.42 (with dust) | ||
s.bobDeposits( | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_000, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_001, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_002, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(10), 50_003, 1), | ||
) | ||
// THEN alice GTC limitOrder minAvgPrice == limitPrice fails | ||
limitPrice := math_utils.MustNewPrecDecFromStr("0.006737") | ||
_, err := s.msgServer.PlaceLimitOrder(s.Ctx, &types.MsgPlaceLimitOrder{ | ||
Creator: s.alice.String(), | ||
Receiver: s.alice.String(), | ||
TokenIn: "TokenA", | ||
TokenOut: "TokenB", | ||
LimitSellPrice: &limitPrice, | ||
AmountIn: sdkmath.NewInt(2000), | ||
OrderType: types.LimitOrderType_GOOD_TIL_CANCELLED, | ||
MinAverageSellPrice: &limitPrice, | ||
}) | ||
s.ErrorIs(err, types.ErrLimitPriceNotSatisfied) | ||
} | ||
|
||
func (s *DexTestSuite) TestPlaceLimitOrderGTCWithDustMinAvgPrice() { | ||
s.fundAliceBalances(1, 0) | ||
s.fundBobBalances(0, 1) | ||
// GIVEN LP liq at 148.37-148.42 (with dust) | ||
s.bobDeposits( | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_000, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_001, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_002, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(10), 50_003, 1), | ||
) | ||
// THEN alice IoC limitOrder with lower min avg prices success | ||
limitPrice := math_utils.MustNewPrecDecFromStr("0.006737") | ||
minAvgPrice := math_utils.MustNewPrecDecFromStr("0.006728") | ||
_, err := s.msgServer.PlaceLimitOrder(s.Ctx, &types.MsgPlaceLimitOrder{ | ||
Creator: s.alice.String(), | ||
Receiver: s.alice.String(), | ||
TokenIn: "TokenA", | ||
TokenOut: "TokenB", | ||
LimitSellPrice: &limitPrice, | ||
AmountIn: sdkmath.NewInt(2000), | ||
OrderType: types.LimitOrderType_GOOD_TIL_CANCELLED, | ||
MinAverageSellPrice: &minAvgPrice, | ||
}) | ||
s.NoError(err) | ||
} | ||
|
||
func (s *DexTestSuite) TestLimitOrderPartialFillDepositCancel() { | ||
s.fundAliceBalances(100, 100) | ||
s.fundBobBalances(100, 100) | ||
|
@@ -303,6 +354,90 @@ func (s *DexTestSuite) TestPlaceLimitOrderWithDustHitsTruePriceLimit() { | |
s.assertAliceLimitSellFails(types.ErrLimitPriceNotSatisfied, "TokenA", 20005, 1, types.LimitOrderType_IMMEDIATE_OR_CANCEL) | ||
} | ||
|
||
func (s *DexTestSuite) TestPlaceLimitOrderIOCWithDustMinAvgPriceFails() { | ||
s.fundAliceBalances(1, 0) | ||
s.fundBobBalances(0, 1) | ||
// GIVEN LP liq at 148.37-148.42 (with dust) | ||
s.bobDeposits( | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_000, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_001, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_002, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(10), 50_003, 1), | ||
) | ||
// THEN alice IoC limitOrder minAvgPrice == limitPrice fails | ||
_, err := s.aliceLimitSellsWithMinAvgPrice( | ||
"TokenA", | ||
math_utils.MustNewPrecDecFromStr("0.006730"), | ||
1, | ||
math_utils.MustNewPrecDecFromStr("0.006730"), | ||
types.LimitOrderType_IMMEDIATE_OR_CANCEL, | ||
) | ||
s.ErrorIs(err, types.ErrLimitPriceNotSatisfied) | ||
} | ||
|
||
func (s *DexTestSuite) TestPlaceLimitOrderIOCWithDustMinAvgPrice() { | ||
s.fundAliceBalances(1, 0) | ||
s.fundBobBalances(0, 1) | ||
// GIVEN LP liq at 148.37-148.42 (with dust) | ||
s.bobDeposits( | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_000, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_001, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(1), 50_002, 1), | ||
NewDepositInt(sdkmath.ZeroInt(), sdkmath.NewInt(10), 50_003, 1), | ||
) | ||
// THEN alice IoC limitOrder with lower min avg prices success | ||
_, err := s.aliceLimitSellsWithMinAvgPrice( | ||
"TokenA", | ||
math_utils.MustNewPrecDecFromStr("0.006730"), | ||
1, | ||
math_utils.MustNewPrecDecFromStr("0.006727"), | ||
types.LimitOrderType_IMMEDIATE_OR_CANCEL, | ||
) | ||
s.NoError(err) | ||
} | ||
|
||
func (s *DexTestSuite) TestPlaceLimitOrderIOCMinAvgPriceGTSellPriceFails() { | ||
s.fundAliceBalances(40, 0) | ||
s.fundBobBalances(0, 40) | ||
// GIVEN LP liq between taker price .995 and .992 | ||
s.bobDeposits( | ||
NewDeposit(0, 10, 50, 1), | ||
NewDeposit(0, 10, 60, 1), | ||
NewDeposit(0, 10, 70, 1), | ||
NewDeposit(0, 10, 80, 1), | ||
) | ||
// THEN alice places IOC limitOrder with very low MinAveragePrice Fails | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With very high? (not "low") |
||
_, err := s.aliceLimitSellsWithMinAvgPrice( | ||
"TokenA", | ||
math_utils.MustNewPrecDecFromStr("0.99"), | ||
40, | ||
math_utils.MustNewPrecDecFromStr("0.995"), | ||
types.LimitOrderType_IMMEDIATE_OR_CANCEL, | ||
) | ||
s.ErrorIs(err, types.ErrLimitPriceNotSatisfied) | ||
} | ||
|
||
func (s *DexTestSuite) TestPlaceLimitOrderIOCMinAvgPriceGTSellPrice() { | ||
s.fundAliceBalances(40, 0) | ||
s.fundBobBalances(0, 40) | ||
// GIVEN LP liq between taker price .995 and .992 | ||
s.bobDeposits( | ||
NewDeposit(0, 10, 50, 1), | ||
NewDeposit(0, 10, 60, 1), | ||
NewDeposit(0, 10, 70, 1), | ||
NewDeposit(0, 10, 80, 1), | ||
) | ||
// THEN alice places IOC limitOrder with an achievable MinAveragePrice | ||
_, err := s.aliceLimitSellsWithMinAvgPrice( | ||
"TokenA", | ||
math_utils.MustNewPrecDecFromStr("0.99"), | ||
40, | ||
math_utils.MustNewPrecDecFromStr("0.993"), | ||
types.LimitOrderType_IMMEDIATE_OR_CANCEL, | ||
) | ||
s.NoError(err) | ||
} | ||
|
||
func (s *DexTestSuite) TestPlaceLimitOrderWithDust() { | ||
s.fundAliceBalances(1, 0) | ||
s.fundBobBalances(0, 1) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 error you are getting this place not because of the new logic, but because of the rounding nature. And thats why
006736936405289611298728644
<0.006737
in other words we swap only and only if liq.Price>limitPrice
If every price > limitPrice, it's impossible the
avg deal true price
< limitPrice.swap debug via 4 deposits:
seems like only because of accumulated rounding errors we got realsellprice 13/1932=0.006728778467908902691511387 < limitPrice
I would suggest you to add two (at least) test cases, i mean and fail and success
MinAverageSellPrice
more obviousThere 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 is the intended functionality. The goal was to be able to trade through a specific tick but tolerate a certain amount of price increase due to rounding.
There is another possible use case, which I believe you are describing where
MinAverageSellPrice
>LimitSellPrice
. This would allow trading through a certain tick, but require the average price to be better than the last tick traded through. I will add some tests for this.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.
Oh, I see. I thought the "another possible use case" is the intended functionality :) Something like: "I want to sell my 10BTC for 500USDT and i do not care about highest and lowest price, i just want my average". Confused with the name. If you wanna just be tolerant to the rounding error, did you think about another approach, e.g. instead of 'MinAverageSellPrice', introduce the bool flag "beRoundingTolerant" and do not check at all truePrice if
true
, or may beroundingTollerance
as offset ticks, i.e. the limit of rounding error which is allowed to bypass, in the nutshell the second approach is close to what you did, but it looks more intuitive for me.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.
We went back and forth on this a lot. Just being ok with all rounding allows the possibility of front running, since there is no cap on how bad rounding can get. So it's better Passing an explicit value is much safer. Both use cases are valid. I will update docs to better explain the usage for this param