[PYTHON] [Systre] Achetez et vendez avec le MACD moyen mobile ♬

La dernière fois, j'ai écrit sur STC (Stocastic Oscilator) en guise d'introduction à Systre. Cette fois, je voudrais reproduire MACD (Moving Average Convergence Divergence), qui est plus précis (le signal de trading sort plus rapidement) en Python, et faire une décomposition pour faire un jugement facile à comprendre. Vous obtiendrez un graphique comme celui ci-dessous.

【référence】 ① Qu'est-ce que MACD? Système évolutif de ligne moyenne mobile où les signaux de trading apparaissent tôt!?Comparaison du code de moyenne mobile exponentielle (EMA) écrit en PythonMoyenne mobile @wikipedia

Ce que j'ai fait

・ J'ai essayé d'en faire une évolution de Stocastic Oscilator ・ À propos de l'EMA qui apparaît dans le calcul de MACD ・ Explication du code MACD

・ J'ai essayé d'en faire une évolution de Stocastic Oscilator

La dernière fois, même si c'était facile à voir après l'introduction de Decompose, j'ai émis un jugement en lisant le graphique ci-dessous. stc_%K%D_9437.JP_now.png Ici, tout en jugeant que 20% ou moins est survendu et 80% ou plus est suracheté, le point de changement où la ligne bleue apparaît est le signe d'achat, et inversement lorsque la ligne orange apparaît. Juges comme signe de vente. Afin de juger cela systématiquement, afin d'inclure ces éléments de 20% et 80%, (% K-% D) /% K peut être calculé et jugé par la fonction suivante.

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

Le calcul avec cette fonction donne le graphique inférieur suivant. En regardant ce graphique, le signal est plus supprimé et le moment de vendre et d'acheter est clair. Cela semble être la limite d'une moyenne mobile simple normale. close_stc_%K%D_9437.JP_trendnow2020-01-01.png Par conséquent, le graphique ci-dessus montre:

Trend=Observed-Cycle
SMA sur 5 jours (moyenne mobile simple), SMA sur 25 jours
Signal d'achat / vente = 100*(5 jours SMA-25 jours SMA)/5 jours SMA

・ À propos de l'EMA qui apparaît dans le calcul de MACD

Écrivons à propos de l'EMA (moyenne mobile exponentielle). La définition est la suivante, comme indiqué dans la référence ③ La formule de calcul de l'EMA lorsque t ≧ 3 est la suivante.

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

Ici, $ S_ {{t}} $ est l'EMA à un certain moment t, et $ Y_ {{t-1}} $ est la valeur observée à un certain moment t sur la série temporelle. De plus, environ $ \ alpha = {2 \ over {N + 1}} $. L'utilisation de cet EMA, MACD, etc.

MACD = EMA de 12 jours-EMA de 26 jours
Signal = MACD EMA 9 jours
Histogramme = Signal-MACD

Par conséquent, par rapport à l'oscillateur stocastique ci-dessus, on peut considérer que la moyenne mobile simple est remplacée par la moyenne mobile exponentielle et que le nombre de jours de la moyenne mobile à long et à court terme est légèrement modifié. L'histogramme correspond au graphique du bas ci-dessus.

・ Explication du code MACD

Je pense que le code suivant est le résultat final de ce système. J'expliquerai celui facile à comprendre en utilisant le code de Référence ②.

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

Voici la fonction d'acquisition de données.

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

Réglez les paramètres.

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

Stockez les données dans la liste avec df ['Close'] .values.tolist ().

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

Des données telles que «[2978.67, 3016.01, 2972.77]» sont sorties. Calculez l'EMA sur n jours ci-dessous. Dans la référence (2), a a été fixé à 0,15, mais ici il est important de calculer a.

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

Avec la fonction ci-dessus, l'EMA de 12 jours, etc. peut être facilement calculée. De plus, MACD et Signal peuvent être facilement calculés comme suit.

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

Ici, l'axe horizontal est représenté par une chaîne numérique. Vous pouvez le décrire explicitement comme l'axe horizontal du graphique, mais ce n'est pas nécessaire ici. Tout ce que vous avez à faire est de dessiner un graphique. Pour le moment, ax2.bar (ind, hist_) est un endroit gênant.

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()

Le résultat est affiché comme suit. ema_decompose_%5K%25D_9437.JP_seriesnow2020-01-01.png Le résultat de la décomposition est aussi simple que ci-dessous. Ce qui suit est le résultat de 9437 NTT Docomo, mais il semble bientôt être platen. Figure_1.png En d'autres termes, qu'il y ait du bruit ou non, le fait est que la partie où l'histogramme passe du moins au plus est achetée, et inversement la partie où elle passe du plus au moins est vendue, donc c'est presque dans le mouvement réel. On dirait qu'il y en a. ** Il s'avère que c'est un indice efficace pour l'achat et la vente à long terme. ** ** J'expliquerai l'autre axe horizontal dessiné par date en prime.

Résumé

・ J'ai essayé d'exprimer Stocastic Oscilator avec un index facile à comprendre. ・ Les indicateurs utilisant MACD semblent être efficaces pour le trading à long terme.

・ Après tout, il est si facile à comprendre que je veux l'appliquer à la soi-disant systole.

prime

Cela ne change pas grand-chose en termes de code, mais il était très difficile de mettre l'axe horizontal à la date, je vais donc l'afficher. Je pense que vous pouvez en profiter si vous le lisez attentivement.

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() #C'est le 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

[Systre] Achetez et vendez avec le MACD moyen mobile ♬
Moyenne mobile avec numpy
Graphique à barres de bougie et tracé de la moyenne mobile
Couper et prendre une moyenne mobile pondérée
Fonction tyrolienne pour acheter et vendre des actions
J'ai comparé la moyenne mobile du type de filtre IIR avec les pandas et scipy
[Cistre] Dépasse la MACD ♬