@@ -84,12 +84,22 @@ def test_trade_volume(kind, amount_field, expected_volume):
8484
8585
8686@pytest .mark .parametrize (
87- "kind,sell_amount,buy_amount,quote_sell_amount,quote_buy_amount,quote_fee_amount,expected_improvement" ,
87+ "kind,sell_amount,buy_amount,quote_sell_amount,quote_buy_amount,quote_fee_amount,surplus_value, expected_improvement" ,
8888 [
89+ # Basic cases
8990 # sell order
90- ("sell" , 50 , 5100 , 100 , 10000 , 0 , 100 ),
91+ ("sell" , 50 , 5100 , 100 , 10000 , 0 , 100 , 100 ),
9192 # buy order
92- ("buy" , 49 , 5000 , 100 , 10000 , 0 , 1 ),
93+ ("buy" , 49 , 5000 , 100 , 10000 , 0 , 1 , 1 ),
94+ # Cases where surplus is smaller than quote price improvement
95+ # sell order: surplus (1) < quote improvement (2)
96+ ("sell" , 100 , 101 , 100 , 99 , 0 , 1 , 1 ),
97+ # buy order: surplus (1) < quote improvement (2)
98+ ("buy" , 99 , 100 , 101 , 100 , 0 , 1 , 1 ),
99+ # sell order: large difference - surplus (5) < quote improvement (10)
100+ ("sell" , 100 , 105 , 100 , 95 , 0 , 5 , 5 ),
101+ # Edge case: sell order with zero surplus (0) < quote improvement (5)
102+ ("sell" , 100 , 100 , 100 , 95 , 0 , 0 , 0 ),
93103 ],
94104)
95105def test_trade_price_improvement (
@@ -99,13 +109,24 @@ def test_trade_price_improvement(
99109 quote_sell_amount ,
100110 quote_buy_amount ,
101111 quote_fee_amount ,
112+ surplus_value ,
102113 expected_improvement ,
103114):
104- """Test price improvement calculation for different order kinds."""
115+ """Test price improvement calculation for different order kinds.
116+
117+ This test verifies that price_improvement returns the minimum of:
118+ 1. Quote price improvement (difference between executed and quote)
119+ 2. Limit price improvement (surplus)
120+
121+ It includes cases where surplus is smaller than quote price improvement,
122+ which should result in the surplus value being returned.
123+ """
105124 trade = Mock (spec = OnchainTrade )
106125 trade .sell_amount = sell_amount
107126 trade .buy_amount = buy_amount
108127 trade .kind = kind
128+ # Mock surplus to return the specified value
129+ trade .surplus = Mock (return_value = surplus_value )
109130
110131 quote = Quote (
111132 sell_amount = quote_sell_amount ,
@@ -214,14 +235,15 @@ def test_surplus_protocol_fee(
214235
215236
216237@pytest .mark .parametrize (
217- "kind,amount_field,price_improvement_value,is_capped,price_improvement_factor,volume_factor,expected_formula" ,
238+ "kind,amount_field,price_improvement_value,surplus_value, is_capped,price_improvement_factor,volume_factor,expected_formula" ,
218239 [
219240 # Not capped cases (price improvement fee < volume fee)
220241 # sell order - not capped
221242 (
222243 "sell" ,
223244 "buy_amount" ,
224245 5 * 10 ** 18 , # positive price improvement
246+ 5 * 10 ** 18 , # surplus equals price improvement
225247 False ,
226248 Fraction (0.5 ),
227249 Fraction (0.5 ),
@@ -233,6 +255,7 @@ def test_surplus_protocol_fee(
233255 "buy" ,
234256 "sell_amount" ,
235257 5 * 10 ** 18 , # positive price improvement
258+ 5 * 10 ** 18 , # surplus equals price improvement
236259 False ,
237260 Fraction (0.5 ),
238261 Fraction (0.5 ),
@@ -245,6 +268,7 @@ def test_surplus_protocol_fee(
245268 "sell" ,
246269 "buy_amount" ,
247270 5 * 10 ** 18 , # positive price improvement
271+ 5 * 10 ** 18 , # surplus equals price improvement
248272 True ,
249273 Fraction (0.5 ),
250274 Fraction (0.01 ),
@@ -256,6 +280,7 @@ def test_surplus_protocol_fee(
256280 "buy" ,
257281 "sell_amount" ,
258282 5 * 10 ** 18 , # positive price improvement
283+ 5 * 10 ** 18 , # surplus equals price improvement
259284 True ,
260285 Fraction (0.5 ),
261286 Fraction (0.01 ),
@@ -268,6 +293,7 @@ def test_surplus_protocol_fee(
268293 "sell" ,
269294 "buy_amount" ,
270295 - 5 * 10 ** 18 , # negative price improvement
296+ - 5 * 10 ** 18 , # surplus equals price improvement
271297 False ,
272298 Fraction (0.5 ),
273299 Fraction (0.01 ),
@@ -278,17 +304,55 @@ def test_surplus_protocol_fee(
278304 "buy" ,
279305 "sell_amount" ,
280306 - 5 * 10 ** 18 , # negative price improvement
307+ - 5 * 10 ** 18 , # surplus equals price improvement
281308 False ,
282309 Fraction (0.5 ),
283310 Fraction (0.01 ),
284311 lambda amount , pi , pi_factor , v_factor : amount , # No change
285312 ),
313+ # Cases where surplus is smaller than price improvement
314+ # sell order - surplus (1) < price improvement (2)
315+ (
316+ "sell" ,
317+ "buy_amount" ,
318+ 2 * 10 ** 18 , # quote price improvement
319+ 1 * 10 ** 18 , # surplus (smaller)
320+ False ,
321+ Fraction (0.5 ),
322+ Fraction (0.5 ),
323+ lambda amount , pi , pi_factor , v_factor : amount
324+ + round (pi_factor / (1 - pi_factor ) * (1 * 10 ** 18 )), # Use surplus value
325+ ),
326+ # buy order - surplus (1) < price improvement (2)
327+ (
328+ "buy" ,
329+ "sell_amount" ,
330+ 2 * 10 ** 18 , # quote price improvement
331+ 1 * 10 ** 18 , # surplus (smaller)
332+ False ,
333+ Fraction (0.5 ),
334+ Fraction (0.5 ),
335+ lambda amount , pi , pi_factor , v_factor : amount
336+ - round (pi_factor / (1 - pi_factor ) * (1 * 10 ** 18 )), # Use surplus value
337+ ),
338+ # Edge case: sell order with zero surplus (0) < price improvement (5)
339+ (
340+ "sell" ,
341+ "buy_amount" ,
342+ 5 * 10 ** 18 , # quote price improvement
343+ 0 , # zero surplus
344+ False ,
345+ Fraction (0.5 ),
346+ Fraction (0.5 ),
347+ lambda amount , pi , pi_factor , v_factor : amount , # No fee applied
348+ ),
286349 ],
287350)
288351def test_price_improvement_protocol_fee (
289352 kind ,
290353 amount_field ,
291354 price_improvement_value ,
355+ surplus_value ,
292356 is_capped ,
293357 price_improvement_factor ,
294358 volume_factor ,
@@ -300,6 +364,8 @@ def test_price_improvement_protocol_fee(
300364 1. Not capped cases - where price improvement fee is less than volume fee
301365 2. Capped cases - where price improvement fee is greater than volume fee
302366 3. Negative price improvement cases - where no fee is applied
367+ 4. Cases where surplus is smaller than quote price improvement - should use the smaller value
368+ 5. Edge case with zero surplus - should apply no fee
303369 """
304370 amount = 15 * 10 ** 18
305371
@@ -318,13 +384,22 @@ def test_price_improvement_protocol_fee(
318384 setattr (trade , amount_field , amount )
319385 trade .kind = kind
320386 trade .volume = Mock (return_value = amount )
321- trade .price_improvement = Mock (return_value = price_improvement_value )
387+
388+ # Set up price_improvement to return the minimum of quote price improvement and surplus
389+ # This matches the actual behavior of the price_improvement method
390+ min_improvement = min (price_improvement_value , surplus_value )
391+ trade .price_improvement = Mock (return_value = min_improvement )
392+
393+ # Set up surplus to return the specified surplus value
394+ trade .surplus = Mock (return_value = surplus_value )
322395
323396 # Reverse the fee application
324397 new_trade = fee_policy .reverse_protocol_fee (trade )
325398
326399 # Verify the amount without fee
400+ # Use the minimum improvement value in the expected formula
401+ min_improvement = min (price_improvement_value , surplus_value )
327402 expected_amount = expected_formula (
328- amount , price_improvement_value , price_improvement_factor , volume_factor
403+ amount , min_improvement , price_improvement_factor , volume_factor
329404 )
330405 assert getattr (new_trade , amount_field ) == expected_amount
0 commit comments