How I test my Futures Trading Strategies

Before testing, it is first necessary to define exactly what a Trading Strategy is. I like to specify a strategy as if I were going to convert it into computer code. Every variable that should be considered needs to be defined.

I break a strategy into 5 sections:

1. Setup
Let’s consider an example strategy: “I want to trade breakouts from an area of consolidation”. In order for a computer to determine an area of consolidation, it is necessary to be very specific. For example:

  1. What is the minimum length (in time) of the consolidation period?
  2. What is the minimum range (in ticks) of the consolidation period?
  3. Does the volume distribution within the consolidation period matter?
  4. How far away does the consolidation period need to be from a prior setup?
  5. How long can price break away from the consolidation bounds before re-entering and still consider the consolidation period valid?

Once these details are specified, it should be possible for a computer to highlight on a chart all the areas that meet the specification.

2. Context
Most methods work some of the time, and no method works all of the time. The key is understanding which methods work at which times!

It is necessary to define the times when a setup should be ignored by asking question such as:

  1. Has the setup occurred immediately after the open, or a few minutes before an interest rate announcement?
  2. Is volatility acceptable?
  3. How long is available before a trade would need to be closed? For example, is there a high risk event coming up where I want to be flat? How long until the cash close?
  4. How much volume has traded during the setup and is this enough to generate the expected move?

3. Signal
Once a setup is identified and it passes the context checks, it is time to identify the Signal - the actual entry point of the trade. For a consolidation breakout, examples of a signal could be:

  1. When price crosses a level on increasing volume.
  2. When price crosses a level, then pulls back to a particular point, then crosses the previous breakout extreme, with favourable bid and offer pulling/stacking.
  3. On a retest of the breakout level when a certain delta change is identified.

Some setups can break in either direction, so there may be a bullish signal and/or a bearish signal. Further constraints may need to be added, for example:

  1. What is happening on a higher timeframe? Do we really want to enter a bearish trade if the higher timeframe is trending up?

4. Targets
It is necessary to define how Stop and Targets are calculated. These can be based on market structure, Fibonacci levels, etc.

5. Validity
The final stage before classing the strategy as valid is to ask - “Does it make sense to execute”? For example:

  1. Is the initial Stop far enough away to accommodate the predicted level of volatility without triggering due to expected normal market fluctuations?
  2. Is the initial Target far enough away to generate an appropriate risk/reward?
  3. Is there sufficient liquidity to keep slippage within defined parameters?

Summary
A strategy is only limited by your imagination and there are an unlimited number of strategies! In order to test a strategy, it is first necessary to define all the details.

In a later post, I’ll discuss the ways a strategy can be tested, and what is necessary to convert a strategy into a fully automated or semi-automated “algo”.

What information do you consider important when building your own trading strategies?

4 Likes

Thank you for starting this great thread! I appreciate new ideas generated for discussion.

Matt

Data

The type of data required to test a strategy will fall into one of the following sets:

  1. Daily price and volume data (typically the Open, High, Low, Close, and total volume traded).
  2. Intraday price and volume data (As above, but for hours, minutes or seconds).
  3. Tick data. This provides every trade executed and the size of the trade. It will typically include the top of book quote (ie the best bid and ask) at the time of the trade.
  4. All quotes - the full Level 2 order book and all changes.

For simpler strategies, e.g. a moving average crossover on an hourly timeframe, data from sets 1 or 2 are required. Such data is often available for free, or via your usual CQG/RIthmic account.

For strategies that look for short market inefficiencies (e.g. stop runs), or that execute based on liquidity or order flow imbalance, data from sets 3 and 4 are required. The amount of data in these sets is colossal compared to sets 1 and 2. CQG and Rithmic will strictly limit the amount of tick data you can download. They will provide just enough for you to work with order flow tools like Optimus Flow or Bookmap so you can generate footprint charts for real time trading. However, if you try and request too much data, e.g. a week or a month, you will quickly find your data is cut or restricted. Sometimes, frequent switching between symbols or reloading a footprint chart multiple times can be enough to exceed rate limits!

For obtaining data in set 3, I have previously used TickData. They can provide many years of historical trade and top-of-book quote data in standard .csv format, so this is useful for feeding into standalone backtest software, e.g. custom algorithms written in Python.

Recently I use Sierra Chart and their own data feed called Denali. Denali provides 180 days of tick data, and 15 days of Level 2 data. This is usually sufficient for backtesting daytrading and scalping strategies.

In the next post I’ll discuss programming languages.

Programming Language

This is a brief introduction to the languages that are often used for writing back-tests and automated trading algorithms:

1. Specialised High level scripting languages
Examples: NinjaTrader’s NinjaScript. TradingView’s Pine Script, MultiCharts’ EasyLanguage. These tend to be easy to understand, lightly featured, and designed specifically for an application. For coding a simple algorithm like a Moving Average Crossover, these languages are fine. However, for anything more complicated, or where you want to create a library of code that can be reused at a later date, simple scripting languages may be limiting.

2. Generic High Level scripting languages
Example: Python. These are widely used across many industries, not just trading. Python is often used in research and education, so there are many libraries available for data analysis and artificial intelligence. This makes it a good candidate for financial quantitative analysis. Python is popular because it offers the simplicity and freedom of a scripting language, yet is powerful enough to be used for more complex tasks. It is possible to build entire applications from Python. For strategy testing, Quantopian offers an online Python system for building and backtesting strategies. You write your code into a web browser on their site, and then run the code on their servers using their data. If your strategy meets certain requirements, they will fund you. This can be a good way to start backtesting in Python, completely for free, even if you don’t intend to make use of their funding.

3. Generic Mid Level, All-Purpose programming languages
Examples: Java, C#. These are often used for building full size applications, for example Optimus Flow is written in C#, and Interactive Brokers’ Trader Workstation is written in Java. The banking app on your phone is probably written in Java. These languages are designed for large, multi-team development while maintaining code safety by keeping the programmer away from hardware where possible. For example, memory management is mostly automatic. Optimus Flow and MultiCharts.Net use C# for creating strategies and automated algos.

4. Generic Lower Level language
Example: C, C++. C++ is often used in High Frequency Trading systems, telecommunications, operating systems, even Jet Fighter control software. Games and applications that require high performance (e.g. Adobe Photoshop) are written in C++. NVidia Graphics cards are programmed with C. As a low level language, the programmer can take responsibility for hardware functions such as managing memory. This means programs can be optimised and run extremely quickly, but the language is less friendly and it is easier to introduce serious bugs that can cause the computer to crash. Sierra Chart is written in C++ and requires custom studies to be written in C++ - this is one of the reasons it is so fast and works well on lower specification PCs.

Standalone software vs integrating with a trading platform

It is possible to purchase data from a company like Tickdata, write a standalone Python algorithm, feed the data into the algorithm, then analyse the results in a program like Excel. For running backtests on years of data or across many asset classes, this can be very efficient as you can scale tests over many CPU cores or even multiple servers.

However, integrating with a charting/trading platform is much easier. Results can be shown graphically on a chart and the platform can provide simulated trading, or live trading when ready.

The Application Programming Interface (API)

An API is provided by the trading platform and is the way your code interacts with the platform. For example, there will be an API to retrieve price data, to enter a trade, move a stop, query your account balance, etc. When choosing a product to code against, the first thing I will check is the API. In particular:

  1. How extensive is it and will it allow me to do what I want to do?
  2. How well is it documented? Are there many users and are they happy or frustrated with the API?
  3. How often does the API change? A mature, well thought out API that has little changes means I don’t need to keep updating my code because the API keeps changing.
  4. Are there many examples available? The best way to learn coding is by looking at examples.
1 Like

@autobahn Thank you for such nice and methodical posts!

Matt