From ecbbf8c53ad94ba453b82ab28490821c2495e7a8 Mon Sep 17 00:00:00 2001 From: Mihai Date: Wed, 19 Jul 2023 13:30:38 -0400 Subject: [PATCH 1/2] remove BotConfig, switch to EnvironmentConfig --- elfpy/bots/__init__.py | 1 - elfpy/bots/bot_config.py | 81 ------------------- ...lt_config.py => create_default_profile.py} | 4 +- 3 files changed, 2 insertions(+), 84 deletions(-) delete mode 100644 elfpy/bots/bot_config.py rename elfpy/bots/{bots_default_config.py => create_default_profile.py} (77%) diff --git a/elfpy/bots/__init__.py b/elfpy/bots/__init__.py index 2bb112b6a1..cd4fab0fa8 100644 --- a/elfpy/bots/__init__.py +++ b/elfpy/bots/__init__.py @@ -1,6 +1,5 @@ """Utilities and classes for Agent.0 bots""" -from .bot_config import BotConfig from .bot_info import BotInfo from .budget import Budget from .environment_config import DEFAULT_USERNAME, EnvironmentConfig diff --git a/elfpy/bots/bot_config.py b/elfpy/bots/bot_config.py deleted file mode 100644 index 8c2b1c2229..0000000000 --- a/elfpy/bots/bot_config.py +++ /dev/null @@ -1,81 +0,0 @@ -"""State object for setting experiment configuration""" -from __future__ import annotations - -import json -from dataclasses import dataclass, field -from typing import Any - -from elfpy import DEFAULT_LOG_LEVEL, DEFAULT_LOG_MAXBYTES, types -from elfpy.utils import json as output_utils - -DEFAULT_USERNAME = "changeme" - - -@types.freezable(frozen=False, no_new_attribs=True) -@dataclass -class BotConfig(types.FrozenClass): - """Parameters that can be set either locally or passed from docker.""" - - # lots of configs! - # pylint: disable=too-many-instance-attributes - - # Logical username for who is running bots - username: str = DEFAULT_USERNAME - # whether to run on alchemy - alchemy: bool = False - # url for retrieving the contract artifacts - artifacts_url: str = "http://localhost:80" - # whether to run on devnet - devnet: bool = True - # if true, stop executing when trade errors occur - halt_on_errors: bool = False - # optional output filename for logging - log_filename: str = "agent0-bots" - # log level; should be in [logging.DEBUG, logging.INFO, logging.WARNING] - log_level: int = DEFAULT_LOG_LEVEL # INFO - # delete_previous_logs; if True, delete existing logs at the start of the run - delete_previous_logs: bool = False - # log log_file_and_stdout; if True, save to file and write to stdout, else just save to file - log_file_and_stdout: bool = False - # log_formatter; specifies the format in which the logger saves the logs - # see https://docs.python.org/3/library/logging.html#logrecord-attributes for which attributes can be used - log_formatter: str = "\n%(asctime)s: %(levelname)s: %(module)s.%(funcName)s:\n%(message)s" - # maximum log file output size, in bytes - max_bytes: int = DEFAULT_LOG_MAXBYTES # int(2e6) or 2MB - # location of RPC - rpc_url: str = "http://localhost:8545" - # chance for a bot to execute a trade - trade_chance: float = 0.1 - # int to be used for the random seed - random_seed: int = 1 - # risk_threshold has different interpretations for different bots. - # In general the bot will be more risk averse as it grows to infinity. - # A value of 0 will usually disable it. - risk_threshold: float = 0.0 - # scratch space for any application-specific & extraneous parameters - scratch: dict[Any, Any] = field(default_factory=dict) - - def __getitem__(self, attrib) -> None: - return getattr(self, attrib) - - def __setitem__(self, attrib, value) -> None: - self.__setattr__(attrib, value) - - def __str__(self) -> str: - # cls arg tells json how to handle numpy objects and nested dataclasses - return json.dumps(self.__dict__, sort_keys=True, indent=2, cls=output_utils.ExtendedJSONEncoder) - - def copy(self) -> BotConfig: - """Returns a new copy of self""" - return BotConfig(**{key: value for key, value in self.__dict__.items() if key not in ["rng"]}) - - def load_from_json(self, json_file_location: str) -> None: - """Load configuration settings from a JSON file and update self""" - with open(json_file_location, mode="r", encoding="UTF-8") as file: - json_config = json.load(file) - self.__dict__.update(**json_config) - - def save_as_json(self, json_file_location: str) -> None: - """Save configuration settings in JSON format""" - with open(json_file_location, mode="w", encoding="UTF-8") as file: - json.dump(self.__dict__, file, sort_keys=True, indent=2, cls=output_utils.ExtendedJSONEncoder) diff --git a/elfpy/bots/bots_default_config.py b/elfpy/bots/create_default_profile.py similarity index 77% rename from elfpy/bots/bots_default_config.py rename to elfpy/bots/create_default_profile.py index 01f24b7fca..5419c3acbf 100644 --- a/elfpy/bots/bots_default_config.py +++ b/elfpy/bots/create_default_profile.py @@ -1,9 +1,9 @@ """Example script for writing a custom bot config to json""" -from elfpy.bots import DEFAULT_USERNAME, BotConfig +from elfpy.bots import DEFAULT_USERNAME, EnvironmentConfig if __name__ == "__main__": # load the config file, which loads defaults - config = BotConfig() + config = EnvironmentConfig() # Add username here if adjusting configurations in this script config.username = DEFAULT_USERNAME From 8696045cbdf60fd30a022f9db6d6b37d1ed8578b Mon Sep 17 00:00:00 2001 From: Mihai Date: Wed, 19 Jul 2023 13:57:13 -0400 Subject: [PATCH 2/2] add back defaults for trade_chance and risk_threshold --- elfpy/bots/environment_config.py | 6 ++++++ examples/evm_bots.py | 14 ++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/elfpy/bots/environment_config.py b/elfpy/bots/environment_config.py index b665038e60..fa6f7a6a54 100644 --- a/elfpy/bots/environment_config.py +++ b/elfpy/bots/environment_config.py @@ -44,6 +44,12 @@ class EnvironmentConfig(types.FrozenClass): max_bytes: int = DEFAULT_LOG_MAXBYTES # int(2e6) or 2MB # location of RPC rpc_url: str = "http://localhost:8545" + # chance for a bot to execute a trade (used if unspecified at the bot level). + default_trade_chance: float = 0.1 + # risk_threshold has different interpretations for different bots (used if unspecified at the bot level). + # In general the bot will be more risk averse as it grows to infinity. + # A value of 0 will usually disable it. + default_risk_threshold: float = 0.0 # int to be used for the random seed random_seed: int = 1 # abi filenames diff --git a/examples/evm_bots.py b/examples/evm_bots.py index 0b12485213..4bacde6e80 100644 --- a/examples/evm_bots.py +++ b/examples/evm_bots.py @@ -152,7 +152,7 @@ def create_agent( # pylint: disable=too-many-arguments assert bot.index is not None, "Bot must have an index." assert isinstance(bot.policy, type(Agent)), "Bot must have a policy of type Agent." - params = {"trade_chance": FixedPoint(bot_config.trade_chance), "budget": bot.budget.sample_budget(rng)} + params = {"trade_chance": FixedPoint(bot.trade_chance), "budget": bot.budget.sample_budget(rng)} params["rng"] = rng if bot.risk_threshold and bot.name != "random": # random agent doesn't use risk threshold params["risk_threshold"] = FixedPoint(bot.risk_threshold) # if risk threshold is manually set, we use it @@ -588,13 +588,19 @@ def main( if "num_random" not in bot_config.scratch: bot_config.scratch["num_random"]: int = 1 bot_config.scratch["louie"] = BotInfo( - policy=LongLouie, trade_chance=bot_config.trade_chance, risk_threshold=bot_config.risk_threshold + policy=LongLouie, + trade_chance=bot_config.default_trade_chance, + risk_threshold=bot_config.default_risk_threshold, ) bot_config.scratch["sally"] = BotInfo( - policy=ShortSally, trade_chance=bot_config.trade_chance, risk_threshold=bot_config.risk_threshold + policy=ShortSally, + trade_chance=bot_config.default_trade_chance, + risk_threshold=bot_config.default_risk_threshold, ) bot_config.scratch["random"] = BotInfo( - policy=RandomAgent, trade_chance=bot_config.trade_chance, risk_threshold=bot_config.risk_threshold + policy=RandomAgent, + trade_chance=bot_config.default_trade_chance, + risk_threshold=bot_config.default_risk_threshold, ) bot_config.scratch["bot_names"] = {"louie", "sally", "random"} # hard-code goerli addresses