Skip to main content

Introduction

Strategies are specialized scripts that share many capabilities with indicators but are designed for building trading systems. Strategies allow you to place, modify, and cancel orders, as well as analyze performance metrics. Currently, strategies cannot be used for live trading, but they can be run in testing mode. Testing mode simulates trades on historical and real-time bars, allowing you to evaluate your strategies in both backtesting and forward-testing scenarios. The current version has the following limitations, which will be implemented later:
  • Strategies cannot be used for live trading.
  • Strategies can trade only one instrument at a time. Like indicators, strategies can request additional market data via calc_on for analysis purposes, but trading operations are limited to the primary instrument on which the strategy is running.

First strategy

Strategies overview To help you get started quickly, let’s walk through a simple strategy. Here is a strategy that flips its position based on a simple condition:
The structure of strategy code follows the same pattern as indicator code:
  • Indie language version
  • package imports
  • Main function or Main class — the entry point of every strategy
However, there are several important differences:
  • the @strategy decorator is used instead of the @indicator decorator
  • self inherits from MainStrategyContext rather than from MainContext, as indicators do
  • strategies have access to the self.trading property, which provides an interface for order and position management
Let’s take a closer look at what is happening in this example. The Main function is called on every candle (and every price tick for real-time data) within the data range used to run the strategy. As with indicators, this function can return values to be rendered on the chart. But in strategies, the Main function can also place orders and make trading decisions. The self parameter in the Main function is an instance of MainStrategyContext. It represents the context of the instrument on which the strategy is running. It provides access to OHLCV values (e.g. self.close) and allows the strategy to place orders for that instrument. Our Main function is decorated with the mandatory @strategy decorator. Decorators (names that begin with the @ character) provide metadata about strategies to the TakeProfit runtime. In addition to the settings provided by the @indicator decorator, the @strategy decorator also allows you to configure various strategy execution parameters. The same parameters can be configured via the UI. In our example, we configure only the initial capital parameter and leave all other settings at their default values. For more information about the available settings, see the Strategy params section. Please note that we need to import certain symbols such as strategy, because they are not part of the built-in Indie symbols. Many strategy-related symbols are located in the indie.strategies package. You can view the entire contents of the package in the library reference. Notice that in this example, all trading operations are performed through the self.trading property. Alternatively, placed orders can also be managed using methods of the Order class, which will be demonstrated later. The self.trading property provides two main groups of functions: Order management methods implement the builder pattern and are used like this:
Note that cancel_order does not require an explicit submit call, as it requires no additional parameters. More detailed information about these methods can be found on the Orders page and in the library reference.

A more advanced example

Now we’re ready to look at a slightly more advanced example that creates orders and saves them to variables for later updating the order parameters:
What’s new in this example?
  • Main is a class rather than a function. For strategies, it must inherit from MainStrategyContext instead of MainContext, which is used in indicators.
  • The self.trading.place_order(...).submit() method returns an Order object, which you can store to track its status or cancel/update it later. We store order objects in the self.long_order and self.short_order variables for later use.
  • Methods for updating or canceling orders have two forms: self.trading.amend_order(...)/cancel_order(...) and order.update(...)/cancel().
  • In this example, we use stop orders. You can read more about order types in the Orders section.
Please note that working with Optional is different in Python and in Indie. In Indie, Optional is an actual wrapper class, and you need to call its value() method to retrieve the underlying value. For more information, see the library reference page. You can find more examples in the Built-in Strategies section.

Next steps

Backtesting mechanics

Information on how backtesting works, how exchange processes are simulated, and how to use the system effectively.

Orders

Information on order types and parameters, order management from strategy code, and the logic of order execution during backtesting.

Strategy parameters

Information on configuring strategy parameters and backtesting settings.