diff --git a/prediction_market_agent_tooling/markets/data_models.py b/prediction_market_agent_tooling/markets/data_models.py index 6cb30db1..fb4cb559 100644 --- a/prediction_market_agent_tooling/markets/data_models.py +++ b/prediction_market_agent_tooling/markets/data_models.py @@ -6,6 +6,7 @@ from pydantic import BaseModel from web3 import Web3 +from prediction_market_agent_tooling.benchmark.utils import should_not_happen from prediction_market_agent_tooling.gtypes import ( USD, ChecksumAddress, @@ -23,6 +24,12 @@ class Currency(str, Enum): Mana = "Mana" +class Resolution(str, Enum): + YES = "YES" + NO = "NO" + CANCEL = "CANCEL" + + class BetAmount(BaseModel): amount: Decimal currency: Currency @@ -184,6 +191,16 @@ def to_agent_market(self) -> "AgentMarket": original_market=self, ) + def get_resolution_enum(self) -> Resolution: + return Resolution(self.resolution) + + def is_resolved_non_cancelled(self) -> bool: + return ( + self.isResolved + and self.resolutionTime is not None + and self.get_resolution_enum() != Resolution.CANCEL + ) + def __repr__(self) -> str: return f"Manifold's market: {self.question}" @@ -235,6 +252,9 @@ class ManifoldBetFees(BaseModel): liquidityFee: Decimal creatorFee: Decimal + def get_total(self) -> Decimal: + return Decimal(sum([self.platformFee, self.liquidityFee, self.creatorFee])) + class ManifoldBet(BaseModel): """ @@ -257,6 +277,27 @@ class ManifoldBet(BaseModel): createdTime: datetime outcome: str + def get_resolved_boolean_outcome(self) -> bool: + outcome = Resolution(self.outcome) + if outcome == Resolution.YES: + return True + elif outcome == Resolution.NO: + return False + else: + should_not_happen(f"Unexpected bet outcome string, '{outcome.value}'.") + + def get_profit(self, market_outcome: bool) -> ProfitAmount: + profit = ( + self.shares - self.amount + if self.get_resolved_boolean_outcome() == market_outcome + else -self.amount + ) + profit -= self.fees.get_total() + return ProfitAmount( + amount=profit, + currency=Currency.Mana, + ) + class ManifoldContractMetric(BaseModel): """ diff --git a/prediction_market_agent_tooling/markets/manifold.py b/prediction_market_agent_tooling/markets/manifold.py index c5783a21..e1ac3602 100644 --- a/prediction_market_agent_tooling/markets/manifold.py +++ b/prediction_market_agent_tooling/markets/manifold.py @@ -12,7 +12,7 @@ ManifoldContractMetric, ManifoldMarket, ManifoldUser, - ProfitAmount, + Resolution, ResolvedBet, ) @@ -113,30 +113,28 @@ def get_resolved_manifold_bets( bets = [b for b in bets if b.createdTime >= start_time] if end_time: bets = [b for b in bets if b.createdTime < end_time] - bets = [b for b in bets if get_manifold_market(b.contractId).isResolved] + bets = [ + b for b in bets if get_manifold_market(b.contractId).is_resolved_non_cancelled() + ] return bets def manifold_to_generic_resolved_bet(bet: ManifoldBet) -> ResolvedBet: market = get_manifold_market(bet.contractId) - if not market.isResolved: + if not market.is_resolved_non_cancelled(): raise ValueError(f"Market {market.id} is not resolved.") if not market.resolutionTime: raise ValueError(f"Market {market.id} has no resolution time.") - # Get the profit for this bet from the corresponding position - positions = get_market_positions(market.id, bet.userId) - bet_position = next(p for p in positions if p.contractId == bet.contractId) - profit = bet_position.profit - + market_outcome = market.get_resolution_enum() == Resolution.YES return ResolvedBet( amount=BetAmount(amount=bet.amount, currency=Currency.Mana), - outcome=bet.outcome == "YES", + outcome=bet.get_resolved_boolean_outcome(), created_time=bet.createdTime, market_question=market.question, - market_outcome=market.resolution == "YES", + market_outcome=market_outcome, resolved_time=market.resolutionTime, - profit=ProfitAmount(amount=profit, currency=Currency.Mana), + profit=bet.get_profit(market_outcome=market_outcome), )