avatarSofien Kaabar, CFA

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

6197

Abstract

High, Low, <span class="hljs-keyword">and</span> <span class="hljs-keyword">Close</span> <span class="hljs-keyword">and</span> it refers <span class="hljs-keyword">to</span> the standard historical data file</pre></div><div id="9aa5"><pre><span class="hljs-title">def</span> ma(<span class="hljs-class"><span class="hljs-keyword">data</span>, lookback, close, where): </span>

<span class="hljs-class"><span class="hljs-keyword">data</span> = adder(<span class="hljs-title">data</span>, 1)</span>

for i <span class="hljs-keyword">in</span> range(len(<span class="hljs-class"><span class="hljs-keyword">data</span>)):</span>
       
        try:
            
            <span class="hljs-class"><span class="hljs-keyword">data</span>[i, where] = (<span class="hljs-title">data</span>[<span class="hljs-title">i</span> - <span class="hljs-title">lookback</span> + 1:<span class="hljs-title">i</span> + 1, <span class="hljs-title">close</span>].<span class="hljs-title">mean</span>())</span>
        
        except <span class="hljs-type">IndexError</span>:
            
            pass
        
<span class="hljs-class"><span class="hljs-keyword">data</span> = jump(<span class="hljs-title">data</span>, <span class="hljs-title">lookback</span>)</span>

return <span class="hljs-class"><span class="hljs-keyword">data</span></span></pre></div><p id="33ba">The below states that the moving average function will be called on the array named my_data for a lookback period of 200, on the column indexed at 3 (closing prices in an OHLC array). The moving average values will then be put in the column indexed at 4 which is the one we have added using the adder function.</p><div id="9da1"><pre><span class="hljs-attribute">my_data</span> = ma(my_data, <span class="hljs-number">200</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>)</pre></div><p id="9cfd">Check out my weekly market sentiment report to understand the current positioning and to estimate the future direction of several major markets through complex and simple models working side by side. Find out more about the report through this link:</p><div id="7415" class="link-block">
      <a href="https://coalescence.substack.com/">
        <div>
          <div>
            <h2>Coalescence</h2>
            <div><h3>A Weekly Report Covering FX &amp; Equities Market Positioning Using Complex Models. Let me read it first This site requires…</h3></div>
            <div><p>coalescence.substack.com</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*7zo8Jv6sfnts5WCL)"></div>
          </div>
        </div>
      </a>
    </div><h1 id="8210">The MACD</h1><p id="c94f">The MACD is probably the second most known oscillator after the RSI. One that is heavily followed by traders. It stands for moving average convergence divergence and it is used mainly for divergences and flips. Many people also consider it a trend-following indicator but others use graphical analysis on it to find reversal points, making the MACD a versatile indicator.</p><figure id="6795"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*pZSPLgauEjYhzVfN.png"><figcaption><b>EURUSD in the first panel with the MACD in the second panel.</b></figcaption></figure><p id="b45c">How is the MACD calculated? It is the difference between the 26-period exponential moving average applied to the closing price and the 12-period exponential moving average also applied to the closing price. The value found after taking the difference is called the MACD line. The 9-period exponential moving average of that calculation is called the MACD signal.</p><figure id="e7d8"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*OR9NZ3MDistMP9-v.png"><figcaption><b>USDCHF in the first panel with the MACD in the second panel.</b></figcaption></figure><p id="7a02">As a reminder, the MACD line is the difference between the two exponential moving averages which is plotted as histograms in green and red. The MACD signal is simply the 9-period exponential moving average of the MACD line.</p><h1 id="46fd">The Schaff Trend Cycle</h1><p id="cf14">Created by Doug Schaff, the idea of the indicator is that FX pairs accelerate and decelerate in cycles. It is used through what we call a barrier exit. As the Schaff Trend Cycle is bounded between 0 and 100, when it surpasses 25, a bullish signal is given and when it breaks 75, a bearish signal is given.</p><figure id="ad8c"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*tXCCDDfLsvuuK-eG.png"><figcaption><b>EURUSD in the first panel with the STC in the second panel.</b></figcaption></figure><p id="e250">The indicator is composed of a MACD using a 23 and a 50-period exponential moving averages (thus, the difference between the two) and a 10-period normalization applied to the MACD values.</p><p id="4ecd">But you do not need to burden yourself with the calculation, as they are not universally clear, the formulas presented elsewhere in the sources I have found are not really possible as they would entail a lot of infinite values. Therefore, I provided a simple fix that is incorporated in the function below.</p><p id="da4c">We can code the Schaff Trend Cycle in the following manner on OHLC data array with a few columns to spare:</p><div id="a0ed"><pre>def stc(<span class="hljs-keyword">Data</span>, st_ema, lt_ema, stoch_lookback, what, <span class="hljs-keyword">where</span>):

<span class="hljs-keyword">Data</span> = ema(<span class="hljs-keyword">Data</span>, <span class="hljs-number">2</span>, st_ema, what, <span class="hljs-keyword">where</span>)
<span class="hljs-keyword">Data</span> = ema(<span class="hljs-keyword">Data</span>, <span class="hljs-number">2</span>, lt_ema, what, <span class="hljs-keyword">where</span> + <span class="hljs-number">1</span>)

# MACD Line
<span class="hljs-keyword">Data</span>[:, <span class="hljs-keyword">where</span> + <span class="hljs-number">2</span>] = <span class="

Options

hljs-keyword">Data</span>[:, <span class="hljs-keyword">where</span>] - <span class="hljs-keyword">Data</span>[:, <span class="hljs-keyword">where</span> + <span class="hljs-number">1</span>]</pre></div><div id="099a"><pre> # %K for i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(len(<span class="hljs-keyword">Data</span>)):

        try:
            <span class="hljs-keyword">Data</span>[i, <span class="hljs-keyword">where</span> + <span class="hljs-number">3</span>] = <span class="hljs-number">100</span> * (<span class="hljs-keyword">Data</span>[i, <span class="hljs-keyword">where</span> + <span class="hljs-number">2</span>] - <span class="hljs-built_in">min</span>(<span class="hljs-keyword">Data</span>[i - stoch_lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-keyword">where</span> + <span class="hljs-number">2</span>])) / (<span class="hljs-built_in">max</span>(<span class="hljs-keyword">Data</span>[i - stoch_lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-keyword">where</span> + <span class="hljs-number">2</span>]) - <span class="hljs-built_in">min</span>(<span class="hljs-keyword">Data</span>[i - stoch_lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-keyword">where</span> + <span class="hljs-number">2</span>]))
        
        except ValueError:
            <span class="hljs-keyword">pass</span>

# %D        
<span class="hljs-keyword">Data</span> = ma(<span class="hljs-keyword">Data</span>, <span class="hljs-number">3</span>, <span class="hljs-keyword">where</span> + <span class="hljs-number">3</span>, <span class="hljs-keyword">where</span> + <span class="hljs-number">4</span>)

<span class="hljs-keyword">return</span> <span class="hljs-keyword">Data</span></pre></div><figure id="9d9e"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*2sk5dL62wDvXK9o2.png"><figcaption><b>USDCHF in the first panel with the STC in the second panel.</b></figcaption></figure><blockquote id="d655"><p>The Schaff Trend Cycle is also referred to as the STC.</p></blockquote><p id="6df2">The STC is used as follows:</p><ul><li><b>A long (Buy) signal is generated whenever the STC surpasses the 25 line, thus confirming the bullish trend.</b></li><li><b>A short (Sell) signal is generated whenever the STC breaks the 75 line, thus confirming the bearish trend.</b></li></ul><p id="3618">I have recently partnered with Lumiwealth, and if you want to see how to create all sorts of algorithms yourself, feel free to check out the below link. From algorithmic trading to blockchain and machine learning, they have hands-on detailed courses that I highly recommend.</p><div id="fead" class="link-block">
      <a href="https://www.lumiwealth.com/algorithmic-trading-landing-page/?utm_source=influence&amp;utm_medium=medium&amp;utm_campaign=sofien">
        <div>
          <div>
            <h2>Learn Algorithmic Trading with Python Lumiwealth</h2>
            <div><h3>undefined</h3></div>
            <div><p>undefined</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*FbCz_ARtbOdywMlC)"></div>
          </div>
        </div>
      </a>
    </div><h1 id="e420">Summary</h1><p id="05a4">To sum up, what I am trying to do is to simply contribute to the world of objective technical analysis which is promoting more transparent techniques and strategies that need to be back-tested before being implemented. This way, technical analysis will get rid of the bad reputation of being subjective and scientifically unfounded.</p><p id="570c">Medium is a hub to interesting reads. I read a lot of articles before I decided to start writing. Consider joining Medium using my referral link (at <b>NO </b>additional cost to you).</p><div id="de8c" class="link-block">
      <a href="https://kaabar-sofien.medium.com/membership">
        <div>
          <div>
            <h2>Join Medium with my referral link — Sofien Kaabar</h2>
            <div><h3>As a Medium member, a portion of your membership fee goes to writers you read, and you get full access to every story…</h3></div>
            <div><p>kaabar-sofien.medium.com</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*XBqK-oHjNF_4ydU8)"></div>
          </div>
        </div>
      </a>
    </div><p id="5d41">I recommend you always follow the the below steps whenever you come across a trading technique or strategy:</p><ul><li>Have a critical mindset and get rid of any emotions.</li><li>Back-test it using real life simulation and conditions.</li><li>If you find potential, try optimizing it and running a forward test.</li><li>Always include transaction costs and any slippage simulation in your tests.</li><li>Always include risk management and position sizing in your tests.</li></ul><p id="beb3">Finally, even after making sure of the above, stay careful and monitor the strategy because market dynamics may shift and make the strategy unprofitable.</p><p id="4f75">For the paperback link of the book, you may use the following link:</p><div id="355f" class="link-block">
      <a href="https://www.amazon.com/dp/B09VG3SH2P?&amp;linkCode=sl1&amp;tag=sofien-20&amp;linkId=f0daa140733c5f6b08c1e744bd1b98b5&amp;language=en_US&amp;ref_=as_li_ss_tl">
        <div>
          <div>
            <h2>Contrarian Trading Strategies in Python</h2>
            <div><h3>Amazon.com: Contrarian Trading Strategies in Python: 9798434008075: Kaabar, Sofien: Books</h3></div>
            <div><p>www.amazon.co</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*C7k3f3kawsSsQCVn)"></div>
          </div>
        </div>
      </a>
    </div></article></body>

The Schaff Trend Cycle

Developing the Schaff Trend Cycle Indicator in Python to Trade the Trend

There are two desired outcomes of a trend-following strategy, the first one is entering on time and the second one is exiting on time. We always seek to detect the changes of trends as early as possible and then want to exit after having exploited most of it. This is easier said than done and many indicators are lagging. In this article we will discuss a supposedly slightly less lagging version of an indicator that resembles the MACD.

I have released a new book called “Contrarian Trading Strategies in Python”. It features a lot of advanced contrarian indicators and strategies with a GitHub page dedicated to the continuously updated code. If you are interested, you could buy the PDF version directly through a PayPal payment of 9.99 EUR.

Please include your email in the note before paying so that you receive it on the right address. Also, once you receive it, make sure to download it through google drive.

The Concept of Moving Averages

Moving averages help us confirm and ride the trend. They are the most known technical indicator and this is because of their simplicity and their proven track record of adding value to the analyses. We can use them to find support and resistance levels, stops and targets, and to understand the underlying trend. This versatility makes them an indispensable tool in our trading arsenal.

EURUSD hourly values with the 200-hour simple moving average.

As the name suggests, this is your plain simple mean that is used everywhere in statistics and basically any other part in our lives. It is simply the total values of the observations divided by the number of observations. Mathematically speaking, it can be written down as:

We can see that the moving average is providing decent dynamic support and resistance levels from where we can place our orders in case the market goes down there. The code for the moving average can be written down as the following:

# The function to add a number of columns inside an array
def adder(Data, times):
    
    for i in range(1, times + 1):
    
        new_col = np.zeros((len(Data), 1), dtype = float)
        Data = np.append(Data, new_col, axis = 1)
        
    return Data
# The function to delete a number of columns starting from an index
def deleter(Data, index, times):
    
    for i in range(1, times + 1):
    
        Data = np.delete(Data, index, axis = 1)
        
    return Data
    
# The function to delete a number of rows from the beginning
def jump(Data, jump):
    
    Data = Data[jump:, ]
    
    return Data
# Example of adding 3 empty columns to an array
my_ohlc_array = adder(my_ohlc_array, 3)
# Example of deleting the 2 columns after the column indexed at 3
my_ohlc_array = deleter(my_ohlc_array, 3, 2)
# Example of deleting the first 20 rows
my_ohlc_array = jump(my_ohlc_array, 20)
# Remember, OHLC is an abbreviation of Open, High, Low, and Close and it refers to the standard historical data file
def ma(data, lookback, close, where): 
    
    data = adder(data, 1)
    
    for i in range(len(data)):
           
            try:
                
                data[i, where] = (data[i - lookback + 1:i + 1, close].mean())
            
            except IndexError:
                
                pass
            
    data = jump(data, lookback)
    
    return data

The below states that the moving average function will be called on the array named my_data for a lookback period of 200, on the column indexed at 3 (closing prices in an OHLC array). The moving average values will then be put in the column indexed at 4 which is the one we have added using the adder function.

my_data = ma(my_data, 200, 3, 4)

Check out my weekly market sentiment report to understand the current positioning and to estimate the future direction of several major markets through complex and simple models working side by side. Find out more about the report through this link:

The MACD

The MACD is probably the second most known oscillator after the RSI. One that is heavily followed by traders. It stands for moving average convergence divergence and it is used mainly for divergences and flips. Many people also consider it a trend-following indicator but others use graphical analysis on it to find reversal points, making the MACD a versatile indicator.

EURUSD in the first panel with the MACD in the second panel.

How is the MACD calculated? It is the difference between the 26-period exponential moving average applied to the closing price and the 12-period exponential moving average also applied to the closing price. The value found after taking the difference is called the MACD line. The 9-period exponential moving average of that calculation is called the MACD signal.

USDCHF in the first panel with the MACD in the second panel.

As a reminder, the MACD line is the difference between the two exponential moving averages which is plotted as histograms in green and red. The MACD signal is simply the 9-period exponential moving average of the MACD line.

The Schaff Trend Cycle

Created by Doug Schaff, the idea of the indicator is that FX pairs accelerate and decelerate in cycles. It is used through what we call a barrier exit. As the Schaff Trend Cycle is bounded between 0 and 100, when it surpasses 25, a bullish signal is given and when it breaks 75, a bearish signal is given.

EURUSD in the first panel with the STC in the second panel.

The indicator is composed of a MACD using a 23 and a 50-period exponential moving averages (thus, the difference between the two) and a 10-period normalization applied to the MACD values.

But you do not need to burden yourself with the calculation, as they are not universally clear, the formulas presented elsewhere in the sources I have found are not really possible as they would entail a lot of infinite values. Therefore, I provided a simple fix that is incorporated in the function below.

We can code the Schaff Trend Cycle in the following manner on OHLC data array with a few columns to spare:

def stc(Data, st_ema, lt_ema, stoch_lookback, what, where):
    
    Data = ema(Data, 2, st_ema, what, where)
    Data = ema(Data, 2, lt_ema, what, where + 1)
    
    # MACD Line
    Data[:, where + 2] = Data[:, where] - Data[:, where + 1]
    # %K
    for i in range(len(Data)):
            
            try:
                Data[i, where + 3] = 100 * (Data[i, where + 2] - min(Data[i - stoch_lookback + 1:i + 1, where + 2])) / (max(Data[i - stoch_lookback + 1:i + 1, where + 2]) - min(Data[i - stoch_lookback + 1:i + 1, where + 2]))
            
            except ValueError:
                pass
    
    # %D        
    Data = ma(Data, 3, where + 3, where + 4)
    
    return Data
USDCHF in the first panel with the STC in the second panel.

The Schaff Trend Cycle is also referred to as the STC.

The STC is used as follows:

  • A long (Buy) signal is generated whenever the STC surpasses the 25 line, thus confirming the bullish trend.
  • A short (Sell) signal is generated whenever the STC breaks the 75 line, thus confirming the bearish trend.

I have recently partnered with Lumiwealth, and if you want to see how to create all sorts of algorithms yourself, feel free to check out the below link. From algorithmic trading to blockchain and machine learning, they have hands-on detailed courses that I highly recommend.

Summary

To sum up, what I am trying to do is to simply contribute to the world of objective technical analysis which is promoting more transparent techniques and strategies that need to be back-tested before being implemented. This way, technical analysis will get rid of the bad reputation of being subjective and scientifically unfounded.

Medium is a hub to interesting reads. I read a lot of articles before I decided to start writing. Consider joining Medium using my referral link (at NO additional cost to you).

I recommend you always follow the the below steps whenever you come across a trading technique or strategy:

  • Have a critical mindset and get rid of any emotions.
  • Back-test it using real life simulation and conditions.
  • If you find potential, try optimizing it and running a forward test.
  • Always include transaction costs and any slippage simulation in your tests.
  • Always include risk management and position sizing in your tests.

Finally, even after making sure of the above, stay careful and monitor the strategy because market dynamics may shift and make the strategy unprofitable.

For the paperback link of the book, you may use the following link:

Trading
Investing
Data Science
Finance
Cryptocurrency
Recommended from ReadMedium