Python
Strategy
Guides
Overview

Writing your first strategy

The table below shows the currently supported exchanges.

ExchangeSupported
Bitget
Bybit
Binance
Okx
Zoomex

As previously mentioned, to create a trading strategy a developer only have to describe two things:

  1. A set of handlers for market events
  2. Conditions for a trade

Let's take a deeper look on how to do them in code.

File Structure

You need to have two files namely requirements.txt and main.py.

    • requirements.txt
    • exchange-keys.json
    • main.py
  • requirements.txt

    This is the file where you include the dependencies of your Python script, which means you can use any external libraries as long as they are published on PyPi eg. TA-lib, numpy, pandas, etc. An example is shown as follows

    cybotrade>=1.4.3
    colorlog>=6.7.0
    TA-Lib>=0.4.26
    pandas>=2.0.2
    matplotlib>=3.7.1

    main.py

    This is the file where you write your Python code, the most important thing is that you must have

    • A class named Strategy that extends from cybotrade's BaseStrategy.
    from cybotrade.strategy import Strategy as BaseStrategy
     
    class Strategy(BaseStrategy):
      pass
    ⚠️

    The strategy will not work on Cybotrade (opens in a new tab) if the requirement above was not satisfied.

    Strategy Implementation

    Handlers for market events

    The runtime subscribes market data stream such as candle, public trades etc. from exchanges and it is up to strategy developers to implement the handlers taken for these events. It can be done by overriding the Strategy class' methods.

    from cybotrade.strategy import Strategy as BaseStrategy
    import talib
    import numpy
     
    class Strategy(BaseStrategy):
      # This method will be invoked every time a candle closes, if the strategy
      # subscribes to 1 hour candle then the method will be invoked every hour.
      async def on_candle_closed(self, strategy, topic, symbol):
        # Here you define the actions to be taken such as calculating indicators.
        ...
     
        # Taking all the collected 1h candles thus far.
        candles = super().data_map[topic]
     
        # Convert candles into a list of close prices and calculate the RSI.
        rsi = talib.RSI(numpy.array(list(map(lambda c: float(c["close"]), candles))))
     
        print(f"RSI: {rsi}")

    Conditions for a trade

    In order for a strategy to be ready for backtests, simulations and live trades, the strategy has to place entry and exit orders. This can be done by simply calling the methods provided by the StrategyTrader, in this case it is the first parameter from the on_candle_closed method.

    Note that the initial_capital field for the RuntimeConfig is not necessary in Live/LiveTestnet mode, and is optional in Backtest. During Backtest, there will not be any checks for insufficient balance and the runtime will not prevent you from placing an order despite having negative balance.

    from cybotrade.strategy import Strategy as BaseStrategy
    from cybotrade.models import OrderParams, OrderSide, Exchange
    import talib
    import numpy
     
    class Strategy(BaseStrategy):
      RSI_ENTRY = 30
      RSI_EXIT = 70
     
      # This method will be invoked every time when a candle closes, if the strategy
      # subscribes to 1 hour candle then the method will be invoked every hour.
      async def on_candle_closed(self, strategy, topic, symbol):
        # Here you define the actions to be taken such as calculating indicators.
     
        # Taking all the collected 1h candles thus far.
        candles = super().data_map[topic]
        latest_candle = candles[-1];
     
        # Convert candles into a list of close prices and calculate the RSI.
        rsi = talib.RSI(numpy.array(list(map(lambda c: float(c["close"]), candles))))
     
        if rsi >= self.RSI_EXIT:
          # Short if RSI more than or equals to 70
          await strategy.open(
            exchange=Exchange.BybitLinear,
            side=OrderSide.Sell,
            quantity=0.01,
            take_profit=None,
            stop_loss=float(latest_candle["close"]) * 1.1,
            limit=None,
            is_hedge_mode=False,
            is_post_only=False,
          )
        elif rsi <= self.RSI_ENTRY:
          # Long if RSI less than or equals to 30
          await strategy.open(
            exchange=Exchange.BybitLinear,
            side=OrderSide.Buy,
            quantity=0.01,
            take_profit=None,
            stop_loss=float(latest_candle["close"]) * 0.9,
            limit=None,
            is_hedge_mode=False,
            is_post_only=False,
          )

    Check the Strategy API for a detailed information on the library's provided functions for entry and exit orders.

    Running your strategy

    After writing the code, it is recommended to go through the following sequence to ensure the strategy is working as expected.