Es gibt ein Update zu dem Tool. Nachdem bei quotemedia und IEX eine subscription benötigt wird, habe ich das Tool auf yahoo abgetimmt. Hier ein kleines python-script. Es genügt den Ansprüchen.
Aufruf mit python ccw.py <stock symbol>
Eventuell müssen zuvor Bibliotheken installiert werden
pip install <name der Bibliothek>
Auf Basis der Entscheidungsmatrix
1. Close>EMA21>EMA34>EMA55
2. ADX < 60
3. ProGo Prof > ProGo Public
wird erst dann ein Graph gezeigt, wenn alle Bedingungen der letzten 6 Handelstage erfüllt sind. Die Entscheidungsmatrix wird immer angezeigt.
Code:
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from functools import reduce # Valid in Python 2.6+, required in Python 3
import operator
import sys
#call with python ccw.py <stock symbol>
stock = sys.argv[1]
stock = yf.Ticker(stock)
data = stock.history(period='3y')
#This converts the date strings in the index into pandas datetime format:
data.index = pd.to_datetime(data.index)
#EMA
ema21 = data['Close'].ewm(span=21).mean()
data['EMA21'] = np.round(ema21, decimals=3)
ema34 = data['Close'].ewm(span=34).mean()
data['EMA34'] = np.round(ema34, decimals=3)
ema55 = data['Close'].ewm(span=55).mean()
data['EMA55'] = np.round(ema55, decimals=3)
#ProGo
#ProGo Public = Close (t-1) - Open (t)
#ProGo Prof = Close(t) - Open (t)
#shift Close to Close-1 for better calculating
data['Close-1']=data['Close'].shift(1)
data['ProGo Public']=data['Close-1'].subtract(data['Open'])
data['ProGo Prof']=data['Close'].subtract(data['Open'])
#smooth data
#SMA14
data['ProGo Pub SMA'] = data['ProGo Public'].rolling(window=14).mean()
data['ProGo Pro SMA'] = data['ProGo Prof'].rolling(window=14).mean()
del data['ProGo Public']
del data['ProGo Prof']
#adx
def ADX(data: pd.DataFrame(), interval: int=14):
data['-DM'] = data['Low'].shift(1) - data['Low']
data['+DM'] = data['High'] - data['High'].shift(1)
data['+DM'] = np.where((data['+DM'] > data['-DM']) & (data['+DM']>0), data['+DM'], 0.0)
data['-DM'] = np.where((data['-DM'] > data['+DM']) & (data['-DM']>0), data['-DM'], 0.0)
data['TR_TMP1'] = data['High'] - data['Low']
data['TR_TMP2'] = np.abs(data['High'] - data['Close'].shift(1))
data['TR_TMP3'] = np.abs(data['Low'] - data['Close'].shift(1))
data['TR'] = data[['TR_TMP1', 'TR_TMP2', 'TR_TMP3']].max(axis=1)
data['TR'+str(interval)] = data['TR'].rolling(interval).sum()
data['+DMI'+str(interval)] = data['+DM'].rolling(interval).sum()
data['-DMI'+str(interval)] = data['-DM'].rolling(interval).sum()
data['+DI'+str(interval)] = data['+DMI'+str(interval)] / data['TR'+str(interval)]*100
data['-DI'+str(interval)] = data['-DMI'+str(interval)] / data['TR'+str(interval)]*100
data['DI'+str(interval)+'-'] = abs(data['+DI'+str(interval)] - data['-DI'+str(interval)])
data['DI'+str(interval)] = data['+DI'+str(interval)] + data['-DI'+str(interval)]
data['DX'] = (data['DI'+str(interval)+'-'] / data['DI'+str(interval)])*100
data['ADX'+str(interval)] = data['DX'].rolling(interval).mean()
data['ADX'+str(interval)] = data['ADX'+str(interval)].fillna(data['ADX'+str(interval)].mean())
del data['TR_TMP1'], data['TR_TMP2'], data['TR_TMP3'], data['TR'], data['TR'+str(interval)]
del data['+DMI'+str(interval)], data['DI'+str(interval)+'-']
del data['DI'+str(interval)], data['-DMI'+str(interval)]
del data['+DI'+str(interval)], data['-DI'+str(interval)]
del data['DX']
del data['-DM'], data['+DM']
return data
data = ADX(data, 14)
#data of the last 90 days
data_short=data.iloc[-90:]
#compute decision matrix
data['ADX'] = (data['ADX14'] < 60) * 1
data['EMA21_Close'] = (data['Close'] >= data['EMA21'])
data['EMA34_EMA21'] = (data['EMA21'] >= data['EMA34'])
data['EMA55_EMA34'] = (data['EMA34'] >= data['EMA55'])
data['EMA'] = data['EMA21_Close'] * data['EMA34_EMA21'] * data['EMA55_EMA34'] * 1
data['ProGo'] = (data['ProGo Pro SMA'] >= data['ProGo Pub SMA']) * 1
#delete not necessary columns
del data['EMA21_Close']
del data['EMA34_EMA21']
del data['EMA55_EMA34']
#creating decision table
table = pd.concat([data['ADX'], data['EMA'], data['ADX']], axis=1, keys=['ADX', 'EMA', 'ProGo']).iloc[-6:]
# displaying decision table
fig, ax = plt.subplots()
fig.patch.set_visible(False)
ax.axis('off')
ax.table(cellText=table.values, colLabels=table.columns, loc='center')
fig.tight_layout()
plt.show()
#evaluate decision matrix by multiply each value with each other (product()-function in EXCEL)
decision = reduce(operator.mul, table[['ADX', 'EMA', 'ProGo']].product(axis=1), 1)
#displaying results if decision = 1
if (decision == 1):
fig = plt.figure(figsize = (8,8))
gs = fig.add_gridspec(3, hspace=0)
axs = gs.subplots(sharex=True)
axs[0].plot(data_short['Close'],'k', label='Price')
axs[0].plot(data_short['EMA21'],'r', label='EMA21')
axs[0].plot(data_short['EMA34'],'g', label='EMA34')
axs[0].plot(data_short['EMA55'],'b', label='EMA55')
axs[1].plot(data_short['ProGo Pro SMA'],'g', label='ProGo Pro')
axs[1].plot(data_short['ProGo Pub SMA'],'r', label='ProGo Pub')
axs[2].plot(data_short['ADX14'],label='ADX')
axs[0].legend()
axs[0].grid()
axs[1].legend()
axs[1].grid()
axs[2].legend()
axs[2].grid()
plt.show()
Aufruf mit python ccw.py AAPL erzeugt folgende Bilder:
Viel Spaß mit dem Script.