Skip to content
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

Compare trading vs prediction accuracy #544

Merged
merged 1 commit into from
Nov 5, 2024
Merged

Conversation

kongzii
Copy link
Contributor

@kongzii kongzii commented Nov 4, 2024

No description provided.

Copy link

coderabbitai bot commented Nov 4, 2024

Walkthrough

This pull request introduces several modifications across multiple files within the prediction_market_agent_tooling module. Key changes include the addition of a new constant BPS_CONSTANT and new properties in the ContractPrediction class, which enhance its functionality. The OmenBet class's transactionHash field is updated to a different data type. A new method is added to the OmenSubgraphHandler class to retrieve agent results for specific bets. Additionally, a new script is introduced to evaluate the accuracy of bets in a prediction market.

Changes

File Change Summary
prediction_market_agent_tooling/markets/omen/data_models.py - Added constant BPS_CONSTANT.
- Added properties estimated_probability and boolean_outcome in ContractPrediction.
- Updated transactionHash type from HexAddress to HexBytes in OmenBet.
prediction_market_agent_tooling/tools/utils.py - Added constant BPS_CONSTANT = 10000.
prediction_market_agent_tooling/markets/omen/omen.py - Added constant BPS_CONSTANT.
- Updated logic in store_trades method to use BPS_CONSTANT instead of a hardcoded value.
prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py - Added method get_agent_results_for_bet to retrieve agent results for a specific OmenBet.
scripts/compare_trading_vs_prediction_accuracy.py - Introduced script to evaluate accuracy of bets in a prediction market with a main function.

Possibly related PRs

Suggested reviewers

  • evangriffiths

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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a 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 (6)
scripts/compare_trading_vs_prediction_accuracy.py (4)

1-6: Consider adding type hints and remove extra blank line.

Consider importing typing related utilities for better type safety. Also, there's an unnecessary extra blank line.

 import typer
 from web3 import Web3
+from typing import List, Optional
 
 from prediction_market_agent_tooling.markets.omen.omen import OmenSubgraphHandler
-

7-9: Add input validation and documentation.

The function would benefit from input validation and documentation explaining its purpose and parameters.

 def main(public_key: str) -> None:
+    """Compare trading and prediction accuracy for a given Ethereum address.
+
+    Args:
+        public_key: Ethereum address in hex format
+
+    Raises:
+        ValueError: If the public_key is not a valid Ethereum address
+    """
+    if not Web3.is_address(public_key):
+        raise ValueError(f"Invalid Ethereum address: {public_key}")
+
     public_key_checksummed = Web3.to_checksum_address(public_key)

34-40: Enhance results reporting and add data persistence.

The current output format could be improved with more detailed statistics and structured output options (e.g., JSON, CSV).

-    print("N bets:", len(all_bets))
-    print("Bet accuracy:", len(correct_bets) / len(all_bets) if all_bets else None)
-    print(
-        "Prediction accuracy:",
-        len(correct_results) / len(all_bets_with_results) if all_bets else None,
-    )
-    print("N bets without results:", len(all_bets_without_results))
+    import json
+    from datetime import datetime
+    
+    results = {
+        "timestamp": datetime.utcnow().isoformat(),
+        "address": public_key_checksummed,
+        "statistics": {
+            "total_bets": len(all_bets),
+            "bet_accuracy": len(correct_bets) / len(all_bets) if all_bets else None,
+            "prediction_accuracy": len(correct_results) / len(all_bets_with_results) if all_bets_with_results else None,
+            "bets_without_results": len(all_bets_without_results),
+            "total_bets_with_results": len(all_bets_with_results),
+        }
+    }
+    
+    # Print human-readable format
+    print(json.dumps(results, indent=2))
+    
+    # Optionally save to file
+    output_file = f"accuracy_report_{public_key_checksummed}_{datetime.utcnow().strftime('%Y%m%d_%H%M%S')}.json"
+    with open(output_file, 'w') as f:
+        json.dump(results, f, indent=2)

43-44: Enhance CLI with additional options and documentation.

The CLI could be improved with better documentation and additional options for output format and verbosity.

+def version_callback(value: bool):
+    if value:
+        print(f"Prediction Market Analysis Tool v1.0.0")
+        raise typer.Exit()
+
 if __name__ == "__main__":
-    typer.run(main)
+    app = typer.Typer(help="Analyze prediction market trading and accuracy.")
+    
+    @app.command()
+    def analyze(
+        public_key: str = typer.Argument(..., help="Ethereum address to analyze"),
+        output_format: str = typer.Option("text", "--format", "-f", help="Output format: text/json/csv"),
+        verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose logging"),
+        version: bool = typer.Option(False, "--version", callback=version_callback, help="Show version"),
+    ):
+        """Analyze trading and prediction accuracy for a given address."""
+        if verbose:
+            logging.basicConfig(level=logging.INFO)
+        main(public_key)
+    
+    app()
prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py (1)

912-924: Implementation looks good with room for optimization.

The method correctly retrieves and filters agent results for a specific bet. The error handling is appropriate, raising a clear error message for multiple results and returning None when no results are found.

Consider adding a query parameter for transaction hash in the subgraph schema to optimize the filtering process, as the current implementation fetches all market results before filtering in memory.

prediction_market_agent_tooling/markets/omen/omen.py (1)

452-452: LGTM! Consider adding a comment for clarity.

Good refactoring to replace the magic number with BPS_CONSTANT. This improves maintainability and consistency.

Consider adding a brief comment explaining the BPS (basis points) conversion:

+            # Convert probability to basis points (1 BPS = 0.01%)
             estimated_probability_bps=int(traded_market.answer.p_yes * BPS_CONSTANT),
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a50b00f and 7e693bc.

📒 Files selected for processing (5)
  • prediction_market_agent_tooling/markets/omen/data_models.py (3 hunks)
  • prediction_market_agent_tooling/markets/omen/omen.py (2 hunks)
  • prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py (1 hunks)
  • prediction_market_agent_tooling/tools/utils.py (1 hunks)
  • scripts/compare_trading_vs_prediction_accuracy.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • prediction_market_agent_tooling/tools/utils.py
🧰 Additional context used
📓 Learnings (1)
prediction_market_agent_tooling/markets/omen/omen_subgraph_handler.py (2)
Learnt from: evangriffiths
PR: gnosis/prediction-market-agent-tooling#300
File: prediction_market_agent_tooling/markets/omen/omen.py:344-352
Timestamp: 2024-10-08T17:30:32.487Z
Learning: The `get_resolved_bets_made_since` method in the `OmenAgentMarket` class should include an `end_time` argument to make it more flexible.
Learnt from: evangriffiths
PR: gnosis/prediction-market-agent-tooling#300
File: prediction_market_agent_tooling/markets/omen/omen.py:344-352
Timestamp: 2024-07-08T07:05:58.507Z
Learning: The `get_resolved_bets_made_since` method in the `OmenAgentMarket` class should include an `end_time` argument to make it more flexible.
🔇 Additional comments (4)
prediction_market_agent_tooling/markets/omen/data_models.py (3)

27-27: LGTM: BPS_CONSTANT import added for probability calculations.

The import is correctly placed and will be used for probability calculations in the ContractPrediction class.


789-796: LGTM: New properties added to ContractPrediction.

The new properties enhance the ContractPrediction class with:

  1. estimated_probability: Correctly converts BPS to probability using BPS_CONSTANT
  2. boolean_outcome: Provides a clear boolean interpretation of the probability

The implementation is clean and follows best practices.


506-506: Verify the impact of changing transactionHash type.

The type change from HexAddress to HexBytes is logically correct as transaction hashes are typically represented as bytes. However, we should verify that all consumers of this field handle the new type correctly.

✅ Verification successful

Let me generate additional scripts to verify the type handling in the codebase.


Based on the analysis of the codebase, I can now provide the final response:

The type change from HexAddress to HexBytes is safe and properly handled.

The codebase shows consistent handling of transactionHash as HexBytes:

  • All usages of transactionHash in transaction receipts are properly handled by calling .hex() when needed for string representation
  • The HexBytes type is properly imported and used throughout the codebase
  • No direct dependencies rely on the old HexAddress type for transactionHash
  • The type change aligns with Web3's transaction hash representation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usages of OmenBet.transactionHash to verify type compatibility
rg -l "OmenBet.*transactionHash|transactionHash.*OmenBet" | xargs rg -A 5 "transactionHash"

Length of output: 5318


Script:

#!/bin/bash
# Search for HexBytes imports and usage
rg "HexBytes" -A 2

# Search for type conversion or hex-related operations on transactionHash
rg "transactionHash.*hex|hex.*transactionHash"

# Search for any error handling or type checking related to transaction hashes
ast-grep --pattern 'try {
  $$$
  transactionHash
  $$$
}'

Length of output: 38060

prediction_market_agent_tooling/markets/omen/omen.py (1)

81-81: LGTM!

The import of BPS_CONSTANT is correctly placed and follows the project's import organization.

Comment on lines +22 to +33
all_bets_with_results = []
all_bets_without_results = []
correct_results = []
for bet in all_bets:
result = OmenSubgraphHandler().get_agent_results_for_bet(bet)
if result is None:
all_bets_without_results.append(bet)
continue
all_bets_with_results.append(bet)
if result.boolean_outcome == bet.fpmm.boolean_outcome:
correct_results.append(result)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Optimize performance with batch processing.

The sequential processing of results could be slow for large datasets. Consider implementing batch processing and adding progress tracking.

+    from tqdm import tqdm
+    from concurrent.futures import ThreadPoolExecutor, as_completed
+
     all_bets_with_results = []
     all_bets_without_results = []
     correct_results = []
-    for bet in all_bets:
-        result = OmenSubgraphHandler().get_agent_results_for_bet(bet)
-        if result is None:
-            all_bets_without_results.append(bet)
-            continue
-        all_bets_with_results.append(bet)
-        if result.boolean_outcome == bet.fpmm.boolean_outcome:
-            correct_results.append(result)
+    
+    handler = OmenSubgraphHandler()
+    
+    def process_bet(bet):
+        return bet, handler.get_agent_results_for_bet(bet)
+    
+    with ThreadPoolExecutor(max_workers=10) as executor:
+        futures = [executor.submit(process_bet, bet) for bet in all_bets]
+        for future in tqdm(as_completed(futures), total=len(all_bets), desc="Processing bets"):
+            bet, result = future.result()
+            if result is None:
+                all_bets_without_results.append(bet)
+                continue
+            all_bets_with_results.append(bet)
+            if result.boolean_outcome == bet.fpmm.boolean_outcome:
+                correct_results.append(result)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
all_bets_with_results = []
all_bets_without_results = []
correct_results = []
for bet in all_bets:
result = OmenSubgraphHandler().get_agent_results_for_bet(bet)
if result is None:
all_bets_without_results.append(bet)
continue
all_bets_with_results.append(bet)
if result.boolean_outcome == bet.fpmm.boolean_outcome:
correct_results.append(result)
from tqdm import tqdm
from concurrent.futures import ThreadPoolExecutor, as_completed
all_bets_with_results = []
all_bets_without_results = []
correct_results = []
handler = OmenSubgraphHandler()
def process_bet(bet):
return bet, handler.get_agent_results_for_bet(bet)
with ThreadPoolExecutor(max_workers=10) as executor:
futures = [executor.submit(process_bet, bet) for bet in all_bets]
for future in tqdm(as_completed(futures), total=len(all_bets), desc="Processing bets"):
bet, result = future.result()
if result is None:
all_bets_without_results.append(bet)
continue
all_bets_with_results.append(bet)
if result.boolean_outcome == bet.fpmm.boolean_outcome:
correct_results.append(result)

Comment on lines +10 to +20
all_bets = [
bet
for bet in OmenSubgraphHandler().get_bets(
better_address=public_key_checksummed,
filter_by_answer_finalized_not_null=True,
)
if bet.fpmm.is_resolved_with_valid_answer
]
correct_bets = [
bet for bet in all_bets if bet.boolean_outcome == bet.fpmm.boolean_outcome
]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling and logging.

The bet retrieval logic needs error handling for API calls and would benefit from progress logging, especially for large datasets.

+    import logging
+    logger = logging.getLogger(__name__)
+    
+    try:
+        logger.info(f"Retrieving bets for address {public_key_checksummed}")
         all_bets = [
             bet
             for bet in OmenSubgraphHandler().get_bets(
                 better_address=public_key_checksummed,
                 filter_by_answer_finalized_not_null=True,
             )
             if bet.fpmm.is_resolved_with_valid_answer
         ]
+        logger.info(f"Retrieved {len(all_bets)} bets")
+    except Exception as e:
+        logger.error(f"Failed to retrieve bets: {e}")
+        raise

Committable suggestion skipped: line range outside the PR's diff.

@evangriffiths evangriffiths self-requested a review November 4, 2024 16:50
@kongzii kongzii merged commit 5ec97e3 into main Nov 5, 2024
14 checks passed
@kongzii kongzii deleted the peter/result-for-bet branch November 5, 2024 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants