Algorithmic Trading
Building trading algorithms from scratch. Part I.
Trading is a risky activity. If you follow anything written in the article, you are responsible for the results. The result of this article may be decreased deposit and lost funds. By reading below and making any actions, you agree with our Disclaimer, Policies, and Risk Warning.
Today, I start a new series on how I build trading algorithms. Those who watched the last course on Sharpedge already know the basic blocks of my process. Here I’ll show a step-by-step procedure with programming codes, results, and everything else.
First things first – what do I use when I build trading algorithms? Well, a lot of professional traders use their own platforms and their own software for developing and backtesting the algorithms. I don’t do that. I use a third-party software which I believe is really good for my needs, at least right now. It’s important to note that I don’t use any machine-learning in my algorithms – I prefer to keep everything as simple as possible. So, let’s start.
In my developing process I use the following platforms:
TradingView
For those who watched Sharpedge, you know what TradingView is. It’s a free online charting platform. TradingView allows you to backtest some simple ideas pretty fast. The disadvantage of the platform is that it sucks in everything apart from testing simple ideas. The amount of data to backtest is limited, the statistics about your idea is limited, and the number of ways in which you can work with your strategy is also really low. Nevertheless, TradingView is a good starting point for almost all cases. Almost.
NinjaTrader & Kinetick
NinjaTrader was the first terminal I used when I started trading. It has good functionality, and it suits me well. Usually, after I found the idea that has some good Profit Factor, or Expectancy, I move to NinjaTrader since it gives you many more dimensions to work with. For those who don’t work with NinjaTrader, you are free to substitute it with TradeStation or MultiCharts. Kinetick is the data feed I use with NinjaTrader. Kinetick is provided by the same company as NinjaTrader Terminal, so it’s easy to use and implement. You can use any data feeds, such as IQFeed, BarChart, or anything else.
Jupyter Notebook
Jupyter is an interactive Python notebook. I use it to analyze and visualize some patterns inside the algorithm and study how trading dimensions behave during a trade. I know it may sound complicated, but once I share the code, pictures, and results, you will understand what I mean.
SEARCHING FOR IDEAS
The first step is to find a simple idea with more or less good profit factor. For the beginning, I search for something that has a profit factor of at least 1.25.
So where to search for ideas? Well, you can Google and search for some entry signals and start working with them. This is a completely legitimate option. However, I use a different approach. First, I come up with the logic I want to capture or test. For example, my last strategy was trend-following, so right now, I’d prefer to create something that would hedge my new trend-following algorithm. Let’s think about it.
How do you hedge a strategy? Well, first you need to understand when your strategy loses money. Let’s consider my last strategy and its’ worst trades. You can see the backtesting results from 1-unit trading and the worst trades below.
Here are some of the inputs:
Instrument: GC (gold futures)
Period: last ten years
Timeframe: 60 minutes
Let’s consider the price dynamics for several worst trades
What do I see from these trades? I see reverses. In each situation the price followed my way for a while before turning around. So, how we can exploit this pattern? Well, here is the first idea – what if I try to sell when the candle closes below the low of the candle that made the highest high of the last 10 bars while the price is still above simple moving average of, let say, 100 bars. I’ll do the opposite for buys. Besides, since it’s a contra-trend strategy I need some risk-management from the very beginning because all mean-reverting strategies can suffer big losses from any impulse one-sided move. In other words, contra-trend strategies don’t have nice inner risk-control. If you watched Sharpedge course on Risk-management, you remember that one of the reasons why Moving Averages are so popular is the fact that they have good risk-control embedded in them. Let’s try and program our first idea in TradingView.
//@version=4
strategy("VSHedge", overlay=true)
ma = sma(close,100)
longCondition = close < ma and close[0] > high[-lowestbars(low,10)[0]]
if (longCondition)
strategy.entry("Long", strategy.long)
strategy.exit("Long", stop = lowest(low,5)[0] - atr(10)[0])
shortCondition = close > ma and close[0] < low[-highestbars(high,10)[0]]
if (shortCondition)
strategy.entry("Short", strategy.short)
strategy.exit("Long", stop = highest(high,5)[0] + atr(10)[0])
Once I run the code on 60 minutes chart of Gold (by the way, in TradingView you have to use CFD contract data), I got really a hectic result. The Profit Factor is positive but the equity curve is messy.
Then I got an idea to switch the timeframe from 60 minutes to 240 minutes. You see, Gold doesn’t move in “really” long waves in terms of time. Trend-following strategies are really good when used on hourly charts, because they catch the move as soon as it starts, while slower timeframes have many more retracements and corrections. As you can see below, the idea worked out and brought more or less “OK” profit factor and equity curve. This is something worth attention.
To make next step we copy the idea’s logic into NinjaTrader. In Ninja Editor you have many more lines of code, but the core code that is performed after every bar is as follows:
protected override void OnBarUpdate() {
if (CurrentBar < BarsRequiredToTrade) return;
longCondition = (Close[0] < SMA(period)[0]) &&
(Close[0] > High[LowestBar(Low,10)]);
shortCondition = (Close[0] > SMA(period)[0]) &&
(Close[0] < Low[HighestBar(High,10)]);
if (longCondition) {
EnterLong();
SetStopLoss(CalculationMode.Price, MIN(Low,5)[0] - ATR(10)[0]);}
if (shortCondition) {
EnterShort();
SetStopLoss(CalculationMode.Price, MAX(High,5)[0] + ATR(10)[0]); }
}
After we wrote the code, we need to compile it and start Strategy Analyzer (yes, it’s much more steps in between writing a code and backtesting it… that’s why I use TradingView at the first stage). So once I run the Strategy Analyzer, I got the results, which seem not right… At least they are not the same as on TradingView, as you see
The number of trades and the equity curve are completely different. Why is that? The reason is the inner methods that are used in NinjaTrader and TradingView and any other platform. You see, when developers make these platforms, they have to make several assumptions about how they want to process the signals and commands. For example, the difference in this particular code is that in NinjaTrader, once the stop order is set, it is not modified, while in TradingView, it is modified every time the long or short condition is true. Basically what I mean is that in NinjaTrader SetStopLoss function works only once per entry:
if (longCondition) {
EnterLong();
SetStopLoss(CalculationMode.Price, MIN(Low,5)[0] - ATR(10)[0]); // works once
}
While in TradingView it works every time the longCondition is true:
if (longCondition)
strategy.entry("Long", strategy.long)
strategy.exit("Long", stop = lowest(low,5)[0] - atr(10)[0]) //works every time the longCondition is true
Is the difference in these inner methods a bad or a good thing? Well, I think it’s a good thing. Sometimes it accidentally forces you to look at the situation from a different perspective. In this case, we understand that introducing partially trailing stops, as on TradingView may make the results smoother.
There may be a good question – why don’t I want to use the strategy with a better profit factor? In this case, the case in NinjaTrader has a much better profit factor, so why I ignore it? It’s mostly because in NinjaTrader everything is defined with 1 big trade (you see the sharp increase in the equity curve). This is just a luck… There may be no such spikes or they may be many of them. In any case, I don’t want to gamble, I want to work with something, that I believe has certain edge. Otherwise I will feel unsecured, and, in the end, will intervene into algorithm performance (watch Psychology course to better understand this topic).
So, while I’m making the proper trailing stops in NinjaTrader (it takes time… and this is a negative side of different inner methods) and write second article, feel free to play with the code on TradingView.