Skip to content

Commit

Permalink
Various updates to fuzz testing (#1249)
Browse files Browse the repository at this point in the history
- Set open trades to be 75% of calc max
- Path independence check effective share reserves has a tolerance of
1e-4
- Path independence sets variable interest to 0 for closing trades only
- Remove hyperdrive balance test
  • Loading branch information
Sheng Lundquist authored Jan 11, 2024
1 parent 972cd92 commit 85dd1f6
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 252 deletions.
1 change: 0 additions & 1 deletion lib/agent0/agent0/interactive_fuzz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Shared functions for interactive fuzz testing."""

from .fuzz_hyperdrive_balance import fuzz_hyperdrive_balance
from .fuzz_long_short_maturity_values import fuzz_long_short_maturity_values
from .fuzz_path_independence import fuzz_path_independence
from .fuzz_profit_check import fuzz_profit_check
232 changes: 0 additions & 232 deletions lib/agent0/agent0/interactive_fuzz/fuzz_hyperdrive_balance.py

This file was deleted.

32 changes: 27 additions & 5 deletions lib/agent0/agent0/interactive_fuzz/fuzz_path_independence.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def main(argv: Sequence[str] | None = None):
def fuzz_path_independence(
num_trades: int,
num_paths_checked: int,
effective_share_reserves_epsilon: float,
present_value_epsilon: float,
chain_config: LocalChain.Config,
log_to_stdout: bool = False,
Expand All @@ -75,6 +76,8 @@ def fuzz_path_independence(
Number of trades to perform during the fuzz tests.
num_paths_checked: int
Number of paths (order of operations for opening/closing) to perform.
effective_share_reserves_epsilon: float
The allowed error for effective share reserves equality tests.
present_value_epsilon: float
The allowed error for present value equality tests.
chain_config: LocalChain.Config, optional
Expand All @@ -84,17 +87,19 @@ def fuzz_path_independence(
Defaults to False.
"""
# pylint: disable=too-many-statements
# pylint: disable=too-many-arguments
log_filename = ".logging/fuzz_path_independence.log"
chain, random_seed, rng, interactive_hyperdrive = setup_fuzz(
log_filename, chain_config, log_to_stdout, fees=False, var_interest=FixedPoint(0)
)
chain, random_seed, rng, interactive_hyperdrive = setup_fuzz(log_filename, chain_config, log_to_stdout, fees=False)

# Open some trades
logging.info("Open random trades...")
trade_events = execute_random_trades(num_trades, chain, rng, interactive_hyperdrive, advance_time=True)
assert len(trade_events) > 0
agent = trade_events[0][0]

# All positions open, we set variable rate to 0 for closing all positions
interactive_hyperdrive.set_variable_rate(FixedPoint(0))

# Snapshot the chain, so we can load the snapshot & close in different orders
logging.info("Save chain snapshot...")
chain.save_snapshot()
Expand Down Expand Up @@ -157,7 +162,9 @@ def fuzz_path_independence(
# Raise an error if it failed
assert first_run_state_dump_dir is not None
try:
invariant_check(check_data, present_value_epsilon, interactive_hyperdrive)
invariant_check(
check_data, effective_share_reserves_epsilon, present_value_epsilon, interactive_hyperdrive
)
except FuzzAssertionException as error:
dump_state_dir = chain.save_state(save_prefix="fuzz_path_independence")

Expand Down Expand Up @@ -201,6 +208,7 @@ class Args(NamedTuple):

num_trades: int
num_paths_checked: int
effective_share_reserves_epsilon: float
present_value_epsilon: float
chain_config: LocalChain.Config
log_to_stdout: bool
Expand All @@ -222,6 +230,7 @@ def namespace_to_args(namespace: argparse.Namespace) -> Args:
return Args(
num_trades=namespace.num_trades,
num_paths_checked=namespace.num_paths_checked,
effective_share_reserves_epsilon=namespace.effective_share_reserves_epsilon,
present_value_epsilon=namespace.present_value_epsilon,
chain_config=LocalChain.Config(chain_port=namespace.chain_port),
log_to_stdout=namespace.log_to_stdout,
Expand Down Expand Up @@ -254,6 +263,12 @@ def parse_arguments(argv: Sequence[str] | None = None) -> Args:
default=10,
help="The port to use for the local chain.",
)
parser.add_argument(
"--effective_share_reserves_epsilon",
type=float,
default=1e-4,
help="The allowed error for effective share reserves equality tests.",
)
parser.add_argument(
"--present_value_epsilon",
type=float,
Expand All @@ -280,6 +295,7 @@ def parse_arguments(argv: Sequence[str] | None = None) -> Args:

def invariant_check(
check_data: dict[str, Any],
effective_share_reserves_epsilon: float,
present_value_epsilon: float,
interactive_hyperdrive: InteractiveHyperdrive,
) -> None:
Expand All @@ -289,6 +305,8 @@ def invariant_check(
---------
check_data: dict[str, Any]
The trade data to check.
effective_share_reserves_epsilon: float
The allowed error for effective share reserves equality tests.
present_value_epsilon: float
The allowed error for present value equality tests.
interactive_hyperdrive: InteractiveHyperdrive
Expand All @@ -305,7 +323,11 @@ def invariant_check(
actual_effective_share_reserves = interactive_hyperdrive.hyperdrive_interface.calc_effective_share_reserves(
pool_state
)
if expected_effective_share_reserves != actual_effective_share_reserves:
if not fp_isclose(
expected_effective_share_reserves,
actual_effective_share_reserves,
abs_tol=FixedPoint(str(effective_share_reserves_epsilon)),
):
difference_in_wei = abs(
expected_effective_share_reserves.scaled_value - actual_effective_share_reserves.scaled_value
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def _get_open_trade_amount(
rng: Generator,
interactive_hyperdrive: InteractiveHyperdrive,
max_budget: FixedPoint = FixedPoint("1e9"),
percent_max: FixedPoint = FixedPoint("0.75"),
) -> FixedPoint:
"""Get a trade amount for a given trade and Hyperdrive pool.
Expand All @@ -94,6 +95,8 @@ def _get_open_trade_amount(
An instantiated InteractiveHyperdrive object.
max_budget: FixedPoint, optional
An optional amount to set an upper bound for the trade, defaults to FixedPoint("1e9").
percent_max: FixedPoint, optional
A percentage of the max trade to use for the upper bound for the trade, defaults to FixedPoint("0.75").
Returns
-------
Expand All @@ -112,6 +115,8 @@ def _get_open_trade_amount(
)
case _:
raise ValueError(f"Invalid {trade_type=}\nOnly opening trades are allowed.")

max_trade = max_trade * percent_max
return FixedPoint(scaled_value=int(np.floor(rng.uniform(low=min_trade.scaled_value, high=max_trade.scaled_value))))


Expand Down
Loading

0 comments on commit 85dd1f6

Please sign in to comment.