This is part 2 of the Ichimoku Strategy creation and backtest – with part 1 having dealt with the calculation and creation of the individual Ichimoku elements (which can be found here), we now move onto creating the actual trading strategy logic and subsequent backtest.
The Ichimoku approach concerns itself with two major elements – firstly the signals and insights produced by the “cloud” structure, which is in trurn created by the interplay between the Senkou Span A and Senkou Span B (and sometimes its relation to the price), and secondly the interplay between the price, the Tenkan-sen and the Kijun-sen.
Let’s deal with the cloud element first:
There are two ways to identify the overall trend using the cloud. First, the trend is up when prices are above the cloud, down when prices are below the cloud and flat when prices are in the cloud. Second, the uptrend is strengthened when the Senkou Span A (green cloud line) is rising and above the Senkou Span B (red cloud line). This situation produces a green cloud (please note this is NOT currently the case on the chart I have produced as I am still working on getting that logic coded with Plotly – currently my cloud is just shaded all red, although the actual lines themselves are correctly coloured). Conversely, a downtrend is reinforced when the Leading Span A (green cloud line) is falling and below the Leading Span B (red cloud line). This situation produces a red cloud. Because the cloud is shifted forward 26 days, it also provides a glimpse of future support or resistance.
Now onto the second elements, the interplay between the price, the Tenkan-sen and the Kijun-sen:
The price, the Tenkan-sen and the Kijun-sen are used to identify faster and more frequent signals. It is important to remember that bullish signals are reinforced when prices are above the cloud and the cloud is green. Bearish signals are reinforced when prices are below the cloud and the cloud is red. In other words, bullish signals are preferred when the bigger trend is up (prices above green cloud), while bearish signals are preferred when the bigger trend is down (prices are below red cloud). This is the essence of trading in the direction of the bigger trend. Signals that are counter to the existing trend are deemed weaker, such as short-term bullish signals within a long-term downtrend or short-term bearish signals within a long-term uptrend.
When the Tenkan-sen crosses up through the Kijun-sen, that is considered a bullish signal and vice versa when the Tenkan-sen crosses down through the Kijun-sen that is considered a bearish signal.
With regards to the price and the Tenkan-sen, when prices cross up through the Tenkan-sen that is considered a bullish signal, and again vice versa when prices cross down through the Tenkan-sen that is considered a bearish signal.
Right so let us formalise our rules…
Buy when the following are true:
1) Prices are above the cloud 2) Senkou Span A is above Senkou Span B EITHER 3) the Tenkan-sen crosses up through the Kijun-sen OR 4) prices cross up through the Tenkan-sen
When either of these last two bullish criteria are met, the buy trade is opened at the start of the NEXT candle. The exit criteria is exit as soon as the Tenkan-sen crosses down through the Kijun-sen.
Sell when the following are true:
1) Prices are below the cloud 2) Senkou Span A is below Senkou Span B EITHER 3) the Tenkan-sen crosses down through the Kijun-sen OR 4) prices cross down through the Tenkan-sen
When either of these last two bearish criteria are met, the sell trade is opened at the start of the NEXT candle. The exit criteria is exit as soon as the Tenkan-sen crosses up through the Kijun-sen.
Let us now start the code – we import the necessary modules and retrieve our stock price data on which to run the strategy.
For completeness I have reproduced the relevant sections of code from the last “Part 1” article, allowing the creation of the Ichimoku constituents along with a Plotly chart of the resulting series.
import pandas as pd import numpy as np from pandas_datareader import data, wb import datetime import matplotlib.pyplot as plt import plotly.plotly as py import plotly.graph_objs as go from plotly.offline import init_notebook_mode, plot, iplot %matplotlib inline init_notebook_mode(connected=True) start = datetime.datetime(2000, 1, 1) end = datetime.datetime(2019, 1, 27) d=data.DataReader("F", 'yahoo', start, end)[['Open','High','Low','Close']] # Tenkan-sen (Conversion Line): (9-period high + 9-period low)/2)) nine_period_high = d['High'].rolling(window= 9).max() nine_period_low = d['Low'].rolling(window= 9).min() d['tenkan_sen'] = (nine_period_high + nine_period_low) /2 # Kijun-sen (Base Line): (26-period high + 26-period low)/2)) period26_high = d['High'].rolling(window=26).max() period26_low = d['Low'].rolling(window=26).min() d['kijun_sen'] = (period26_high + period26_low) / 2 # Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2)) d['senkou_span_a'] = ((d['tenkan_sen'] + d['kijun_sen']) / 2).shift(26) # Senkou Span B (Leading Span B): (52-period high + 52-period low)/2)) period52_high = d['High'].rolling(window=52).max() period52_low = d['Low'].rolling(window=52).min() d['senkou_span_b'] = ((period52_high + period52_low) / 2).shift(52) # The most current closing price plotted 26 time periods behind (optional) d['chikou_span'] = d['Close'].shift(-26) # Set colours for up and down candles INCREASING_COLOR = '#17BECF' DECREASING_COLOR = '#7F7F7F' # create list to hold dictionary with data for our first series to plot # (which is the candlestick element itself) data1 = [ dict( type = 'candlestick', open = d.Open, high = d.High, low = d.Low, close = d.Close, x = d.index, yaxis = 'y2', name = 'F', increasing = dict( line = dict( color = INCREASING_COLOR ) ), decreasing = dict( line = dict( color = DECREASING_COLOR ) ), ) ] # Create empty dictionary for later use to hold settings and layout options layout=dict() # create our main chart "Figure" object which consists of data to plot and layout settings fig = dict( data=data1, layout=layout ) # Assign various seeting and choices - background colour, range selector etc fig['layout']['plot_bgcolor'] = 'rgb(250, 250, 250)' fig['layout']['xaxis'] = dict( rangeselector = dict( visible = True ) ) fig['layout']['yaxis'] = dict( domain = [0, 0.2], showticklabels = False ) fig['layout']['yaxis2'] = dict( domain = [0.2, 0.8] ) fig['layout']['legend'] = dict( orientation = 'h', y=0.9, x=0.3, yanchor='bottom' ) fig['layout']['margin'] = dict( t=40, b=40, r=40, l=40 ) fig['layout']['height'] = 900 fig['layout']['width'] = 1300 # Populate the "rangeselector" object with necessary settings rangeselector=dict( visible = True, x = 0, y = 0.9, bgcolor = 'rgba(150, 200, 250, 0.4)', font = dict( size = 13 ), buttons=list([ dict(count=1, label='reset', step='all'), dict(count=1, label='1yr', step='year', stepmode='backward'), dict(count=3, label='3 mo', step='month', stepmode='backward'), dict(count=1, label='1 mo', step='month', stepmode='backward'), dict(step='all') ])) fig['layout']['xaxis']['rangeselector'] = rangeselector # Append the Ichimoku elements to the plot fig['data'].append( dict( x=d['tenkan_sen'].index, y=d['tenkan_sen'], type='scatter', mode='lines', line = dict( width = 1 ), marker = dict( color = '#33BDFF' ), yaxis = 'y2', name='tenkan_sen' ) ) fig['data'].append( dict( x=d['kijun_sen'].index, y=d['kijun_sen'], type='scatter', mode='lines', line = dict( width = 1 ), marker = dict( color = '#F1F316' ), yaxis = 'y2', name='kijun_sen' ) ) fig['data'].append( dict( x=d['senkou_span_a'].index, y=d['senkou_span_a'], type='scatter', mode='lines', line = dict( width = 1 ), marker = dict( color = '#228B22' ), yaxis = 'y2', name='senkou_span_a' ) ) fig['data'].append( dict( x=d['senkou_span_b'].index, y=d['senkou_span_b'], type='scatter', mode='lines', line = dict( width = 1 ),fill='tonexty', marker = dict( color = '#FF3342' ), yaxis = 'y2', name='senkou_span_b' ) ) fig['data'].append( dict( x=d['chikou_span'].index, y=d['chikou_span'], type='scatter', mode='lines', line = dict( width = 1 ), marker = dict( color = '#D105F5' ), yaxis = 'y2', name='chikou_span' ) ) # Set colour list for candlesticks colors = [] for i in range(len(d.Close)): if i != 0: if d.Close[i] > d.Close[i-1]: colors.append(INCREASING_COLOR) else: colors.append(DECREASING_COLOR) else: colors.append(DECREASING_COLOR) iplot( fig, filename = 'candlestick-ichimoku' )

Great it looks like we have correctly generated the base DataFrame with the Ichimoku constituents. Now time to start the trading logic.First we drop any “Na” values from our DataFrame and then set the “regime marker” that will signify whether the prices are currently above, below or within the cloud structure. Then we use the same idea to set a column signifying whether the Senkou Span A is above or below the Senkou Span B.
d.dropna(inplace=True) d['above_cloud'] = 0 d['above_cloud'] = np.where((d['Low'] > d['senkou_span_a']) & (d['Low'] > d['senkou_span_b'] ), 1, d['above_cloud']) d['above_cloud'] = np.where((d['High'] < d['senkou_span_a']) & (d['High'] < d['senkou_span_b']), -1, d['above_cloud']) d['A_above_B'] = np.where((d['senkou_span_a'] > d['senkou_span_b']), 1, -1)
The we proceed to create two new columns, firstly one identifying the rows of the data which correspond with an occurrence of a cross over of the Tenkan-sen and the Kiju-sen (1 is entered as a value if it is a cross up of the Tenkan-sen through the Kijun-sen and -1 if its a cross downwards). The second identifies the rows of data that correspond to the “Open” price with the Tenkan-sn line (similarly to above, 1 is entered as a value if it is a cross up of the price through the Tenkan-sen and -1 if its a cross downwards).
d['tenkan_kiju_cross'] = np.NaN d['tenkan_kiju_cross'] = np.where((d['tenkan_sen'].shift(1) <= d['kijun_sen'].shift(1)) & (d['tenkan_sen'] > d['kijun_sen']), 1, d['tenkan_kiju_cross']) d['tenkan_kiju_cross'] = np.where((d['tenkan_sen'].shift(1) >= d['kijun_sen'].shift(1)) & (d['tenkan_sen'] < d['kijun_sen']), -1, d['tenkan_kiju_cross']) d['price_tenkan_cross'] = np.NaN d['price_tenkan_cross'] = np.where((d['Open'].shift(1) <= d['tenkan_sen'].shift(1)) & (d['Open'] > d['tenkan_sen']), 1, d['price_tenkan_cross']) d['price_tenkan_cross'] = np.where((d['Open'].shift(1) >= d['tenkan_sen'].shift(1)) & (d['Open'] < d['tenkan_sen']), -1, d['price_tenkan_cross'])
The code below deals with the creation of our actual buy and sell entry signals.
Firstly we create a ‘buy’ columns and fill it with “np.NaN” values to act as a placeholder. For the buys, the value of a row in the ‘buy’ column is set to 1 if the first two criteria and met (Prices are above the cloud AND Senkou Span A is above Senkou Span B), and EITHER of the final 2 criteria are met (the Tenkan-sen crosses up through the Kijun-sen OR 4) prices cross up through the Tenkan-sen). For any rows where these criteria are not met, the value on the ‘buy’ column remains as a np.NaN value.
Then we identify the rows in the ‘buy’column that correspond with a positive instance of our closing criteria (i.e. a crossing down of the Tenkan-sen through the Kijun-sen) We fill these rows of the ‘buy’ column with a 0.
We then use the “ffill” method to “forward fill” our ‘buy’ column values to fill the gaps currently holding np.NaN values. so now the ‘buy’ column will hold a value of 1 while the strategy has signalled we should be in a long position, and a 0 while the strategy signals we should not be in a long position.
The same logic is then repeated in order to fill our strategy ‘sell’ columns with the signals of course reversed to correctly represent our strategy logic on the “short” side.
Finally the “buy” and “sell” column are added to create a new column holding our net strategy “position”.
d['buy'] = np.NaN d['buy'] = np.where((d['above_cloud'].shift(1) == 1) & (d['A_above_B'].shift(1) == 1) & ((d['tenkan_kiju_cross'].shift(1) == 1) | (d['price_tenkan_cross'].shift(1) == 1)), 1, d['buy']) d['buy'] = np.where(d['tenkan_kiju_cross'].shift(1) == -1, 0, d['buy']) d['buy'].ffill(inplace=True) d['sell'] = np.NaN d['sell'] = np.where((d['above_cloud'].shift(1) == -1) & (d['A_above_B'].shift(1) == -1) & ((d['tenkan_kiju_cross'].shift(1) == -1) | (d['price_tenkan_cross'].shift(1) == -1)), -1, d['sell']) d['sell'] = np.where(d['tenkan_kiju_cross'].shift(1) == 1, 0, d['sell']) d['sell'].ffill(inplace=True) d['position'] = d['buy'] + d['sell']
A “stock_returns” column is then created holding the log returns of the stock we are running the backtest on, which are then multiplied by the strategy “position” to correctly record the strategy returns depending on whether we are currently long or short.
Those two returns series are then cumulatively summed and plotted together for comparison using the built in Pandas plotting functionality.
d['stock_returns'] = np.log(d['Open']) - np.log(d['Open'].shift(1)) d['strategy_returns'] = d['stock_returns'] * d['position'] d[['stock_returns','strategy_returns']].cumsum().plot(figsize=(15,8))

In order to allow us to easily run the strategy over different stocks/assets, I have moved the code into a function which can be called with differing ticker symbols and date ranges passed as inputs.
def ichimoku(ticker, start, end): d=data.DataReader(ticker, 'yahoo', start, end)[['Open','High','Low','Close']] # Tenkan-sen (Conversion Line): (9-period high + 9-period low)/2)) nine_period_high = d['High'].rolling(window= 9).max() nine_period_low = d['Low'].rolling(window= 9).min() d['tenkan_sen'] = (nine_period_high + nine_period_low) /2 # Kijun-sen (Base Line): (26-period high + 26-period low)/2)) period26_high = d['High'].rolling(window=26).max() period26_low = d['Low'].rolling(window=26).min() d['kijun_sen'] = (period26_high + period26_low) / 2 # Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2)) d['senkou_span_a'] = ((d['tenkan_sen'] + d['kijun_sen']) / 2).shift(26) # Senkou Span B (Leading Span B): (52-period high + 52-period low)/2)) period52_high = d['High'].rolling(window=52).max() period52_low = d['Low'].rolling(window=52).min() d['senkou_span_b'] = ((period52_high + period52_low) / 2).shift(52) # The most current closing price plotted 26 time periods behind (optional) d['chikou_span'] = d['Close'].shift(-26) d.dropna(inplace=True) d['above_cloud'] = 0 d['above_cloud'] = np.where((d['Low'] > d['senkou_span_a']) & (d['Low'] > d['senkou_span_b'] ), 1, d['above_cloud']) d['above_cloud'] = np.where((d['High'] < d['senkou_span_a']) & (d['High'] < d['senkou_span_b']), -1, d['above_cloud']) d['A_above_B'] = np.where((d['senkou_span_a'] > d['senkou_span_b']), 1, -1) d['tenkan_kiju_cross'] = np.NaN d['tenkan_kiju_cross'] = np.where((d['tenkan_sen'].shift(1) <= d['kijun_sen'].shift(1)) & (d['tenkan_sen'] > d['kijun_sen']), 1, d['tenkan_kiju_cross']) d['tenkan_kiju_cross'] = np.where((d['tenkan_sen'].shift(1) >= d['kijun_sen'].shift(1)) & (d['tenkan_sen'] < d['kijun_sen']), -1, d['tenkan_kiju_cross']) d['price_tenkan_cross'] = np.NaN d['price_tenkan_cross'] = np.where((d['Open'].shift(1) <= d['tenkan_sen'].shift(1)) & (d['Open'] > d['tenkan_sen']), 1, d['price_tenkan_cross']) d['price_tenkan_cross'] = np.where((d['Open'].shift(1) >= d['tenkan_sen'].shift(1)) & (d['Open'] < d['tenkan_sen']), -1, d['price_tenkan_cross']) d['buy'] = np.NaN d['buy'] = np.where((d['above_cloud'].shift(1) == 1) & (d['A_above_B'].shift(1) == 1) & ((d['tenkan_kiju_cross'].shift(1) == 1) | (d['price_tenkan_cross'].shift(1) == 1)), 1, d['buy']) d['buy'] = np.where(d['tenkan_kiju_cross'].shift(1) == -1, 0, d['buy']) d['buy'].ffill(inplace=True) d['sell'] = np.NaN d['sell'] = np.where((d['above_cloud'].shift(1) == -1) & (d['A_above_B'].shift(1) == -1) & ((d['tenkan_kiju_cross'].shift(1) == -1) | (d['price_tenkan_cross'].shift(1) == -1)), -1, d['sell']) d['sell'] = np.where(d['tenkan_kiju_cross'].shift(1) == 1, 0, d['sell']) d['sell'].ffill(inplace=True) d['position'] = d['buy'] + d['sell'] d['stock_returns'] = np.log(d['Open']) - np.log(d['Open'].shift(1)) d['strategy_returns'] = d['stock_returns'] * d['position'] d[['stock_returns','strategy_returns']].cumsum().plot(figsize=(15,8))
Here is an example run for Netflix over the 2000 to 2019 time period.
ticker = 'NFLX' start = datetime.datetime(2000, 1, 1) end = datetime.datetime(2019, 1, 1) ichimoku(ticker, start, end)

I’ll leave it there for now as we have the basic functionality and output that we were aiming to achieve. The strategy could of course be adapted and improved no doubt by tweaking the rules and logic – perhaps setting a stop loss element or tweaking the entry/exit criteria, but I shall leave that up to you lot if you are so inclined to try.
Any questions or comments etc, please do leave them below and I will do my best to reply.
Until next time…
26 comments
I believe that you did not import numpy
Hi DA, thanks for pointing that out! I will fix it now 😉
Thanks for this blog. I have been getting into learning Python in order to automate my Ichimoku based trading strategy and found your website by surprise. In particular, i’d like to recreate this project: https://github.com/kumotrader/ichimoku-crypto, and turn it into a fully functioning bot for Telegram, which plots ichimoku charts on demand. It hasn’t worked out for me yet, and given that I have only recently started learning Python it might take a while for me to succeed in recreating this.
According to the picture posted on the GitHub page, the guy has managed to succesfully create Ichimoku clouds, so it might help you.
The settings that were used for the conversion line, baseline etc. are known as ‘doubled settings’ and are often used for cryptocurrency trading (20, 60, 120, 30)
Hi Kaijser, sorry I must have completely missed this comment when it was made… Thank you for the github link and hope your ichimoku project is going well!!
Hello, congrats for the post. Thanks for sharing your work.
I believe the shift for the senkou span b is 26, and not 52.
Hi Marcelo, thanks for the comment and for pointing that out. I had actually been notified previously about the calculation being made using the last 52 periods and then projecting/shifting it forward 26 periods as you say, rather than also shifting it by 52 periods. I had made the correction to part 1 of the article but I obviously forgot this part!! I shall make the changes as soon as I get a moment. Cheers
Thank you for this post! I am quite new in Python and just started to code Ichimoku-Signals. Do you have any idea how to implement multi timeframe indicators or do you know any helpful tutorial?! For example let’s assume that we calculate the Ichimoku cloud on H4-candlesticks and we want to receive a signal on the m30 data if the open price of the 30min is below and the close above the Span B?
Hi Chris, I guess one way would be to work with data that is of the granularity at which you wat to receive signals etc. – so in your example you would be working with 30 minute data, and then when you are writing the code that deals with the creation of the actual Ichimoku constituent series/columns/data – just muliply the rolling window periods so that they work on the same overall time window that you would like them to. So for instance, if you are basing your Ichimoku rolling window periods on the 4 Hour candlesticks – just multiply the window lengths by (4 hours / 30 minutes) 8 if you are uising 30 minutes data, and you should in essence be able to replicate what you are looking for!
I have missed to say, that the previous question relates to backtesting… It‘s not a problem with live Date. But I want to see the signals of the past.
Very helpful and well written
Hi,
I created a github repo based on your excellent post.
thanks for your great info.
https://github.com/shayegh/ichimoku-strategy
Great post, this is amazing and is helping me a lot. Though I have a simple question. Why did you shift the Tankan and the Kijun lines in the line of code:
d[‘tenkan_kiju_cross’] = np.where((d[‘tenkan_sen’].shift(1) <= d[‘kijun_sen’].shift(1)) & (d[‘tenkan_sen’] > d[‘kijun_sen’]), 1, d[‘tenkan_kiju_cross’])
Thank you so much!
Hey, great article, this was so much help! Thank you. I have a question though, why do you shift the lines by 1 during the d[‘tenkan_kiju_cross’]?
I don’t quite know what you are doing while calculating your returns, but if you just take the point/pip pnl, no matter how you slice it…it’s a loser.
gb = d.groupby((d[‘position’].shift() != d[‘position’]).cumsum())
kp=[]
for k, v in gb:
if v.iloc[0]['position'] == 1:
print 'long case'
print v
pnl = v.tail(1)['Close'] - v.iloc[0]['Open']
print "pnl = ", pnl
print '------------------------'
kp.append(float(pnl))
if v.iloc[0]['position'] == -1:
print 'short case'
print v
pnl = v.iloc[0]['Open'] - v.tail(1)['Close']
print "pnl = ", pnl
print '------------------------'
kp.append(float(pnl))
print ‘pnl sum’, sum(kp)
Hi Aaron, I have used your code for both tickers (F & NFLX) and both come back as positive (F = 12.32 & NFLX = 262.97) for the dates 2000-01-01 to 2019-01-27 so I am not sure we are looking at the same thing exactly.
I have calculated returns by summing the daily log returns, depending on the strategy position on the relevant day.
Are you sure you are looking at the same tickers over the same date range?
Sorry my bad, I am using the strategy on currency pairs.
Not a problem – I’ve done that more than a few times myself 😉
There are two boolean tests being carried out in the example line you posted; basically the test with the “shifted” data is looking at “yesterday’s” values. So here, we want to check whether the tenkan_sen was below the kijun_sen yesterday (shifted data), and above it today (non-shifted data) – this signifies an actual cross of the two lines.
Hi,
great article but some mentions from my side:
1.) if i want to watch on a stock until now, i have to d.drop(‘chikou_span’, axis=1, inplace=True) before d.dropna(inplace=True) or alternatively we have to use dropna with the subset-attribute, otherwise the NaNs will cause a drop of the newest data (for which chikou isn’t calculated right now)
2.) i need a d.fillna({‘buy’:0, ‘sell’:0}, inplace=True) before d[‘position’] = d[‘buy’] + d[‘sell’] to get strategy_returns for the very first buy/sell signal in given timeframe, otherwise the NaNs in buy/sell will lead to NaNs in position & strategy_returns
3.) i don’t understand, why the stock_returns are handled with np.log but not the strategy_returns when we want to compare those values … could you give me a hint to get the idea behind it?
Thanks again for this TOP article, it was very valuable for me to understand the Ichimoku approach.
BR
maexrock
instead of dropping chikou-span, i’d specified all the columns in parameter “columns” of pandas.DataFrame.drop(), except for the chikou-span,
i made a mistake in previous comment, it should be:
instead of dropping chikou-span, i’d specified all the columns in parameter “subset” of pandas.DataFrame.dropna(), except for the chikou-span,
i made a mistake in previous comment, it should be:
instead of dropping chikou-span, i’d specified all the columns, except for the chikou-span, in parameter “subset” of pandas.DataFrame.dropna(). Preferably in a previously defineded list for readability
isn’t code for d[‘tenkan_kiju_cross’] wrong?
it is:
d[‘tenkan_kiju_cross’] = np.where((d[‘tenkan_sen’].shift(1) <= d[‘kijun_sen’].shift(1)) & (d[‘tenkan_sen’] > d[‘kijun_sen’]), 1, d[‘tenkan_kiju_cross’]
what i would expect:
d[‘tenkan_kiju_cross’] = np.where((d[‘tenkan_sen’].shift(-1) <= d[‘kijun_sen’].shift(-1)) & (d[‘tenkan_sen’] > d[‘kijun_sen’]), 1, d[‘tenkan_kiju_cross’]
why?
to check the values from the date before, not after current date
Hi Chris – if you use -1 that will pull the value date back one from tomorrow to today. Using 1 pushes the value date forward from yesterday to today. So using 1 does check the values from the date before, not after the current date. 😀
thank you very much for reply, also i have one note:
using “close” values, instead of “high” or “low” values in some lines of code will restrict opening a position. Using closes is advised by Grzegorz Moskwa – polish ichimoku expert. I changed highs or lows for closes and efficiency evaluation goes higher for both ford and netflix, giving better result than the stock itself. If you wanted to see exactly where i put close, feel free to visit my github
https://github.com/ihavenoideaforusername/ichimoku_in_python
but i have to say, that i’m very beginner of programming.
Hi Chris – nice to see the improvements and the suggestions – I just had a quick Google for Grzegorz Moskwa, and I can see that the Ichimoku strategy is very much his area of expertise – I would defer to his good self when it comes to the finer points and approaches! Great to see your adaptations and improvements on Github!