-
Notifications
You must be signed in to change notification settings - Fork 8
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
Add max_price_impact
parameter to KellyBettingStrategy
#433
Conversation
WalkthroughThe pull request introduces a comprehensive suite of unit tests for the Changes
Possibly related PRs
Suggested reviewers
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Results from this simulation look promising - already better than
Note that Next steps |
Some updated simulations Highlights:
|
else new_yes / (new_yes + new_no) | ||
) | ||
# print(f"actual_price {actual_price} actual_price2 {actual_price_2}") | ||
s = (actual_price - expected_price) / expected_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.
The sign of s
is the opposite to what you'd get from the formula in this comment. Does it make a difference?
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.
-> If actual_price
> expected_price
, you paid more for the same amount of tokens, hence slippage should be > 0.
-> If actual_price
< 'expected_price`, you paid less, hence slippage < 0.
So I guess the formula is correct per the above, or would you disagree?
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.
Also note that
-> By the way, one correction ref slippage - in the "normal case" (see example here https://docs.gnosis.io/conditionaltokens/docs/introduction3/#an-example-with-cpmm), slippage is >0 (new_price_yes = 0.8, old_price = 0.5, hence positive slippage) (edited)
-> Now, in the example above, let's say you place a bet NO with the same 10 xDAI. If you do the math, you derive that you got 23 .33 NO tokens (invariant becomes 15 Y * 6.67 No = 100), but you expected 20 tokens (since original price was 0.2). Hence this is a <0 slippage (you paid cheaper than expected)
12:32
So slippage can be negative!
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.
Okay, this makes sense now. And it also makes sense to me that this works as expected when called in slippage_diff
😄. Lots of not very intuitive things for me to get my head around
try: | ||
optimized_bet_amount = minimize_scalar( | ||
slippage_diff, | ||
bounds=(min(yes_outcome_pool_size, no_outcome_pool_size) / 10, 100), |
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.
If self.max_slippage
is very small, then the root might be smaller than the lower bound. Similarly, if the pool is very large, the root could be bigger than 100. Is [0, inf] okay?
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.
-> 0 is not OK since get_buy_outcome_token_amount
breaks for 0
if ending_outcome_balance <= 0:
raise ValueError("must have non-zero balances")
For that reason I used a small size as bound, which might be too large already.
-> inf works, I can try with sys.maxsize or similar
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.
@evangriffiths please take a look the updated versions now, should address the concerns above.
I don't see any more logs with deviating values. I also changed the log
to an Error, so it's obvious when values are wrong.
…track-experiments-kelly # Conflicts: # examples/monitor/match_bets_with_langfuse_traces.py # poetry.lock
] | ||
|
||
storage = hishel.FileStorage(ttl=3600) | ||
controller = hishel.Controller(force_cache=True) | ||
httpx_client = hishel.CacheClient(storage=storage, controller=controller) |
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.
That's interesting, what about cutting it out to some helper function like get_cached_httpx_client
?
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.
Abstracted it away (see class HttpxCachedClient)
@@ -1,5 +1,10 @@ | |||
from abc import ABC, abstractmethod | |||
|
|||
import numpy as np | |||
from loguru import logger |
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.
from loguru import logger | |
from prediction_market_agent_tooling.loggers import logger |
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.
You didn't commit this
slippage, self.max_price_impact, self.max_price_impact / 100 | ||
): | ||
logger.info( | ||
f"Slippage {slippage} deviates too much from self.max_slippage {self.max_price_impact}, market_id {market.id}" |
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.
deviates too much
It sounds pretty bad, yet it's logged as info
, and the code continues. Can it be just ignored?
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 see this happen a lot if I run the script on this branch. If this is ever hit, does that mean there's a bug in calculate_bet_amount_for_price_impact
?
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.
Indeed the minimize_scalar
was complaining - I adjusted bounds and now it looks better. Please give it a go and let me know if you find issues!
Please note that this is now a ValueError since I want to enforce these boundaries.
# We just don't want Kelly size to extrapolate price_impact - hence we take the min. | ||
kelly_bet_size = min(kelly_bet.size, max_slippage_bet_amount) | ||
|
||
self._check_price_impact_ok_else_log( |
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.
So it's possible it's not ok, but it just continues?
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.
Please check revised version - now it's a ValueError.
def calculate_bet_amount_for_price_impact( | ||
self, market: AgentMarket, kelly_bet: SimpleBet, fee: float | ||
) -> float: | ||
def calculate_price_impact_deviation_from_target_price_impact(b: xDai) -> float: |
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.
Why does this need to be a function within the function?
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.
It doesn't have to be, it just felt simpler to have this here since it's not needed anywhere else in the class.
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.
Hmm, that's almost never done in Python. Can you just make it a normal function, please?
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 dunno, I think it's fine in this context, especially as it's being used as a Callable, passed as an arg to minimize_scalar
ChatGPT agrees:
in python is it good practice to define a function inside a function?
...
If the inner function is being passed as a callable to another function, this can be a valid and clean design choice, especially if the callable depends on the state of the outer function
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.
Also I did the same thing here
prediction-market-agent-tooling/prediction_market_agent_tooling/tools/utils.py
Lines 231 to 238 in 29224f8
def f(r: float) -> float: | |
R = r / (1 - fee) | |
first_term = other_holdings - R | |
second_term = holdings + shares_to_sell - R | |
third_term = holdings * other_holdings | |
return (first_term * second_term) - third_term | |
amount_to_sell = newton(f, 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.
Okay then, I'm standing overvoted 😄 For sure it's not a blocker.
scripts/calc_slippage.py
Outdated
@@ -0,0 +1,18 @@ | |||
r_a = 10 |
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.
In PMAT, all scripts
have been helpful in executing some actions so far.
This feels more for the examples
folder. 🤔
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.
Removed
tests/markets/omen/test_kelly.py
Outdated
kelly: KellyBettingStrategy, | ||
): | ||
# expect | ||
expected_price = yes / (yes + no) # p_yes |
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 p_no
?
prediction-market-agent-tooling/prediction_market_agent_tooling/markets/omen/data_models.py
Line 346 in 75e9310
1 - self.outcomeTokenAmounts[self.yes_index] / sum(self.outcomeTokenAmounts) |
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 changed yes, no = no, yes
if buy_direction is False.
Tests taken from https://docs.gnosis.io/conditionaltokens/docs/introduction3/#an-example-with-cpmm pass.
Sorry, accidentaly clicked on Approve while submitting
Can you post these for all agents we have available? No need for the full table, just What I'm wondering is if this strategy is more profitable on all of them. To check if this isn't an over-fit for this particular agent. |
Some more results Notes:
DeployablePredictionProphetGPT4TurboFinalAgent23 bets
DeployablePredictionProphetGPT4TurboPreviewAgent23 bets
DeployableOlasEmbeddingOAAgent23 bets
DeployableKnownOutcomeAgent23 bets
|
…track-experiments-kelly
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.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (3)
prediction_market_agent_tooling/deploy/betting_strategy.py (3)
150-174
: New method:assert_price_impact_lt_max_price_impact_else_raise
This method ensures that the price impact of a bet doesn't exceed the specified maximum. The implementation looks correct, but there are a few points to consider:
- The method name is quite long. Consider a shorter name like
assert_price_impact_within_limit
.- The use of
np.isclose
with a relative tolerance is a good approach to handle floating-point comparisons.- The error message in the
ValueError
is informative, which is good for debugging.Consider renaming the method to improve readability:
def assert_price_impact_within_limit( self, buy_direction: bool, bet_size: float, market: AgentMarket, ) -> None: # ... rest of the method remains the same
204-216
: Updatedcalculate_trades
method with price impact considerationThe modifications to include price impact calculations in the
calculate_trades
method are well-implemented. However, there are a few points to consider:
- The comment "Adjust amount" could be more descriptive.
- The hardcoded
0
passed tocalculate_bet_amount_for_price_impact
for thefee
parameter might not be correct for all markets.Consider updating the comment and using the market's fee:
# Calculate bet amount considering max price impact max_slippage_bet_amount = self.calculate_bet_amount_for_price_impact( market, kelly_bet, market.fee )
229-244
: New method:calculate_price_impact_for_bet_amount
This method calculates the price impact based on the bet amount and market conditions. The implementation looks correct, but there's a minor issue with a comment:
The comment "price_impact should always be > 0" is not always true. Price impact can be negative in certain market conditions. Consider updating the comment to reflect this:
# Note: price_impact can be positive or negative depending on market conditions
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
- prediction_market_agent_tooling/deploy/betting_strategy.py (5 hunks)
🔇 Additional comments (5)
prediction_market_agent_tooling/deploy/betting_strategy.py (5)
3-5
: New imports added for price impact calculationsThe additions of
numpy
,logger
, andminimize_scalar
are appropriate for the new price impact calculation functionality. These libraries will be useful for numerical operations, logging, and optimization respectively.
18-20
: Import ofget_buy_outcome_token_amount
functionThe import of
get_buy_outcome_token_amount
from the Omen module is now explicitly stated. This is good for clarity and helps in understanding the dependencies of the price impact calculations.
146-148
: Updated constructor withmax_price_impact
parameterThe addition of the
max_price_impact
parameter with a default value ofNone
is a good approach. It allows for backwards compatibility while introducing the new price impact functionality.
290-290
: Updated__repr__
methodThe
__repr__
method has been updated to include themax_price_impact
parameter. This is good for debugging and logging purposes.
Line range hint
1-290
: Overall assessment of changesThe modifications to the
KellyBettingStrategy
class significantly enhance its functionality by incorporating price impact considerations. The new methods for calculating and asserting price impact are well-implemented, and the updates to thecalculate_trades
method effectively integrate these new features.There are a few minor suggestions for improvement:
- Consider renaming the
assert_price_impact_lt_max_price_impact_else_raise
method for better readability.- Ensure that market fees are correctly used in price impact calculations.
- Update comments to accurately reflect the behavior of price impact calculations.
These changes provide a more sophisticated betting strategy that should perform better in real-world market conditions by considering the impact of bets on market prices.
def calculate_bet_amount_for_price_impact( | ||
self, | ||
market: AgentMarket, | ||
kelly_bet: SimpleBet, | ||
fee: float, | ||
) -> float: | ||
def calculate_price_impact_deviation_from_target_price_impact( | ||
bet_amount: xDai, | ||
) -> float: | ||
price_impact = self.calculate_price_impact_for_bet_amount( | ||
kelly_bet.direction, | ||
bet_amount, | ||
yes_outcome_pool_size, | ||
no_outcome_pool_size, | ||
fee, | ||
) | ||
# We return abs for the algorithm to converge to 0 instead of the min (and possibly negative) value. | ||
|
||
max_price_impact = check_not_none(self.max_price_impact) | ||
return abs(price_impact - max_price_impact) | ||
|
||
if not market.outcome_token_pool: | ||
logger.warning( | ||
"Market outcome_token_pool is None, cannot calculate bet amount" | ||
) | ||
return kelly_bet.size | ||
|
||
yes_outcome_pool_size = market.outcome_token_pool[ | ||
market.get_outcome_str_from_bool(True) | ||
] | ||
no_outcome_pool_size = market.outcome_token_pool[ | ||
market.get_outcome_str_from_bool(False) | ||
] | ||
|
||
optimized_bet_amount = minimize_scalar( | ||
calculate_price_impact_deviation_from_target_price_impact, | ||
bounds=(min(yes_outcome_pool_size, no_outcome_pool_size) / 1000, 1000), | ||
method="bounded", | ||
tol=1e-11, | ||
options={"maxiter": 10000}, | ||
) | ||
return float(optimized_bet_amount.x) |
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.
New method: calculate_bet_amount_for_price_impact
This method uses numerical optimization to find the bet amount that achieves the target price impact. The implementation is generally good, but there are a few points to consider:
- The use of
minimize_scalar
with bounded optimization is appropriate. - The inner function
calculate_price_impact_deviation_from_target_price_impact
is well-structured. - The error handling for missing
outcome_token_pool
is good.
However, there's a potential issue:
The fee
parameter is passed to this method but not used in the price impact calculation. This could lead to inaccurate results if the market has a non-zero fee. Consider updating the inner function to use the fee
parameter:
price_impact = self.calculate_price_impact_for_bet_amount(
kelly_bet.direction,
bet_amount,
yes_outcome_pool_size,
no_outcome_pool_size,
fee, # Use the fee parameter here
)
price_impact = self.calculate_price_impact_for_bet_amount( | ||
buy_direction, | ||
bet_size, | ||
outcome_token_pool["Yes"], |
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.
Somewhere down the codes you used
market.outcome_token_pool[market.get_outcome_str_from_bool(True)]
and
market.outcome_token_pool[market.get_outcome_str_from_bool(False)]
That's more future-proof for no extra costs
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 point - implemented.
tests/markets/omen/test_kelly.py
Outdated
@@ -0,0 +1,50 @@ | |||
import numpy as np |
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.
These test are in the omen
directory but they don't have anything specific about Omen
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.
Agreed - moved.
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.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (7)
tests/test_kelly.py (3)
6-13
: Enhance test coverage and readability.While the test case is based on Gnosis documentation, consider the following improvements:
- Add assertions within the function body to verify the initial state of the
KellyBettingStrategy
instance.- Include comments explaining the expected behavior or outcome of the test.
- Consider parameterizing the test to cover multiple scenarios easily.
Here's a suggested improvement:
def test_kelly_slippage_calculation1() -> None: # Test case based on https://docs.gnosis.io/conditionaltokens/docs/introduction3/#an-example-with-cpmm kelly = KellyBettingStrategy(max_bet_amount=1, max_price_impact=0.5) # Verify initial state assert kelly.max_bet_amount == 1 assert kelly.max_price_impact == 0.5 # Equal probability scenario yes = 10 no = 10 bet_amount = 10 buy_direction = True # Expected outcome: Price impact should be calculated correctly for a buy direction in an equal probability scenario assert_price_impact(bet_amount, buy_direction, yes, no, kelly)
16-24
: Enhance test coverage and readability.Similar to the first test case, consider the following improvements:
- Add assertions within the function body to verify the initial state of the
KellyBettingStrategy
instance.- Include comments explaining the expected behavior or outcome of the test.
- Consider parameterizing the test to cover multiple scenarios easily.
Here's a suggested improvement:
def test_kelly_slippage_calculation2() -> None: # Test case based on https://docs.gnosis.io/conditionaltokens/docs/introduction3/#an-example-with-cpmm kelly = KellyBettingStrategy(max_bet_amount=1, max_price_impact=0.5) # Verify initial state assert kelly.max_bet_amount == 1 assert kelly.max_price_impact == 0.5 # Scenario after a bet of 10 xDAI on Yes yes = 5 no = 20 bet_amount = 10 buy_direction = False # Expected outcome: Price impact should be calculated correctly for a sell direction after a previous bet assert_price_impact(bet_amount, buy_direction, yes, no, kelly)
1-51
: Overall good start, but room for improvement in test coverage and structure.The file provides a good foundation for testing the
KellyBettingStrategy
class, particularly focusing on price impact calculations. However, there are several areas where the tests could be enhanced:
- Increase test coverage by adding more test cases with different scenarios.
- Consider using parameterized tests to easily cover multiple input combinations.
- Add more assertions within each test function to verify the state of the
KellyBettingStrategy
instance and intermediate calculations.- Improve code readability by adding more comments explaining the expected behavior and outcomes of each test.
- Consider organizing the tests into a test class, which could help with setup and teardown of common test fixtures.
To improve the overall structure and maintainability of the tests, consider the following:
- Create a
TestKellyBettingStrategy
class to group related tests.- Use
pytest.fixture
for common setup code.- Implement parameterized tests using
pytest.mark.parametrize
for testing multiple scenarios efficiently.Example structure:
import pytest from prediction_market_agent_tooling.deploy.betting_strategy import KellyBettingStrategy class TestKellyBettingStrategy: @pytest.fixture def kelly_strategy(self): return KellyBettingStrategy(max_bet_amount=1, max_price_impact=0.5) @pytest.mark.parametrize("yes,no,bet_amount,buy_direction,expected_impact", [ (10, 10, 10, True, ...), # Fill in expected impact (5, 20, 10, False, ...), # Fill in expected impact # Add more test cases here ]) def test_price_impact_calculation(self, kelly_strategy, yes, no, bet_amount, buy_direction, expected_impact): price_impact = kelly_strategy.calculate_price_impact_for_bet_amount( buy_direction, bet_amount=bet_amount, yes=yes, no=no, fee=0 ) assert pytest.approx(price_impact, rel=1e-2) == expected_impact # Add more test methods as neededThis structure would make it easier to add and maintain tests as the
KellyBettingStrategy
class evolves.prediction_market_agent_tooling/deploy/betting_strategy.py (4)
146-148
: New parameter added for price impact control.The addition of
max_price_impact
parameter enhances the flexibility of theKellyBettingStrategy
. This is a good improvement that allows for more fine-grained control over the betting behavior.Consider using
Optional[float]
instead offloat | None
for better compatibility with Python versions below 3.10:from typing import Optional def __init__(self, max_bet_amount: float, max_price_impact: Optional[float] = None):
150-174
: New method to assert price impact is within limits.This method provides a crucial check to ensure that the price impact of a bet doesn't exceed the specified maximum. The use of
np.isclose
for floating-point comparison is a good practice.Consider improving the error handling by providing more context in the error message:
raise ValueError( f"Price impact {price_impact:.4f} exceeds max_price_impact {max_price_impact:.4f} " f"by {(price_impact - max_price_impact) / max_price_impact:.2%}. " f"Market ID: {market.id}" )This change provides more detailed information about the extent of the violation, which could be helpful for debugging and monitoring.
229-244
: New method to calculate price impact.This method provides a crucial calculation for determining the price impact of a bet. The logic seems correct and uses appropriate market functions.
However, the comment "price_impact should always be > 0" might not be accurate in all cases. Price impact can be negative if the actual price is lower than the expected price. Consider updating the comment to:
# Note: price_impact can be positive or negative depending on market conditions
This change acknowledges that price impact can vary based on market dynamics.
246-287
: New method for optimizing bet amount based on price impact.This method effectively uses numerical optimization to find the optimal bet amount that achieves the target price impact. The use of
minimize_scalar
is appropriate for this task.Consider the following improvements:
- Add a docstring to explain the purpose and parameters of the method.
- Handle the case when
self.max_price_impact
is None more explicitly.- Consider making the optimization bounds more flexible or configurable.
Here's a suggested improvement:
def calculate_bet_amount_for_price_impact( self, market: AgentMarket, kelly_bet: SimpleBet, fee: float, ) -> float: """ Calculate the optimal bet amount for a given price impact using numerical optimization. Args: market (AgentMarket): The market to calculate the bet amount for. kelly_bet (SimpleBet): The Kelly bet object containing direction and size. fee (float): The fee percentage. Returns: float: The optimal bet amount that achieves the target price impact. """ if self.max_price_impact is None: return kelly_bet.size if not market.outcome_token_pool: logger.warning("Market outcome_token_pool is None, cannot calculate bet amount") return kelly_bet.size yes_outcome_pool_size = market.outcome_token_pool[market.get_outcome_str_from_bool(True)] no_outcome_pool_size = market.outcome_token_pool[market.get_outcome_str_from_bool(False)] lower_bound = min(yes_outcome_pool_size, no_outcome_pool_size) / 1000 upper_bound = max(1000, kelly_bet.size * 2) # Adjust upper bound based on Kelly bet size # ... rest of the method remains the sameThese changes improve the method's clarity, error handling, and flexibility.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (2)
- prediction_market_agent_tooling/deploy/betting_strategy.py (5 hunks)
- tests/test_kelly.py (1 hunks)
🔇 Additional comments (3)
tests/test_kelly.py (1)
1-3
: LGTM: Imports are appropriate for the tests.The import statements are correct and necessary for the tests being performed.
numpy
is used for floating-point comparison, andKellyBettingStrategy
is the class being tested.prediction_market_agent_tooling/deploy/betting_strategy.py (2)
3-5
: New imports added for enhanced functionality.The additions of
numpy
,logger
, andminimize_scalar
from scipy suggest new mathematical operations and optimization techniques are being introduced. This is a good practice for expanding the capabilities of the betting strategy.
289-290
: Updated string representation to include max_price_impact.The
__repr__
method has been correctly updated to include themax_price_impact
parameter. This change ensures that the string representation of the class accurately reflects its current state, including the new parameter.
tests/test_kelly.py
Outdated
def assert_price_impact( | ||
bet_amount: float, | ||
buy_direction: bool, | ||
yes: float, | ||
no: float, | ||
kelly: KellyBettingStrategy, | ||
) -> None: | ||
price_impact = kelly.calculate_price_impact_for_bet_amount( | ||
buy_direction, bet_amount=bet_amount, yes=yes, no=no, fee=0 | ||
) | ||
|
||
# Calculation is done assuming buy_direction is True. Else, we invert the reserves. | ||
if not buy_direction: | ||
yes, no = no, yes | ||
|
||
expected_price_yes = no / (yes + no) | ||
k = yes * no | ||
tokens_bought_yes = (yes + bet_amount) - (k / (no + bet_amount)) # 23.333 # x*y = k | ||
actual_price_yes = bet_amount / tokens_bought_yes | ||
expected_price_impact = (actual_price_yes - expected_price_yes) / expected_price_yes | ||
#### | ||
|
||
assert np.isclose(price_impact, expected_price_impact, rtol=0.01) | ||
|
||
print(price_impact) |
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.
💡 Codebase verification
Unnecessary print statements found in test files.
The following print statements are present:
tests/test_kelly.py: print(price_impact)
tests/markets/omen/test_omen.py: print(position) # For extra test coverage
Consider removing these print statements or replacing them with proper logging to avoid cluttering test outputs.
🔗 Analysis chain
Minor improvements and clarification needed.
The assert_price_impact
function looks well-implemented overall. However, consider the following suggestions:
- Add type hints for the return value of
calculate_price_impact_for_bet_amount
. - Consider using constants for magic numbers like 0.01 in the np.isclose call.
- The print statement at the end might not be necessary for automated tests. If it's for debugging, consider using a logger or removing it.
Here's a suggested improvement:
import logging
from typing import Any
RELATIVE_TOLERANCE = 0.01
def assert_price_impact(
bet_amount: float,
buy_direction: bool,
yes: float,
no: float,
kelly: KellyBettingStrategy,
) -> None:
price_impact: float = kelly.calculate_price_impact_for_bet_amount(
buy_direction, bet_amount=bet_amount, yes=yes, no=no, fee=0
)
# ... (rest of the function remains the same)
assert np.isclose(price_impact, expected_price_impact, rtol=RELATIVE_TOLERANCE)
logging.debug(f"Price impact: {price_impact}")
Could you clarify the purpose of the print statement at the end of the function? Is it intended for debugging or some other purpose?
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other print statements in test files
rg --type python 'print\(' tests/
Length of output: 66
Script:
#!/bin/bash
# Search for other print statements in Python test files
rg --type py 'print\(' tests/
Length of output: 154
kelly_bet_size = kelly_bet.size | ||
if self.max_price_impact: | ||
# Adjust amount | ||
max_slippage_bet_amount = self.calculate_bet_amount_for_price_impact( | ||
market, kelly_bet, 0 | ||
) | ||
|
||
# We just don't want Kelly size to extrapolate price_impact - hence we take the min. | ||
kelly_bet_size = min(kelly_bet.size, max_slippage_bet_amount) | ||
|
||
self.assert_price_impact_lt_max_price_impact_else_raise( | ||
kelly_bet.direction, kelly_bet_size, market | ||
) | ||
|
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.
Bet size adjustment based on price impact.
The addition of price impact consideration in the bet size calculation is a significant improvement. It ensures that the Kelly bet size doesn't exceed the maximum allowed price impact.
However, the hardcoded value of 0 for the fee parameter in calculate_bet_amount_for_price_impact
could lead to inaccurate calculations if the market has a non-zero fee. Consider using the actual market fee:
max_slippage_bet_amount = self.calculate_bet_amount_for_price_impact(
market, kelly_bet, fee=market.fee if hasattr(market, 'fee') else 0
)
This change ensures that the fee is correctly accounted for in the price impact calculations.
# We just don't want Kelly size to extrapolate price_impact - hence we take the min. | ||
kelly_bet_size = min(kelly_bet.size, max_slippage_bet_amount) | ||
|
||
self.assert_price_impact_lt_max_price_impact_else_raise( |
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 this needed to run every time in the core code? Looks like a sanity check that could be done in a pytest, and removed from 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.
Makes sense. Refactored this as an integration test (see test_kelly
).
|
||
optimized_bet_amount = minimize_scalar( | ||
calculate_price_impact_deviation_from_target_price_impact, | ||
bounds=(min(yes_outcome_pool_size, no_outcome_pool_size) / 1000, 1000), |
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 I commented on these bounds before, but find it. But these don't seem super robust, e.g. if used for markets with v large or v small liquidity (or non-Omen markets that use a different currency where it's normal to see larger/smaller values). Shouldn't the bounds be [0, inf]?
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.
Ah here's the previous comment #433 (comment)
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.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (7)
prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py (1)
20-20
: LGTM! Consider updating the import style for consistency.The change from using
loguru
to an internal logging module is a good practice for maintaining control over the logging implementation. This change is unlikely to cause any functional issues as the usage oflogger.debug()
is consistent with both implementations.For consistency with other imports in the file, consider using an absolute import:
from prediction_market_agent_tooling.loggers import loggerThis style is more explicit and less prone to potential circular import issues.
prediction_market_agent_tooling/deploy/betting_strategy.py (6)
146-149
: LGTM: New parameter added for price impact controlThe addition of the
max_price_impact
parameter with a default value ofNone
is a good improvement. It allows for more flexible betting strategies while maintaining backward compatibility.Consider adding a type hint for
max_price_impact
to improve code readability:def __init__(self, max_bet_amount: float, max_price_impact: Optional[float] = None):Don't forget to import
Optional
fromtyping
if you make this change.
150-174
: LGTM: New method to enforce maximum price impactThis method effectively ensures that the price impact doesn't exceed the maximum allowed value. The use of
check_not_none
for null checks andnp.isclose
for float comparisons are good practices.Consider adding a docstring to explain the purpose and parameters of this method. For example:
def assert_price_impact_lt_max_price_impact_else_raise( self, buy_direction: bool, bet_size: float, market: AgentMarket, ) -> None: """ Assert that the price impact of a bet is less than the maximum allowed price impact. Args: buy_direction (bool): True if buying, False if selling. bet_size (float): The size of the bet. market (AgentMarket): The market to check the price impact against. Raises: ValueError: If the price impact exceeds the maximum allowed value. """
204-217
: LGTM: Bet size adjustment based on price impactThe addition of price impact considerations in the bet size calculation is a significant improvement. It ensures that the Kelly bet size doesn't exceed the maximum allowed price impact.
The hardcoded value of 0 for the fee parameter in
calculate_bet_amount_for_price_impact
could lead to inaccurate calculations if the market has a non-zero fee. Consider using the actual market fee:max_slippage_bet_amount = self.calculate_bet_amount_for_price_impact( market, kelly_bet, fee=market.fee if hasattr(market, 'fee') else 0 )
229-244
: LGTM: New method for calculating price impactThe
calculate_price_impact_for_bet_amount
method correctly implements the price impact calculation. The use ofget_buy_outcome_token_amount
from the Omen market is appropriate.The comment "price_impact should always be > 0" might not always be true. Price impact can be negative if the actual price is lower than the expected price, which can happen in certain market conditions. Consider updating the comment to:
# Note: price_impact can be positive or negative depending on market conditions
246-287
: LGTM: New method for optimizing bet amount based on price impactThe
calculate_bet_amount_for_price_impact
method effectively uses numerical optimization to find the optimal bet amount. The use ofscipy.optimize.minimize_scalar
with bounded optimization is appropriate, and the error handling for missingoutcome_token_pool
is good.Consider making the optimization bounds more flexible:
- The lower bound
min(yes_outcome_pool_size, no_outcome_pool_size) / 1000
might be too large for markets with very small liquidity.- The upper bound of 1000 might be too small for markets with very large liquidity or when using a different currency.
You could make these bounds configurable or use a wider range. For example:
lower_bound = max(1e-6, min(yes_outcome_pool_size, no_outcome_pool_size) / 1e6) upper_bound = max(1000, max(yes_outcome_pool_size, no_outcome_pool_size) * 10) optimized_bet_amount = minimize_scalar( calculate_price_impact_deviation_from_target_price_impact, bounds=(lower_bound, upper_bound), method="bounded", tol=1e-11, options={"maxiter": 10000}, )This change would make the method more robust across different market conditions and currencies.
Line range hint
1-290
: Overall assessment: Significant improvement in betting strategyThe changes to the
KellyBettingStrategy
class represent a substantial improvement in the betting strategy by incorporating price impact considerations. The new methods for calculating and optimizing bet amounts based on price impact are well-implemented and add valuable functionality to the strategy.Key improvements:
- Addition of
max_price_impact
parameter for flexible control.- New methods for calculating and asserting price impact.
- Integration of price impact considerations in the
calculate_trades
method.- Use of numerical optimization to find optimal bet amounts.
These changes should lead to more sophisticated and potentially more profitable betting strategies, especially in markets where price impact is a significant factor.
To further improve the code:
- Consider extracting the price impact calculation logic into a separate class or module. This would improve modularity and make it easier to test and maintain the price impact logic independently of the betting strategy.
- Implement unit tests for the new methods, especially
calculate_price_impact_for_bet_amount
andcalculate_bet_amount_for_price_impact
, to ensure their correctness across various market conditions.- Consider adding logging statements in key parts of the code (e.g., when adjusting bet sizes or when price impact assertions fail) to aid in debugging and monitoring the strategy's performance.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- prediction_market_agent_tooling/deploy/betting_strategy.py (5 hunks)
- prediction_market_agent_tooling/markets/polymarket/api.py (1 hunks)
- prediction_market_agent_tooling/tools/is_predictable.py (1 hunks)
- prediction_market_agent_tooling/tools/tavily_storage/tavily_models.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
- prediction_market_agent_tooling/markets/polymarket/api.py
🔇 Additional comments (3)
prediction_market_agent_tooling/tools/is_predictable.py (1)
Line range hint
1-185
: LGTM! Ensure thorough testing of logging functionality.The change in the logger import doesn't appear to affect the rest of the file. The main functions
is_predictable_binary
andis_predictable_without_description
should continue to work as expected. However, it's crucial to ensure that the logging functionality remains intact.To verify the logging functionality, please run the following test cases:
- Test the error logging in
is_predictable_binary
:import sys sys.path.append('path/to/your/project') from prediction_market_agent_tooling.tools.is_predictable import is_predictable_binary # Simulate a scenario where langchain is not installed import sys sys.modules['langchain'] = None result = is_predictable_binary("Test question") # Check if the error was logged correctly
- Test the error logging in
is_predictable_without_description
:from prediction_market_agent_tooling.tools.is_predictable import is_predictable_without_description # Simulate a scenario where langchain is not installed import sys sys.modules['langchain'] = None result = is_predictable_without_description("Test question", "Test description") # Check if the error was logged correctlyThese tests will help ensure that the logging functionality works as expected with the new logger.
prediction_market_agent_tooling/deploy/betting_strategy.py (2)
3-7
: New imports added for price impact calculationsThe additions of
numpy
,scipy.optimize
, andget_buy_outcome_token_amount
are appropriate for the new price impact calculations. These libraries provide the necessary tools for numerical optimization and financial calculations.
289-290
: LGTM: Updated__repr__
methodThe
__repr__
method has been correctly updated to include themax_price_impact
parameter. This change provides a more complete representation of the object's state, which is consistent with the addition ofmax_price_impact
in the__init__
method.
max_price_impact
parameter to KellyBettingStrategy
|
||
optimized_bet_amount = minimize_scalar( | ||
calculate_price_impact_deviation_from_target_price_impact, | ||
bounds=(min(yes_outcome_pool_size, no_outcome_pool_size) / 1000, 1000), |
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 see you get some exception with max bound of sys.maxsize
. A simple way of making it more robust would be just to set the upper bound relative to total pool size.
I tried
bounds=(min(yes_outcome_pool_size, no_outcome_pool_size) / 1000, 1000), | |
bounds=(0, 1000 * (yes_outcome_pool_size + no_outcome_pool_size)), |
and it seems to work fine, and is more robust imo.
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.
Works for me as well. Implemented.
…track-experiments-kelly # Conflicts: # poetry.lock # pyproject.toml
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.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (6)
prediction_market_agent_tooling/deploy/betting_strategy.py (6)
146-149
: LGTM: New parameter for price impact control.The addition of
max_price_impact
parameter allows for configurable price impact limits, which is a good enhancement to the strategy.Consider using
Optional[float]
instead offloat | None
for better compatibility with Python versions below 3.10:-def __init__(self, max_bet_amount: float, max_price_impact: float | None = None): +from typing import Optional + +def __init__(self, max_bet_amount: float, max_price_impact: Optional[float] = None):
150-174
: LGTM: Price impact assertion method.This method effectively ensures that the price impact doesn't exceed the specified limit. The use of
np.isclose
is a good practice for floating-point comparisons.Consider the following improvements:
- Make the tolerance configurable, e.g., as a class attribute.
- Enhance the error message to include the actual difference between the price impact and the max_price_impact.
class KellyBettingStrategy(BettingStrategy): def __init__(self, max_bet_amount: float, max_price_impact: Optional[float] = None, price_impact_tolerance: float = 0.01): # ... existing code ... self.price_impact_tolerance = price_impact_tolerance def assert_price_impact_lt_max_price_impact_else_raise( self, buy_direction: bool, bet_size: float, market: AgentMarket, ) -> None: # ... existing code ... if price_impact > max_price_impact and not np.isclose( price_impact, max_price_impact, atol=max_price_impact * self.price_impact_tolerance ): raise ValueError( f"Price impact {price_impact:.6f} exceeds max_price_impact {max_price_impact:.6f} " f"by {price_impact - max_price_impact:.6f} (tolerance: {max_price_impact * self.price_impact_tolerance:.6f}), " f"market_id {market.id}" )
204-217
: LGTM: Bet size adjustment based on price impact.The addition of price impact consideration in the bet size calculation is a significant improvement. It ensures that the Kelly bet size doesn't exceed the maximum allowed price impact.
Consider the following improvements:
- Remove the redundant assertion after adjustment, as
calculate_bet_amount_for_price_impact
should already ensure the price impact is within limits.- Rename
max_slippage_bet_amount
tomax_price_impact_bet_amount
for consistency with the new terminology.- Pass the market fee to
calculate_bet_amount_for_price_impact
instead of hardcoding 0.if self.max_price_impact: # Adjust amount - max_slippage_bet_amount = self.calculate_bet_amount_for_price_impact( - market, kelly_bet, 0 + max_price_impact_bet_amount = self.calculate_bet_amount_for_price_impact( + market, kelly_bet, market.fee ) # We just don't want Kelly size to extrapolate price_impact - hence we take the min. - kelly_bet_size = min(kelly_bet.size, max_slippage_bet_amount) + kelly_bet_size = min(kelly_bet.size, max_price_impact_bet_amount) - self.assert_price_impact_lt_max_price_impact_else_raise( - kelly_bet.direction, kelly_bet_size, market - )
229-244
: LGTM: Price impact calculation method.The
calculate_price_impact_for_bet_amount
method correctly calculates the price impact based on the expected and actual prices.Update the comment about price impact always being > 0, as it might not be accurate in all cases:
-# price_impact should always be > 0 +# Note: price_impact can be positive or negative depending on market conditions price_impact = (actual_price - expected_price) / expected_price
246-288
: LGTM: Optimal bet amount calculation for price impact.The
calculate_bet_amount_for_price_impact
method effectively uses numerical optimization to find the bet amount that achieves the target price impact.Consider the following improvements:
- Make the optimization bounds more flexible:
-bounds=(0, 1000 * (yes_outcome_pool_size + no_outcome_pool_size)), +bounds=(0, 10 * (yes_outcome_pool_size + no_outcome_pool_size)),
- Add a docstring explaining the method's purpose and parameters.
- Consider extracting the inner function
calculate_price_impact_deviation_from_target_price_impact
as a separate method for better readability.- Add error handling for cases where the optimization fails to converge.
Example implementation:
def calculate_bet_amount_for_price_impact( self, market: AgentMarket, kelly_bet: SimpleBet, fee: float, ) -> float: """ Calculate the optimal bet amount that achieves the target price impact. Args: market (AgentMarket): The market to calculate the bet amount for. kelly_bet (SimpleBet): The Kelly bet object containing direction and size. fee (float): The market fee. Returns: float: The optimal bet amount that achieves the target price impact. Raises: ValueError: If the optimization fails to converge. """ if not market.outcome_token_pool: logger.warning("Market outcome_token_pool is None, cannot calculate bet amount") return kelly_bet.size yes_outcome_pool_size = market.outcome_token_pool[market.get_outcome_str_from_bool(True)] no_outcome_pool_size = market.outcome_token_pool[market.get_outcome_str_from_bool(False)] result = minimize_scalar( self._calculate_price_impact_deviation, args=(kelly_bet, yes_outcome_pool_size, no_outcome_pool_size, fee), bounds=(0, 10 * (yes_outcome_pool_size + no_outcome_pool_size)), method="bounded", tol=1e-11, options={"maxiter": 10000}, ) if not result.success: raise ValueError(f"Failed to find optimal bet amount: {result.message}") return float(result.x) def _calculate_price_impact_deviation( self, bet_amount: float, kelly_bet: SimpleBet, yes_outcome_pool_size: float, no_outcome_pool_size: float, fee: float, ) -> float: price_impact = self.calculate_price_impact_for_bet_amount( kelly_bet.direction, bet_amount, yes_outcome_pool_size, no_outcome_pool_size, fee, ) max_price_impact = check_not_none(self.max_price_impact) return abs(price_impact - max_price_impact)
Line range hint
1-291
: Overall assessment: Significant enhancement to KellyBettingStrategyThe changes introduce price impact considerations to the KellyBettingStrategy, which is a valuable improvement. The implementation is generally well-structured and efficient, using numerical optimization techniques to calculate optimal bet amounts.
Key improvements:
- Addition of
max_price_impact
parameter for configurable price impact limits.- New methods for calculating and asserting price impacts.
- Adjustment of bet sizes based on price impact constraints.
While the implementation is sound, consider the following general suggestions:
- Improve error handling and logging throughout the new methods.
- Add comprehensive unit tests for the new functionality, especially edge cases.
- Consider adding more detailed documentation, including examples of how to use the new price impact features.
To further enhance the strategy's robustness and flexibility, consider:
- Implementing a factory method or configuration system to easily create different variants of the KellyBettingStrategy with various price impact settings.
- Exploring the possibility of dynamically adjusting the
max_price_impact
based on market conditions or historical data.- Implementing a simulation framework to test the strategy's performance under various market scenarios and price impact settings.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (2)
poetry.lock
is excluded by!**/*.lock
,!**/*.lock
pyproject.toml
is excluded by!**/*.toml
📒 Files selected for processing (1)
- prediction_market_agent_tooling/deploy/betting_strategy.py (5 hunks)
🔇 Additional comments (2)
prediction_market_agent_tooling/deploy/betting_strategy.py (2)
3-4
: LGTM: New imports for numerical operations.The addition of numpy and scipy.optimize.minimize_scalar is appropriate for the new price impact calculations implemented in the
KellyBettingStrategy
class.
291-291
: LGTM: Updated string representation.The
__repr__
method now includes themax_price_impact
parameter, providing a more complete representation of the strategy's configuration.
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.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (8)
tests_integration/markets/omen/test_kelly.py (5)
16-23
: LGTM: Well-documented test case for price impact calculation.The test case is clear and references the Gnosis documentation, which is excellent for traceability. The use of assert_price_impact is appropriate for verifying the calculation.
Consider adding a brief comment explaining the expected outcome of this test case to enhance readability.
26-34
: LGTM: Consistent follow-up test case for price impact calculation.This test case logically follows the previous one and continues to reference the Gnosis documentation. The use of assert_price_impact is consistent with the previous test.
For consistency with the previous test, consider adding a brief comment explaining the expected outcome of this specific scenario.
37-50
: LGTM: Well-structured parameterized test for large pool price impact.The use of pytest.mark.parametrize is excellent for testing multiple scenarios efficiently. The test appropriately retrieves a large market for realistic testing.
Consider the following improvements:
- Add error handling for potential exceptions from OmenSubgraphHandler.get_omen_binary_markets_simple().
- Include a brief comment explaining the purpose of testing with a large pool and the expected outcomes for different parameter combinations.
69-108
: LGTM: Well-structured helper function for price impact convergence.The function effectively calculates and asserts the convergence of price impact. The use of np.isclose for floating-point comparison is appropriate.
Consider the following improvements:
- Add error handling for potential exceptions from external function calls (e.g., get_kelly_bet_full, calculate_bet_amount_for_price_impact).
- Consider adding a docstring to explain the function's purpose and parameters.
- The tolerance in the assertion (0.001 * max_price_impact) might be too strict for some cases. Consider making it a parameter or using a relative tolerance instead.
111-135
: LGTM: Well-implemented helper function for price impact assertion.The function effectively calculates and asserts the correctness of price impact for both buy and sell directions. The logic is clear and the use of np.isclose for comparison is appropriate.
Consider the following improvements:
- Remove the print statement at the end of the function (line 135) as it's not necessary for a test function and might clutter the test output.
- Add a docstring to explain the function's purpose and parameters.
- Consider using a constant for the relative tolerance in np.isclose (currently 0.01) to make it easier to adjust if needed.
prediction_market_agent_tooling/deploy/betting_strategy.py (2)
145-147
: LGTM: Newmax_price_impact
parameter addedThe addition of the
max_price_impact
parameter with a default value ofNone
is a good improvement. It allows for more flexible betting strategies while maintaining backward compatibility.Consider adding a docstring to explain the purpose and usage of the
max_price_impact
parameter.
215-257
: New method for calculating bet amount based on price impact is well-implementedThe
calculate_bet_amount_for_price_impact
method is a good addition, using numerical optimization to find the bet amount that achieves the target price impact.Consider the following improvements:
- Add a docstring explaining the purpose and parameters of the method.
- Add a comment explaining the rationale behind the chosen optimization bounds.
- Consider making the bounds more flexible or configurable, especially for markets with very large or very small liquidity pools.
Example docstring:
def calculate_bet_amount_for_price_impact( self, market: AgentMarket, kelly_bet: SimpleBet, fee: float, ) -> float: """ Calculate the optimal bet amount that achieves the target price impact. Args: market (AgentMarket): The market to calculate the bet amount for. kelly_bet (SimpleBet): The Kelly bet object containing direction and size. fee (float): The market fee. Returns: float: The optimal bet amount that achieves the target price impact. """prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py (1)
322-331
: Summary: New liquidity-based sorting options added.The changes introduce new sorting options for
HIGHEST_LIQUIDITY
andLOWEST_LIQUIDITY
in the_build_sort_params
method. These additions enhance the functionality of the Omen subgraph handler by allowing markets to be sorted based on their liquidity.To ensure these changes are fully integrated:
- Verify that the
get_omen_binary_markets_simple
method properly handles these new sorting options.- Update any relevant documentation or API references to include these new sorting options.
- Consider adding unit tests to verify the behavior of these new sorting options.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (4)
- prediction_market_agent_tooling/deploy/betting_strategy.py (5 hunks)
- prediction_market_agent_tooling/markets/agent_market.py (1 hunks)
- prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py (1 hunks)
- tests_integration/markets/omen/test_kelly.py (1 hunks)
🔇 Additional comments (8)
tests_integration/markets/omen/test_kelly.py (2)
1-14
: LGTM: Import statements are well-organized and appropriate.The import statements are logically organized and include all necessary modules for testing the KellyBettingStrategy. Good job on following the import order convention (standard library, third-party, local).
1-135
: Overall: Well-structured test file with room for minor improvementsThis test file for the KellyBettingStrategy is generally well-organized and covers various scenarios for price impact calculations. The use of parameterized tests and helper functions promotes code reuse and maintainability.
Key points for improvement:
- Address the inconsistency in the test_kelly_price_impact_works_small_pool function.
- Add error handling for potential exceptions from external API calls and function invocations.
- Enhance documentation with docstrings for helper functions and brief comments explaining expected outcomes for test cases.
- Remove unnecessary print statements and consider parameterizing tolerance values for easier adjustment.
Addressing these points will further improve the robustness and clarity of the tests.
prediction_market_agent_tooling/markets/agent_market.py (2)
Line range hint
1-32
: Overall assessment: Changes look good, but seem to be part of a larger implementation.The additions to the
SortBy
enum are well-implemented and consistent with the existing code. However, these changes alone don't fully implement themax_price_impact
parameter mentioned in the PR objectives. It would be helpful to see the complete set of changes across all affected files to fully understand how this enhancement to the Kelly betting strategy is being implemented.To get a better understanding of the full scope of changes, please run the following script:
#!/bin/bash # Description: List all modified files in this PR and show a summary of changes # List all modified files echo "Modified files in this PR:" git diff --name-only origin/main # Show a summary of changes for each file echo "\nSummary of changes:" git diff --stat origin/mainThis will help reviewers understand the full context of the changes and how they relate to the PR objectives.
31-32
: LGTM! Consider adding documentation for the new sorting options.The addition of
HIGHEST_LIQUIDITY
andLOWEST_LIQUIDITY
to theSortBy
enum is a good enhancement. These new sorting options align well with the PR's objective of improving the Kelly betting strategy by considering market conditions.Consider adding a brief comment above the
SortBy
class to explain the purpose of these sorting options, especially the new liquidity-based ones. This would help other developers understand the intent and usage of these options.To ensure these changes are properly integrated, please run the following script to check for any usage of
SortBy
that might need updating:✅ Verification successful
Verification Successful
All usages of the
SortBy
enum, including the newHIGHEST_LIQUIDITY
andLOWEST_LIQUIDITY
values, have been reviewed and integrated correctly across the codebase.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for usage of SortBy enum and potential areas that need updating # Search for SortBy usage echo "Searching for SortBy usage:" rg --type python "SortBy\." -A 5 # Search for potential switch statements or if-else blocks that might need updating echo "\nSearching for potential switch statements or if-else blocks using SortBy:" rg --type python "if.*SortBy\..*:.*elif.*SortBy\." -A 10Length of output: 1588
Script:
#!/bin/bash # Description: Check for usage of SortBy enum and potential areas that need updating # Search for SortBy usage echo "Searching for SortBy usage:" rg --type python "SortBy\." -A 5 # Search for potential switch statements or if-else blocks using SortBy echo -e "\nSearching for potential switch statements or if-else blocks using SortBy:" rg --type python "if\s+.*SortBy\..*:" -A 10Length of output: 370
Script:
#!/bin/bash # Description: Check for usage of SortBy enum and potential areas that need updating # Search for SortBy usage echo "Searching for SortBy usage:" rg --type py "SortBy\." -A 5 # Search for potential if-else blocks using SortBy echo -e "\nSearching for potential if-else blocks using SortBy:" rg --type py "if\s+.*SortBy\..*:" -A 10Length of output: 23556
prediction_market_agent_tooling/deploy/betting_strategy.py (3)
3-6
: New imports added for price impact calculationsThe new imports (
minimize_scalar
,xDai
, andlogger
) are appropriate for the added functionality. Theminimize_scalar
function from SciPy will be used for optimizing the bet amount based on price impact.
260-260
: LGTM: Updated__repr__
methodThe
__repr__
method has been correctly updated to include themax_price_impact
parameter in the string representation of theKellyBettingStrategy
object.
198-213
:⚠️ Potential issueNew method for calculating price impact looks good
The
calculate_price_impact_for_bet_amount
method is well-implemented and correctly calculates the price impact for a given bet amount.However, the comment "price_impact should always be > 0" on line 211 is not always true. Price impact can be negative if the actual price is lower than the expected price. Consider updating the comment to reflect this possibility:
-# price_impact should always be > 0 +# Note: price_impact can be positive or negative depending on market conditionsLikely invalid or redundant comment.
prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py (1)
322-331
: New sorting options added for market liquidity.The changes introduce two new sorting options:
HIGHEST_LIQUIDITY
andLOWEST_LIQUIDITY
. These additions enhance the flexibility of the market querying functionality, allowing users to sort markets based on their liquidity.A few observations:
- The implementation is consistent with the existing pattern.
- The new options use the
liquidityMeasure
field, which is appropriate for sorting by liquidity.- The changes don't break existing functionality.
No description provided.