Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Ravleen-Solulab committed Oct 17, 2024
1 parent a55f0af commit eb475e5
Showing 1 changed file with 35 additions and 22 deletions.
57 changes: 35 additions & 22 deletions packages/valory/skills/decision_maker_abci/behaviours/sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# ------------------------------------------------------------------------------

"""This module contains the behaviour for sampling a bet."""

from typing import Generator, Iterator, List, Optional

from packages.valory.skills.decision_maker_abci.behaviours.base import (
Expand All @@ -39,54 +40,66 @@ class SamplingBehaviour(DecisionMakerBaseBehaviour):
@property
def available_bets(self) -> Iterator[Bet]:
"""Get an iterator of the unprocessed bets."""

# Note: the openingTimestamp is misleading as it is the closing timestamp of the bet
if self.params.using_kelly:
# Filter for bets closing within the next `sample_bets_closing_days`
# get only bets that close in the next 48 hours
self.bets = [
bet
for bet in self.bets
if bet.openingTimestamp <= (self.synced_timestamp + self.params.sample_bets_closing_days * UNIX_DAY)
if bet.openingTimestamp
<= (
self.synced_timestamp
+ self.params.sample_bets_closing_days * UNIX_DAY
)
]

# Filter for unprocessed and unskipped bets
return filter(lambda bet: bet.status in {BetStatus.UNPROCESSED}, self.bets)

def _is_profitable(self, bet: Bet) -> bool:
"""Determine if a bet is profitable."""
return bet.potential_net_profit > 0 and bet.scaledLiquidityMeasure > 0
return filter(lambda bet: bet.status == BetStatus.UNPROCESSED, self.bets)

def _sampled_bet_idx(self, bets: List[Bet]) -> int:
"""Sample a bet and return its index based on the highest liquidity."""
return self.bets.index(max(bets, key=lambda bet: bet.scaledLiquidityMeasure))
"""
Sample a bet and return its id.
The sampling logic is relatively simple at the moment.
It simply selects the unprocessed bet with the largest liquidity.
:param bets: the bets' values to compare for the sampling.
:return: the id of the sampled bet, out of all the available bets, not only the given ones.
"""
return self.bets.index(max(bets))

def _sample(self) -> Optional[int]:
"""Sample a bet, mark it as processed if profitable, and return its index."""
"""Sample a bet, mark it as processed, and return its index."""
available_bets = list(self.available_bets)

if len(available_bets) == 0:
self.context.logger.warning("No unprocessed bets available to sample from!")
msg = "There were no unprocessed bets available to sample from!"
self.context.logger.warning(msg)
return None

idx = self._sampled_bet_idx(available_bets)
sampled_bet = self.bets[idx]

if not self._is_profitable(sampled_bet):
# Mark unprofitable bets as skipped
sampled_bet.status = BetStatus.SKIPPED
self.context.logger.info(f"Skipped bet due to lack of profitability: {sampled_bet}")
if self.bets[idx].scaledLiquidityMeasure == 0:
msg = "There were no unprocessed bets with non-zero liquidity!"
self.context.logger.warning(msg)
return None

# Mark as processed if profitable
sampled_bet.status = BetStatus.PROCESSED
self.context.logger.info(f"Sampled profitable bet: {sampled_bet}")
# update the bet's status for the given id to `PROCESSED`
self.bets[idx].status = BetStatus.PROCESSED
msg = f"Sampled bet: {self.bets[idx]}"
self.context.logger.info(msg)
return idx

def async_act(self) -> Generator:
"""Perform the sampling action."""
"""Do the action."""
with self.context.benchmark_tool.measure(self.behaviour_id).local():
self.read_bets()
idx = self._sample()
self.store_bets()
bets_hash = self.hash_stored_bets() if idx is not None else None
if idx is None:
bets_hash = None
else:
bets_hash = self.hash_stored_bets()
payload = SamplingPayload(self.context.agent_address, bets_hash, idx)

yield from self.finish_behaviour(payload)

0 comments on commit eb475e5

Please sign in to comment.