This week we return to QuantConnect for an article on working with Heiken Ashi data. We will cover how to use Heikin Ashi data in your strategy, take a look at some plotting options and also provide a simple strategy that can be used as a base for your own projects.
This is not the first time we have touched this topic. Previously, we have covered working with Heikin Ashi charts on Backtrader. In that article, we also covered a little background/introduction to the Heikin Ashi candlestick and how to interpret it. Those introductory parts of the article are not really platform specific. As such, any readers who are new to Heiken Ashi candles would benefit from reading the first few paragraphs.
Although QuantConnect does support creating custom charts, it is not a charting platform by trade. As such, users cannot expect to have Tradingview levels of charting ability. Having said all that, there are some things we can do to plot our Heikinashi data and four suggestions will follow. These are not the only options in the world but should provide a range of styles to consider.
If you are a visual person and like to see charts in order to generate development ideas, then there is no harm in using a charting platform like Tradingview in conjunction with QuantConnect. Use the charting platform as your notepad and then come back to QuantConnect when you are ready to put an idea into practice!
So without further ado, let’s move onto our suggestions.
Note: All the suggestions shown below will be contained in the final strategy code.
Personally, I find that a little hard to read and would rather look at a log file.
As you can see, each candle represents the change in price between 2 days. We can see this on the x-axis. It moves in 2-day steps.
In the image above, we verify two things. First, that the sentiment is correct and secondly that only when sentiment changes we send buy/sell orders.
Here we can see that the trade is filled at the open of the following bar as expected. What’s more is that it is filled against real
Heiken Ashi on QuantConnect
QuantConnect’s approach to handling Heikin Ashi data differs from other platforms such as Tradingview and Backtrader. On QuantConnect we access Heikinashi data via an Indicator. This design decision makes a whole lot of sense. After all, Heiken Ashi candles are a derivative of real prices just like any other indicator. By contrast, on other platforms, Heiken Ashi data is delivered as a data feed. In other words, theOHLC
data is converted to the Heikin Ashi version of OHLC
.
When OHLC
data is converted, often beginners will end up with incorrect results and unrealistic expectations. This is because when Heikin Ashi prices are delivered as a data feed, the backtesting engine only has these prices for reference. In turn, this means that order fill levels and profit/loss calculations are based on prices which never existed.
Note that this does not mean the other platforms are wrong or have issues. It just means that users must be aware of it and adjust their code appropriately.
On QuantConnect the beginner does not even need to worry about this. The data will come through as a set of indicator values. All order fills and PnL calculations etc will always be calculated from the data feed using real prices!
Adding Heikinashi Indicators
As we discussed, in order to use Heiken Ashi data on QuantConnect, we need to create an indicator. We do this in the same way as we created the RSI indicator in our first script tutorial. Fire up the API tree and you will find theHeikinAshi()
Indicator is available right at the root of the tree.

Plotting Heikinashi Candles
Users trying to plot Heikin Ashi candlestick charts might find themselves arriving at this article courtesy of Google. If that is you, we can at least save you some time from looking for a solution that does not exist. At the time of writing there is no support for plotting Heikin Ashi candles that look like this:
Try Logging!
Whilst this is not one of the plotting suggestions, wherever possible, try to use the logging function (self.Log()
). Unless you looking for visual patterns, you can verify everything you need to through logging. As such, this is a good time to start getting comfortable in the logs. Further to this, since we already know from our plotting tutorial that QuantConnect enforces limits on plotting, it is not practical to plot every data point in our algorithms. Our charts should be selected wisely and plotted only when needed.
Suggestion 1 – Line Charts
First, we can plot each data point from the indicator on a simple line chart. This will result in a chart which looks like this:
Suggestion 2 – Candle Charts
The next, option is to create a custom chart and set up a series on the chart that usesSeriesType.Candle
. It should be noted though that this does not produce a OHLC
candlestick that you might be accustomed to on charting platforms. Instead, it produces something which more closely represents the equity chart.

Suggestion 3 – Scatter Charts
The third suggestion has been recommended in the community forums on several occasions and so it is worth mentioning here! With this method, we use scatter markers to plot theOHLC
data.

Suggestion 4 – Mixed
In the final chart, we mix line and scatter plots to get a nice mix of information. Circles on thePrice
line denote whether we closed up or down. I.e whether the Heiken Ashi candle is green or red. In addition to this, we add two scatter plots to show the relative highs and lows. This results in a chart that looks like this:

The Code
### <summary> ### Simple RSI Strategy intended to provide a minimal algorithm example using ### one indicator ### </summary> from System.Drawing import Color class RSIAlgorithm(QCAlgorithm): def Initialize(self): '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.''' # Set our main strategy parameters self.SetStartDate(2014,12, 1) # Set Start Date self.SetEndDate(2015,1,1) # Set End Date self.SetCash(10000) # Set Strategy Cash self.Equities = ["AAPL"] self.HK = dict() # Create dict to hold all our HK Indicators for Equity in self.Equities: # Find more symbols here: http://quantconnect.com/data self.AddEquity(Equity, Resolution.Daily) self.HK[Equity] = self.HeikinAshi(Equity, Resolution.Daily) # Plotting Suggestion 1: Line chart # -------------------------------------- # Note: This has been commented out as # we are limited to 10 series per # backtest. To test, uncomment the # lines below and then comment out # either suggestion 3 or 4. # --------------------------------------- #self.PlotIndicator( # Equity + " - Line", # self.HK[Equity].Open, # self.HK[Equity].High, # self.HK[Equity].Low, # self.HK[Equity].Close # ) # Plotting Suggestion 2: Candle Chart # --------------------------------------- CandChart = Chart(Equity + "- Candle", ChartType.Stacked) CandChart.AddSeries(Series('Heikinashi', SeriesType.Candle)) self.AddChart(CandChart) # Plotting Suggestion 3: Scatter Chart # --------------------------------------- ScatPlot = Chart(Equity + "- X", ChartType.Stacked) ScatPlot.AddSeries(Series('Open', SeriesType.Scatter, '$', Color.Black, ScatterMarkerSymbol.Circle)) ScatPlot.AddSeries(Series('High', SeriesType.Scatter, '$', Color.Green, ScatterMarkerSymbol.Triangle)) ScatPlot.AddSeries(Series('Low', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.TriangleDown)) ScatPlot.AddSeries(Series('Close', SeriesType.Scatter, '$', Color.Black, ScatterMarkerSymbol.Square)) self.AddChart(ScatPlot) # Plotting Suggestion 4: Mixed # --------------------------------------- SAPlot = Chart(Equity + "- Mix", ChartType.Stacked) SAPlot.AddSeries(Series('Price', SeriesType.Line, "$", Color.Black)) SAPlot.AddSeries(Series('Bullish', SeriesType.Scatter, "$", Color.Green, ScatterMarkerSymbol.Circle)) SAPlot.AddSeries(Series('Bearish', SeriesType.Scatter, "$", Color.Red, ScatterMarkerSymbol.Circle)) SAPlot.AddSeries(Series('Neutral', SeriesType.Scatter, "$", Color.Black, ScatterMarkerSymbol.Circle)) SAPlot.AddSeries(Series('High', SeriesType.Scatter, '$', Color.Black, ScatterMarkerSymbol.Triangle)) SAPlot.AddSeries(Series('Low', SeriesType.Scatter, '$', Color.Black, ScatterMarkerSymbol.TriangleDown)) self.AddChart(SAPlot) def OnData(self, data): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. Arguments: data: Slice object keyed by symbol containing the stock data ''' for Equity in self.Equities: # Aliases # ----------------------------------------------------------------- # Heikin HK_O = self.HK[Equity].Open.Current.Value HK_H = self.HK[Equity].High.Current.Value HK_L = self.HK[Equity].Low.Current.Value HK_C = self.HK[Equity].Close.Current.Value HK_P = self.HK[Equity].Current.Price # OHLC O = data[Equity].Open H = data[Equity].High L = data[Equity].Low C = data[Equity].Close P = data[Equity].Price # ----------------------------------------------------------------- # Work out Heikin Sentiment # --------------------------------------- if HK_O < HK_C: HK_S = "Bull" elif HK_O > HK_C: HK_S = "Bear" else: HK_S = "Neut" # Plotting Option 2: Candle Chart # --------------------------------------- self.Plot(Equity + "- Candle", 'Heikinashi', HK_P) # Plotting Option 3: Scatter Chart # --------------------------------------- self.Plot(Equity + "- X", 'Open', HK_O) self.Plot(Equity + "- X", 'High', HK_H) self.Plot(Equity + "- X", 'Low', HK_L) self.Plot(Equity + "- X", 'Close', HK_C) # Plotting Option 4: Mixed # --------------------------------------- self.Plot(Equity + "- Mix", 'Price', HK_P) self.Plot(Equity + "- Mix", 'High', HK_H) self.Plot(Equity + "- Mix", 'Low', HK_L) if HK_S == "Bull": self.Plot(Equity + "- Mix", 'Bullish', HK_P) elif HK_S == "Bear": self.Plot(Equity + "- Mix", 'Bearish', HK_P) else: self.Plot(Equity + "- Mix", 'Neutral', HK_P) # Logging # ----------------------------------------------------------------- self.Log("{0} OHLC >> O: {1} H: {2} L:{3}, C:{4} | Price: {5}".format(Equity, O,H,L,C,P)) self.Log("{0} Heikin >> O: {1} H: {2} L:{3}, C:{4} | Price: {5} | Sentiment: {6}".format(Equity, HK_O,HK_H,HK_L,HK_C,HK_P,HK_S)) # Entry / Exit Criteria # ----------------------------------------------------------------- # Check if we are in the market if not self.Portfolio.Invested: # If not, we check HK sentiment is bullish if HK_S == "Bull": self.SetHoldings(Equity, 0.5) else: if HK_S == "Bear": self.Liquidate(Equity)
Code Commentary
The strategy is very, very basic. It simply buys when the Heikin candles are bullish (green) and sells when they turn bearish (red). As mentioned in the introduction, the code is intended to be used as a simple base to build upon. One general note that is applicable to the complete example code is that theInitialize()
and OnData()
methods (functions) have been coded in a way to support multiple assets. As such, if you add a second symbol into the line:
self.Equities = ["AAPL"]
Then the strategy will cycle through both symbols and create plots for each. It should be noted that due to the number of plots used in the examples, plotting limits will likely be reached. We are limited to 10 series plots per backtest. It is also for this reason that suggestion 1 is fully commented out.
Logging
To practice what one preaches, some basic logging has been added to the example. Here we simply log the realOHLC
, Heikin OHLC
and the candle sentiment. This is enough to compare the differences in prices and validate that our strategy is opening and closing positions in the correct places.
Plotting – Identity Objects!
One potential Gotcha when working with Heiken Ashi Indicators is that it is also possible to access the latest indicator values like so:HK_O = self.HK[Equity].Open HK_H = self.HK[Equity].High HK_L = self.HK[Equity].Low HK_C = self.HK[Equity].Close HK_P = self.HK[Equity].CurrentHowever, these appear to be “Identity” type objects and cannot be plotted. If you try to plot them you will receive the following error:
Runtime Error: Trying to dynamically access a method that does not exist throws a TypeError exception. To prevent the exception, ensure each parameter type matches those required by the Plot method. Please checkout the API documentation. at OnData in main.py:line 110 TypeError : No method matches given arguments for Plot (Open Stacktrace)It can be confusing at first because if you try to print the values using
self.Log()
, the values will be converted to a string and you will see them in the log. As such, you can be left wondering what the issue is. Save yourself some time and access the latest values through Current.Value
as shown in the example code.
HK_O = self.HK[Equity].Open.Current.Value HK_H = self.HK[Equity].High.Current.Value HK_L = self.HK[Equity].Low.Current.Value HK_C = self.HK[Equity].Close.Current.Value HK_P = self.HK[Equity].Current.Price
Verifying Our Output
After creating any algorithm we should perform some checks to make sure that it is performing as expected. As simple as the strategy might be, we should still perform testing. Silly typos can easily creep in and completely invalidate the test. Besides, it is a good habit to get into for when your algorithms become more complex. The two key items we shall verify are:- Whether we are buying/selling at the correct time.
- Double checking the earlier claim here that the LEAN engine always uses real prices for order fills.
Buying/Selling
To check whether we are buying and selling in the correct places, we can study the logs and compare to the trade list:
Order Fills
Finally, we will verify our orders are being filled with real prices. Again we can do this by comparing our Log to the trades list.
OHLC
prices rather than the Heikin Ashi prices.
Find This Post Useful?
If this post saved you time and effort, please consider support the site! There are many ways to support us and some won’t even cost you a penny.
Brave
Backtest Rookies is a registered with Brave publisher!
Brave users can drop us a tip.
Alternatively, support us by switching to Brave using this referral link and we will receive some BAT!
Tradingview
Referral Link
Enjoying the content and thinking of subscribing to Tradingview? Support this site by clicking the referral link before you sign up!
PayPal
BTC
3HxNVyh5729ieTfPnTybrtK7J7QxJD9gjD
ETH
0x9a2f88198224d59e5749bacfc23d79507da3d431
LTC
M8iUBnb8KamHR18gpgi2sSG7jopddFJi8S
Hi, I had a question regarding the use of the QuantConnect API. I am trying to use the candlestick patterns in the API and I am wondering what exactly I have to do to use the specific indicator. For example, in your Heikin Ashi indicator, what did you use from the API that allowed you to call the Heikin Ashi indicator? Also, by calling the Heikin Ashi indicator from the API, what does that allow you to do? I am a beginner with python and QuantConnect, having used it for just over a month. Your summaries have been incredible and I really appreciate you doing this.