Skip to main content

Configuration

This is a brief step-by-step guide for new users leveraging the Multiverse SDK & how to start their first simulation. It should be as simple as possible yet highlight follow-up resources for users to complement their knowledge about agent-based simulations & strategies/protocols.

Almanak developed the Multiverse, a simulation platform to realistically mimic on-chain behaviour & derive actionable insights for any interested entity. Main use cases are revolving around DeFi strategy optimization & protocol parameters check but also economic auditing and fine-grained orderflow analysis.

This is only a high-level tutorial to get you started! More information for in-depth understanding will be linked in these boxes or directly in the text.

Getting started with the Multiverse SDK

Prior to setting up a simulation, install the Multiverse SDK (available in Python), which enables the general interactions with the Multiverse.

pip install multiverse-sdk

This installs all dependencies required to get you started. You will have to fetch your API key from app.almanak.co & setup your configuration to create simulations on the Multiverse platform.

Go to app.almanak.co & click on your profile on the top right corner.

Under API key management, you will be able to generate your own key.

Make sure to save your key & not share it with others, as they can be used to start & therefore pay for new simulation runs.

Create a .env file and add the following line

API_KEY=<YOUR KEY>

Save the file in your local working directory

Congrats, you can now start to define your simulation configuration & let them run!

More information about the architecture & how your simulation configuration is processed can be found here.

Define your simulation environment

The main component within a simulation is the environment, which houses not only the respective protocols but also the agents, which reflect on-chain behaviour. The first step is to include the protocols of interest.

Protocols

This tutorial will only cover a single protocol, namely Uniswap v3.

from multiverse import protocols

uniswap_v3 = protocols(name='uniswapv3', chain='ethereum')

That is the main contribution of a protocol within the Multiverse environment. Note that you will have to define a chain to each protocol. If the protocol is not registered on the respective/any chain, an error will be thrown.

Implementing the protocol does not mean that the respective agents associated to it are available within the simulation. These have to be added in the next step.

Agents

Since you already have the protocol of choice implemented, assessing & adding agents interacting with the protocol is the next step to populate the simulation environment. In our case, a liquidity provider & a trader of a respective pool on Uniswap v3 are added.

from multiverse import agents
from multiverse.strategies import TrendFollowing, DynamicLP

lp_strategy = DynamicLP(protocol='Uniswapv3')
trading_stratey = TrendFollowing(protocol='Uniswapv3')

agent_lp = agents.custom(strategy=lp_strategy,
strategy_params={'pool': '0xcbcdf9626bc03e24f779434178a73a0b4bad62ed'},
wallet='0xc0ffee254729296a45a3885639AC7E10F9d54979')
agent_trading = agents.custom(strategy=trading_strategy,
strategy_params={'pool': '0xcbcdf9626bc03e24f779434178a73a0b4bad62ed'},
wallet='0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E')

Both agents have been created with respective strategies already available as part of the Multiverse library. Additional parameters for the strategy to be initialized, in this case we specify the pool to execute the actions on. A Wallet instance is additionally associated to an agent to make funds available for any action executed on-chain.

Metrics

To understand what happened for either of these agents, assigning useful metrics is a great way to track the health of each agent throughout the simulation. Metrics can be calculated on your own or through integration of existing implementations

from multiverse import metrics

apr_metric = metrics.apr(agent=agent_lp, aggregate=True)
pnl_metric = metrics.pnl(agent=agent_trading, aggregate=True)

Not every agent needs to be tracked with a metrics, it is up to you to define what agents are of interest, who does make most during the simulated timeframe and drawing up your own conclusions.

Connecting the Environment

Since all components of the environment are set, we can connect them with an Environment instance to finalize the initial configuration. Note that all prior steps are convoluted into this step:

from multiverse import Environment

env_config = Environment(agents=[agent_lp, agent_trading],
protocols=[uniswap_v3],
metrics=[apr_metric, pnl_metric])

Choosing & including price feeds

One major variable to drive decision-making is the price of an asset, which determines whether to buy, sell or hold it over time. You can choose how prices should look like within the simulation runs by generating market scenarios through the Price Simulator.

Select an asset pair (e.g. ETH-USDT).

Select market scenario(s) and customize the parameters if you wish. Press the customize button and adjust the sliders. For example, in a trending market the drift and volatility can be adjusted.

Select number of price trajectories to run per market scenario.

Select a time horizon. Both for the historical data that will be used to train the model and the simulation range that would like to simulate over. You can also select the time interval (e.g. 1 hr).

After setting up your scenario, press "generate price trajectories". Depending on how many you selected, it may take some time to run. When it finishes you will be able to see a preview of the price trajectories.

If sufficient, copy the uuids of the price scenarios for the next step

Running the simulation

All components to determine the environment to simulate as well as how many simulation runs are generated are defined, which brings us to the final step: submitting the simulation.

from multiverse import simulator

sim_id = simulator.run(config=env_config,
price_feeds=['uuid1', 'uuid2'])
________________________________________________________
simulator.get(id=sim_id)

In this case only two price feeds have been defined, resulting in two simulation runs being submitted to the queue. Once submitted, you can check the status of your simulation runs by submitting a request with the respective uuid you got when submitting the run.

Export your data

You will then be able to export the data of two runs, where each run is tagged by their own uuid and the respective market scenario uuid attached.

from multiverse import export

exported_data = export(id=sim_id,
format='json')

All metrics tracked throughout the simulation are then provided as a JSON-formatted string to the variable & ready to use for further documentation.

Putting It All Together: Complete Example

The code below covers all the above statements into one for you to directly dive into your first simulation run without trouble

from multiverse import portocols agent, metrics, simulator, export
from multiverse import Environment
from multiverse.strategies import TrendFollowing, DynamicLP

# Protocol initiated
uniswap_v3 = protocols(name='uniswapv3', chain='ethereum')

# Defining the strategies for agents
lp_strategy = DynamicLP(protocol='Uniswapv3')
trading_stratey = TrendFollowing(protocol='Uniswapv3')

# Combining strategies & wallets to agents
agent_lp = agents.custom(strategy=lp_strategy,
strategy_params={'pool': '0xcbcdf9626bc03e24f779434178a73a0b4bad62ed'},
wallet='0xc0ffee254729296a45a3885639AC7E10F9d54979')
agent_trading = agents.custom(strategy=trading_strategy,
strategy_params={'pool': '0xcbcdf9626bc03e24f779434178a73a0b4bad62ed'},
wallet='0x999999cf1046e68e36E1aA2E0E07105eDDD1f08E')

# Setup metrics to track selected agents
apr_metric = metrics.apr(agent=agent_lp, aggregate=True)
pnl_metric = metrics.apr(agent=agent_trading, aggregate=False)

# Define Environment instance
env_config = Environment(agents=[agent_lp, agent_trading],
protocols=[uniswap_v3],
metrics=[apr_metric, pnl_metric])

# Submit simulation runs with previously fetched market scenarios
sim_id = simulator.run(config=env_config,
price_feeds=['uuid1', 'uuid2'])

# Check current status of simulation runs
simulator.get(id=sim_id)

# Export data of simulations runs once succeeded
exported_data = export(id=sim_id,
format='json')

In case you run into any errors or encounter any hiccups, please reach out to support@almanak.co!