Skip to content

Commit

Permalink
add gas price multiples (#1433)
Browse files Browse the repository at this point in the history
  • Loading branch information
wakamex authored Apr 27, 2024
1 parent 037f062 commit 7844425
Show file tree
Hide file tree
Showing 16 changed files with 592 additions and 156 deletions.
7 changes: 3 additions & 4 deletions examples/custom_policy.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
"""Custom policy example"""
"""Custom policy example."""

from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING

from fixedpointmath import FixedPoint

from agent0 import (
HyperdriveBasePolicy,
add_liquidity_trade,
Expand All @@ -17,6 +15,7 @@
redeem_withdraw_shares_trade,
remove_liquidity_trade,
)
from fixedpointmath import FixedPoint

if TYPE_CHECKING:
from agent0.core.base import Trade
Expand All @@ -27,7 +26,7 @@
# Build custom policy
# Simple agent, opens a set of all trades for a fixed amount and closes them after
class CustomCycleTradesPolicy(HyperdriveBasePolicy):
"""An agent that simply cycles through all trades"""
"""An agent that simply cycles through all trades."""

@dataclass(kw_only=True)
class Config(HyperdriveBasePolicy.Config):
Expand Down
10 changes: 10 additions & 0 deletions src/agent0/core/base/policies/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from fixedpointmath import FixedPoint
from numpy.random import default_rng

from agent0.core.base.types import freezable

if TYPE_CHECKING:
from numpy.random._generator import Generator

Expand All @@ -24,6 +26,7 @@ class BasePolicy(Generic[MarketInterface, Wallet]):

# Because we're inheriting from this config, we need to set
# kw_only so that we can mix and match defaults and non-defaults
@freezable(frozen=False, no_new_attribs=False)
@dataclass(kw_only=True)
class Config:
"""Config data class for policy specific configuration."""
Expand All @@ -34,6 +37,10 @@ class Config:
"""The experiment's stateful random number generator. Defaults to a spawn of the global rng."""
slippage_tolerance: FixedPoint | None = None
"""The slippage tolerance for trades. Defaults to None."""
base_fee_multiple: float | None = None
"""The base fee multiple for transactions. Defaults to None."""
priority_fee_multiple: float | None = None
"""The priority fee multiple for transactions. Defaults to None."""

def __init__(self, policy_config: Config):
"""Initialize the policy.
Expand All @@ -47,6 +54,9 @@ def __init__(self, policy_config: Config):
# overwriting the __init__ function. The downside is that users of this member variable
# can't be type checked. There's probably a way to do this with generics instead of Any.
self.config: Any = policy_config
# lock down the config so we can't change it by either modifying existing attribs or adding new ones
self.config.freeze() # type: ignore
self.config.disable_new_attribs() # type: ignore
self.slippage_tolerance = policy_config.slippage_tolerance
# Generate rng if not set in config
if policy_config.rng is None:
Expand Down
8 changes: 4 additions & 4 deletions src/agent0/core/base/types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Core types used across the repo"""
"""Core types used across the repo."""

from __future__ import annotations # types will be strings by default in 3.11

Expand Down Expand Up @@ -40,7 +40,7 @@ def dtypes(self):


def freezable(frozen: bool = False, no_new_attribs: bool = False):
"""A wrapper that allows classes to be frozen, such that existing member attributes cannot be changed.
"""Allow classes to be frozen, such that existing member attributes cannot be changed.
Arguments
---------
Expand All @@ -53,7 +53,7 @@ def freezable(frozen: bool = False, no_new_attribs: bool = False):
"""

def decorator(cls):
"""Decorator for the provided class.
"""Define decorator for the provided class.
Arguments
---------
Expand Down Expand Up @@ -139,7 +139,7 @@ def dtypes(self) -> dict[str, type]:


class TokenType(Enum):
r"""A type of token"""
r"""A type of token."""

BASE = "base"

Expand Down
51 changes: 29 additions & 22 deletions src/agent0/core/base/types_test.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Testing for agent0 types"""
"""Testing for agent0 types."""

from __future__ import annotations

Expand All @@ -13,37 +13,37 @@

@dataclass
class ClassWithOneAttribute:
"""Class with one attribute"""
"""Class with one attribute."""

existing_attrib: int = 1


@freezable(frozen=False, no_new_attribs=False)
@dataclass
class FreezableClass(ClassWithOneAttribute):
"""Freezable class unfrozen by default"""
"""Freezable class unfrozen by default."""


@freezable(frozen=True, no_new_attribs=False)
@dataclass
class FreezableClassFrozenByDefault(ClassWithOneAttribute):
"""Freezable class frozen by default"""
"""Freezable class frozen by default."""


@freezable(frozen=False, no_new_attribs=True)
@dataclass
class FreezableClassNoNewAttribsByDefault(ClassWithOneAttribute):
"""Freezable class with no_new_attribs set by default"""
"""Freezable class with no_new_attribs set by default."""


@freezable(frozen=True, no_new_attribs=True)
@dataclass
class FreezableClassFrozenNoNewAttribsByDefault(ClassWithOneAttribute):
"""Freezable class frozen and with no_new_attribs set by default"""
"""Freezable class frozen and with no_new_attribs set by default."""


class TestFreezability(unittest.TestCase):
"""Test freezable wrapper functionality
"""Test freezable wrapper functionality.
each test checks for the ability to change or add attributest, in 4 cases:
1. not frozen
Expand All @@ -56,16 +56,18 @@ class TestFreezability(unittest.TestCase):
"""

def test_freezable_when_not_set(self):
"""Freezable object when frozen is NOT set, and no_new_attribs is NOT set
desired behavior is: CAN change attributes, and CAN add attributes
"""Freezable object when frozen is NOT set, and no_new_attribs is NOT set.
Desired behavior is: CAN change attributes, and CAN add attributes
"""
freezable_object = FreezableClass()
freezable_object.existing_attrib = 2
freezable_object.new_attrib = 1 # pylint: disable=attribute-defined-outside-init # type: ignore

def test_freezable_when_frozen_is_set(self):
"""Freezable object when frozen IS set, but no_new_attribs is NOT set, manually
desired behavior is: can NOT change attributes, and CAN add attributes
"""Freezable object when frozen IS set, but no_new_attribs is NOT set, manually.
Desired behavior is: can NOT change attributes, and CAN add attributes
"""
freezable_object = FreezableClass()
freezable_object.freeze() # pylint: disable=no-member # type: ignore
Expand All @@ -74,17 +76,19 @@ def test_freezable_when_frozen_is_set(self):
freezable_object.new_attrib = 1 # pylint: disable=attribute-defined-outside-init # type: ignore

def test_freezable_when_frozen_is_set_by_default(self):
"""Freezable object when frozen IS set, but no_new_attribs is NOT set, by default
desired behavior is: can NOT change attributes, and CAN add attributes
"""Freezable object when frozen IS set, but no_new_attribs is NOT set, by default.
Desired behavior is: can NOT change attributes, and CAN add attributes
"""
freezable_object = FreezableClassFrozenByDefault()
with self.assertRaises(AttributeError):
freezable_object.existing_attrib = 2
freezable_object.new_attrib = 1 # pylint: disable=attribute-defined-outside-init # type: ignore

def test_freezable_when_no_new_attribs_is_set(self):
"""Freezable object when frozen is NOT set, but no_new_attribs IS set, manually
desired behavior is: CAN change attributes, and can NOT add attributes
"""Freezable object when frozen is NOT set, but no_new_attribs IS set, manually.
Desired behavior is: CAN change attributes, and can NOT add attributes
"""
freezable_object = FreezableClass()
freezable_object.disable_new_attribs() # pylint: disable=no-member # type: ignore
Expand All @@ -93,17 +97,19 @@ def test_freezable_when_no_new_attribs_is_set(self):
freezable_object.new_attrib = 1 # pylint: disable=attribute-defined-outside-init # type: ignore

def test_freezable_when_no_new_attribs_is_set_by_default(self):
"""Freezable object when frozen is NOT set, but no_new_attribs IS set, by default
desired behavior is: CAN change attributes, and can NOT add attributes
"""Freezable object when frozen is NOT set, but no_new_attribs IS set, by default.
Desired behavior is: CAN change attributes, and can NOT add attributes.
"""
freezable_object = FreezableClassNoNewAttribsByDefault()
freezable_object.existing_attrib = 2
with self.assertRaises(AttributeError):
freezable_object.new_attrib = 1 # pylint: disable=attribute-defined-outside-init # type: ignore

def test_freezable_when_frozen_is_set_and_no_new_attribs_is_set(self):
"""Freezable object when frozen IS set, and no_new_attribs IS set, manually
desired behavior is: can NOT change attributes, and can NOT add attributes
"""Freezable object when frozen IS set, and no_new_attribs IS set manually.
Desired behavior is: can NOT change attributes, and can NOT add attributes
"""
freezable_object = FreezableClass()
freezable_object.freeze() # pylint: disable=no-member # type: ignore
Expand All @@ -114,8 +120,9 @@ def test_freezable_when_frozen_is_set_and_no_new_attribs_is_set(self):
freezable_object.new_attrib = 1 # pylint: disable=attribute-defined-outside-init # type: ignore

def test_freezable_when_frozen_is_set_and_no_new_attribs_is_set_by_default(self):
"""Freezable object when frozen IS set, and no_new_attribs IS set, by default
desired behavior is: can NOT change attributes, and can NOT add attributes
"""Freezable object when frozen IS set, and no_new_attribs IS set.
Default desired behavior is: can NOT change attributes, and can NOT add attributes.
"""
freezable_object = FreezableClassFrozenNoNewAttribsByDefault()
with self.assertRaises(AttributeError):
Expand All @@ -124,7 +131,7 @@ def test_freezable_when_frozen_is_set_and_no_new_attribs_is_set_by_default(self)
freezable_object.new_attrib = 1 # pylint: disable=attribute-defined-outside-init # type: ignore

def test_dtypes(self):
"""Test dtype casting & checking capability of classes that have the freezable decorator"""
"""Test dtype casting & checking capability of classes that have the freezable decorator."""
freezable_object = FreezableClass(existing_attrib=4)
# cast to int, check that it is an int
assert isinstance(
Expand Down
Loading

0 comments on commit 7844425

Please sign in to comment.