[PYTHON] [Cistre] Buy and sell with moving average MACD ♬

Last time, I wrote about STC (Stocastic Oscilator) as an introduction to Systre. This time, I would like to reproduce MACD (Moving Average Convergence Divergence), which is more accurate (the trading signal comes out faster) in Python, and make an easy-to-understand judgment by decomposing. You will get the following graph.

【reference】 ① What is MACD? Evolutionary system of moving averages where trading signals appear early !?Comparison of exponential moving average (EMA) code written in PythonMoving average @wikipedia

What i did

・ I tried to make it an evolution of Stocastic Oscilator ・ About EMA that appears in the calculation of MACD ・ MACD code explanation

・ I tried to make it an evolution of Stocastic Oscilator

Last time, although it was easy to see after introducing Decompose, I made a judgment by reading from the graph below. stc_%K%D_9437.JP_now.png Here, while judging that 20% or less is oversold and 80% or more is overbought, the change point where the blue line comes up is the buy sign, and conversely when the orange line comes up. Judges as a sell sign. In order to judge this systematically, in order to include these 20% and 80% elements, (% K-% D) /% K can be calculated and judged by the following function.

def calc_dff(dK,dD):
    dff= dK.copy()
    for j in range(len(dK)):
        #print(j)
        if dK[j]-dD[j]>0:
            dff[j]=100*(dK[j]-dD[j])/(abs(dK[j])+1)
        else:
            dff[j]=100*(dK[j]-dD[j])/(100-abs(dK[j])+1)
    return dff

Calculating with this function gives the bottom graph below. Looking at this graph, the signal is more suppressed and the time to sell and buy is clear. This seems to be the limit of a normal simple moving average. close_stc_%K%D_9437.JP_trendnow2020-01-01.png Therefore, the graph above shows:

Trend=Observed-Cycle
5-day SMA (simple moving average), 25-day SMA
Trading signal = 100*(5 days SMA-25 days SMA)/5 days SMA

・ About EMA that appears in the calculation of MACD

Let's write about EMA (Exponential Moving Average). The definition is as follows as shown in Reference ③ The formula for calculating EMA when t ≧ 3 is as follows.

S_{{t}}=\alpha \times Y_{{t-1}}+(1-\alpha )\times S_{{t-1}}

Here, $ S_ {{t}} $ is the EMA at a certain point in time t, and $ Y_ {{t-1}} $ is an observation value at a certain point in time t on the time series. Also, approximately $ \ alpha = {2 \ over {N + 1}} $. Using this EMA, MACD etc. are defined as follows.

MACD = 12-day EMA-26-day EMA
Signal = MACD 9-day EMA
Histogram = Signal-MACD

Therefore, when compared with the above Stocastic Oscilator, it can be considered that the simple moving average is replaced with the exponential moving average and the number of days of the long-term and short-term moving average is slightly changed. The histogram corresponds to the bottom graph above.

・ MACD code explanation

I think the following code is the final result of this systole. I will explain what is easy to understand using the code in Reference (2).

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
from pandas_datareader import data
import statsmodels.api as sm
from statsmodels.tsa.seasonal import STL

The following is the data acquisition function.

def get_stock(stock,start,end):
    df = data.DataReader(stock, 'stooq',start)["Close"]
    df = df.iloc[::-1]
    return df[start:end]

Set the parameters.

stock0 = '9437'
stock = stock0 + '.JP'
bunseki = "series"
start = dt.date(2020,1,1)
end = dt.date(2020,6,5)
df = pd.DataFrame(get_stock(stock, start, end))
series=df['Close']
cycle, trend = sm.tsa.filters.hpfilter(series, 144)
df['Close']=trend

Store the data in list with df ['Close'] .values.tolist ().

gwalk = df['Close'].values.tolist()
print(gwalk[0:3])

Data such as [2978.67, 3016.01, 2972.77] is output. Calculate the n-day EMA below. In Reference (2), a was fixed at 0.15, but here it is important to calculate a.

def EMA1(x, n):
    a= 2/(n+1)
    return pd.Series(x).ewm(alpha=a).mean()

With the above function, 12-day EMA etc. can be easily calculated. In addition, MACD and Signal can be easily calculated as follows.

y12 = EMA1(gwalk, 12)
y26 = EMA1(gwalk, 26)
MACD = y12 -y26
signal = EMA1(MACD, 9)
hist_=MACD-signal

Here, the horizontal axis is represented by a numerical string. You can explicitly describe it as the horizontal axis of the plot, but it is not necessary here. All you have to do is draw a graph. For the time being, ax2.bar (ind, hist_) is a troublesome place.

ind = np.arange(len(signal))
fig, (ax1,ax2) = plt.subplots(2,1,figsize=(1.6180 * 12, 4*2),dpi=200)
ax1.plot(gwalk,label="series")
ax1.plot(y12,label="y12")
ax1.plot(y26,label="y26")
ax2.plot(MACD,label="MACD")
ax2.plot(signal,label="signal")
ax2.bar(ind,hist_)
ax1.legend()
ax2.legend()
ax1.grid()
ax2.grid()
plt.show()
plt.savefig("ema_.png ")
plt.close()

The result is output as follows. ema_decompose_%5K%25D_9437.JP_seriesnow2020-01-01.png The result of decompose is as simple as below. The following is the result of 9437 NTT DoCoMo, but it seems to be platen soon. Figure_1.png In other words, regardless of whether there is noise or not, the point is that you buy at the part where the histogram changes from minus to plus, and conversely, the part where it changes from plus to minus is for sale, so it is almost in actual movement It looks like there is. ** It turns out that it is an effective index for long-span trading. ** ** I will explain the other horizontal axis drawn by date as a bonus.

Summary

・ I tried to express Stocastic Oscilator with an easy-to-understand index. ・ Indicators using MACD seem to be effective for long-span trading.

・ After all, it is so easy to understand that I want to apply it to so-called systole.

bonus

It doesn't change much in terms of code, but it was very difficult to set the horizontal axis to the date, so I will post it. I think you can enjoy it if you read it carefully.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import datetime as dt
from pandas_datareader import data
import statsmodels.api as sm
from statsmodels.tsa.seasonal import STL

def get_stock(stock,start,end):
    df = data.DataReader(stock, 'stooq',start)["Close"]
    df = df.iloc[::-1]
    return df[start:end]

from numba import jit
@jit(nopython=True)
def EMA3(x, n):
    alpha = 2/(n+1)
    y = np.empty_like(x)
    y[0] = x[0]
    for i in range(1,len(x)):
        y[i] = alpha*x[i] + (1-alpha)*y[i-1]
    return y

def EMA1(x, n):
    a= 2/(n+1)
    return pd.Series(x).ewm(alpha=a).mean()

def calc_dff(dK,dD):
    dff= dK.copy()
    for j in range(len(dK)):
        dff[j]=100*(dK[j]-dD[j])/(abs(dK[j])+abs(dD[j])+1)
    return dff

stock0 = '9437'
stock = stock0 + '.JP'
start = dt.date(2020,1,1)
end = dt.date(2020,6,5)
df = pd.DataFrame(get_stock(stock, start, end))
date_df=df['Close'].index.tolist() #This is the point
print(date_df[0:30])
series = df['Close'].values.tolist()

bunseki = "trend" #series" #cycle" #trend
cycle, trend = sm.tsa.filters.hpfilter(series, 144)
series2 = trend

y12 = EMA3(series2, 12)
y26 = EMA3(series2, 26)
MACD = y12 -y26
signal = EMA3(MACD, 9)
hist_=MACD-signal

ind3=date_df[:]
print(len(series),len(ind3))

fig, (ax1,ax2) = plt.subplots(2,1,figsize=(1.6180 * 8, 4*2),dpi=200)
ax1.plot(ind3,series,label="series")
ax1.plot(ind3,series2,label="series2")
ax1.plot(ind3,y12,label="y12")
ax1.plot(ind3,y26,label="y26")
ax2.plot(ind3,MACD,label="MACD")
ax2.plot(ind3,signal,label="signal")
ax2.bar(ind3,hist_)
ax1.legend()
ax2.legend()
ax1.grid()
ax2.grid()
plt.savefig("./stock/{}/ema_decompose_%5K%25D_{}_{}now{}.png ".format(stock0,stock,bunseki,start))
plt.pause(1)
plt.close()

df['Close']=series  #series" #cycle" #trend
df['series2']=series2
df['y12'] = EMA1(df['Close'], 12)
df['y26'] =  EMA1(df['Close'], 26)
df['MACD'] = df['y12'] -df['y26']
df['signal'] = EMA1(df['MACD'], 9)
df['hist_']=df['MACD']-df['signal']
date_df=df['Close'].index.tolist()
print(df[0:30])

fig, (ax1,ax2) = plt.subplots(2,1,figsize=(1.6180 * 8, 4*2),dpi=200)
ax1.plot(df['Close'],label="series")
ax1.plot(df['series2'],label="series2")
ax1.plot(df['y12'],label="y12")
ax1.plot(df['y26'],label="y26")
ax2.plot(df['MACD'],label="MACD")
ax2.plot(df['signal'],label="signal")
ax2.bar(date_df,df['hist_'])
ax1.legend()
ax2.legend()
ax1.grid()
ax2.grid()
plt.savefig("./stock/{}/ema_df_decompose_%5K%25D_{}_{}now{}.png ".format(stock0,stock,bunseki,start))
plt.pause(1)
plt.close()

Recommended Posts

[Cistre] Buy and sell with moving average MACD ♬
Moving average with numpy
Candlestick chart and moving average plot
Trim and take a weighted moving average
zipline Function to buy and sell stocks
I compared the moving average of IIR filter type with pandas and scipy
[Cistre] Beyond MACD ♬