GMX Market Orders

Background

GMX is a decentralized perpetual futures exchange where traders can trade digital assets with leverage without the need for a third party to fill the order. On GMX, you are able to long or short positions with different underlying assets including ETH, BTC and more. One of the most important features of GMX is that it allows users to apply for leveraged trades and, accordingly, borrow funds to increase their positions, which could provide bigger returns (or losses) on price movements.

Unlike centralized exchanges, GMX is fully on-chain; this means all transactions and positions occur openly. Users get to engage directly with the smart contracts, which effectively reduces counterparty risks and increases control. Along with this, GMX has put in place an oracle system for fetching price data accurately, due to the help it gets in reducing price manipulation.

In this example, a simple trading strategy that opens a leveraged long on WETH is considered, and the closing based on a predefined threshold of profit or loss. Whether you're a seasoned trader or someone new to perpetual trading, this strategy will give you insight into how to execute basic trades on GMX while managing risk.

Compass Labs enables simulations on GMX

Perpetuals Trading Strategy on GMX

This strategy is straightforward but effective for traders who want to take advantage of potential upward price movements in WETH. Here's how it works:

  • Opening a Long Position: We'd like to go long on WETH if price goes below $2525. With the condition met, the strategy opens a long position at 3x leverage. In this case, it would mean you are trading with three times more capital than you actually have. For this example, let the position size be $100,000 worth of WETH; this includes borrowed funds so only $33,333 worth of WETH will be taken from the agent. Also allow up to 2% slippage, meaning that if the trade is filled at a slightly worse price, we allow that 2% margin of error.

  • Managing Risk and Taking Profit: The strategy closes the position to take profits or reduce losses. When the trade makes a profit of $120 or more, it will then close the position to capture those gains. On the other hand, if the trade were to lose $70 or more, we would also close our position. In this way, the trader can cap downside at risk and yet is free to realize further drawbacks on favorable market movements.

By setting clear entry and exit rules, this strategy provides a disciplined approach to trading on GMX while leveraging the power of decentralized finance (DeFi).

Screenshot of https://compasslabs.ai/dashboard?example=gmxV2_market_orders

How To Run

Installation

Follow our Getting Started guide to install the dojo library and other required tools.

Then clone the dojo_examples repository and go into the relevant directory.

Terminal
git clone https://github.com/CompassLabs/dojo_examples.git
cd dojo_examples/examples/gmxV2_market_orders

Running

Download the dashboard to view the simulation results. To view example simulation data, download results.db file from the repo and click 'Add A Simulation' on the dashboard.

To run the simulation yourself, use the following command.

Terminal
python run.py

This command will setup your local blockchain, contracts, accounts and agents. You can then access your results on your Dojo dashboard by connecting to a running simulation.


Step-By-Step Explanation

Initialization

We create a subclass of BasePolicy called GmxV2Policy. This class is responsible for defining the trading logic for the agent. In the __init__ method, we set a variable to track if we have an open position or not.

policy.py
class State(Enum):
  NO_POSITION = 0
  POSITION_OPEN = 1
  FINISH = 2
 
 
class GmxV2Policy(BasePolicy):
  """Example gmx policy."""
 
  def __init__(self, agent: BaseAgent) -> None:
      """Initialize the policy."""
      super().__init__(agent=agent)
      self.state = State.NO_POSITION

Signal Calculation

Screenshot of https://compasslabs.ai/dashboard?example=gmxV2_market_orders

Signals allow us to easily view data on our Dojo dashboard. In this example, we are adding multiple signals to monitor the GMX market that we are on such as PnL of long positions, PnL of short positions, net PnL, price of long token, short token, index token and the GM token.

policy.py
gm_token_value, market_pool_value_info = obs.get_market_token_price_for_traders(
  True
)
index_token_price = obs.index_token_price("WETH:WETH:USDC")
long_token_price = obs.long_token_price("WETH:WETH:USDC")
short_token_price = obs.short_token_price("WETH:WETH:USDC")
net_pnl = obs.get_net_pnl(True)
long_pnl = obs.get_pnl(True, True)
short_pnl = obs.get_pnl(False, True)
long_open_interest_with_pnl = obs.get_open_interest_with_pnl(True, True)
short_open_interest_with_pnl = obs.get_open_interest_with_pnl(False, True)
market_info = obs.get_market_info()
 
obs.add_signal("net pnl", net_pnl)
obs.add_signal("long pnl", long_pnl)
obs.add_signal("short pnl", short_pnl)
obs.add_signal("long open interest with pnl", long_open_interest_with_pnl)
obs.add_signal("short open interest with pnl", short_open_interest_with_pnl)
obs.add_signal("gm token value", gm_token_value)
obs.add_signal("index token price", index_token_price)
obs.add_signal("long token price", long_token_price)
obs.add_signal("short token price", short_token_price)
 
total_trader_pnl = self.agent.reward(obs)

Trade Execution

policy.py
if index_token_price < Decimal(2525) and self.state == State.NO_POSITION:
  self.state = State.POSITION_OPEN
  return [
      IncreaseLongMarketOrder.from_parameters(
          agent=self.agent,
          size_delta_usd=Decimal(100000),
          market_key="WETH:WETH:USDC",
          token_in_symbol="WETH",
          collateral_token_symbol="WETH",
          slippage=200,
          observations=obs,
          leverage=Decimal(3),
      )
  ]
 
if total_trader_pnl > Decimal(120) and self.state == State.POSITION_OPEN:
  self.state = State.NO_POSITION
  return [
      DecreaseLongMarketOrder.from_parameters(
          agent=self.agent,
          size_delta_usd=Decimal(100000),
          market_key="WETH:WETH:USDC",
          token_in_symbol="WETH",
          collateral_token_symbol="WETH",
          slippage=200,
          observations=obs,
          leverage=Decimal(3),
      )
  ]
 
if total_trader_pnl < Decimal(-70) and self.state == State.POSITION_OPEN:
  self.state = State.FINISH
  return [
      DecreaseLongMarketOrder.from_parameters(
          agent=self.agent,
          size_delta_usd=Decimal(100000),
          market_key="WETH:WETH:USDC",
          token_in_symbol="WETH",
          collateral_token_symbol="WETH",
          slippage=200,
          observations=obs,
          leverage=Decimal(3),
      )
  ]

Here, we specify the conditions that must be met to open or close our long position. If the price of WETH is less than $2525 and we don't have an open position, we open a long position with a leverage of 3x. We also set the position size to $100,000 and allow up to 2% slippage.

If the trade makes a profit of $120 or more, we close the position to capture those gains. On the other hand, if the trade loses $70 or more, we close our position to cap downside risk.

In the run.py file, we create an agent that implements our trading strategy specified by the policy, a GMX environment and a market venue that our agent will operate on.

Results

You can download the results to this example below.

We offer a dashboard desktop application for visualizing your simulation results. You can download the file for the desktop application here, or just open the results in our hosted dashboard.