Posts

Attempting to improve on the MACD strategy in python

avatar of @chasmic-cosm
25
@chasmic-cosm
·
·
0 views
·
2 min read

In my previous post I introduced a rudimentary trading strategy based on the MACD. This strategy produced lots of spurious trading signals and would probably not be particularly effective in the wild. In this post I'll explore some attempts to improve the quality of signal produced by the MACD strategy.

Baseline results

In order to evaluate the performance of each approach, we need to have a reference. The naïve MACD strategy produces lots of bad trade signals over the test data.

Approach 1: Positivity of the MACD

We can try to filter out bad trade signals by insisting that the MACD be positive in order to trigger a trade.

import numpy as np 
 
def macd_strategy2(ohlcv): 
    """ 
    Calculate the macd of a stock, decide whether to buy, sell, or hold based on signal behaviour 
    Inputs: 
        ohlcv:  numpy array -   A 5 x N matrix with rows corresponding to 
                                o, h, l, c, v respectively 
    Outputs: 
        status: string      -   "BUY", "SELL", or "HOLD" 
    """ 
    typical = typical_price(ohlcv) 
    macd, macd_sig, macd_hist = macd(typical) 
    macd_hist = macd_hist[::-1] # reversed MACD histogram 
    macd = macd[::-1] 
 
    if macd_hist[0] > 0 and macd_hist[1] <= 0 and macd[0] >= 0: 
        return "BUY" 
    elif macd_hist[0] < 0 and macd_hist[1] >= 0: 
        return "SELL" 
    else: 
        return "HOLD" 

This seems to filter out quite a few of the bad buy signals, however this strategy isn't applicable for sell signals.

Approach 2: Positivity of the derivative

Another potential way to filter out signals from the MACD is to look at the sign of the first derivative. In order to calculate the first derivative, we can use a rudimentary method such as a finite difference scheme:

import numpy as np 
 
def first_deriv(signal, dt): 
    """ 
    Calculate the first derivative using finite difference method 
    Inputs: 
        signal: numpy array -   A sequence of price points in time 
        dt:     int         -   Bucket size in seconds 
    Outputs: 
        dx:     numpy array -   First derivative at each point in points 
    """ 
    dx = np.zeros(len(signal)) 
    dx[0] = (signal[1] - signal[0]) / dt 
    dx[-1] = (signal[-1] - signal[-2]) 
    for i in range(1, len(dx) - 1): 
        dx[i] = (signal[i + 1] - signal[i - 1]) / (2 * dt) 
    return dx 

Then integrating this into the MACD strategy:

def macd_strategy3(ohlcv): 
    """ 
    Calculate the macd of a stock, decide whether to buy, sell, or 
    hold based on signal behaviour 
    Inputs: 
        ohlcv:  numpy array -   A 5 x N matrix with rows corresponding to 
                                o, h, l, c, v respectively 
    Outputs: 
        status: string      -   "BUY", "SELL", or "HOLD" 
    """ 
    typical = ta.typical_price(ohlcv) 
    macd, macd_sig, macd_hist = ta.macd(typical) 
    dx = ta.first_deriv(typical, 1)[::-1] 
    macd_hist = macd_hist[::-1] # reversed MACD histogram 
    if macd_hist[0] > 0 and macd_hist[1] <= 0 and dx[0] > 0: 
        return "BUY" 
    elif macd_hist[0] < 0 and macd_hist[1] >= 0 and dx[0] < 0: 
        return "SELL" 
    else: 
        return "HOLD" 

I had high hopes for this approach, but it didn't seem to have much effect at all.

Results

Neither of these approaches do a particularly good job of cleaning up the signals generated by the original MACD strategy. Usually the MACD is used in conjunction with other indicators in order to provide more reliable trading signals.

Posted Using LeoFinance