目錄
- talib提供給我們的K線形態
- pyqt5繪制K線圖
talib提供給我們的K線形態
在前面的博文中,我們介紹了talib提供給我們的6種K形態,不過,那只是博主通過講解一部分,讓大家認識如何使用talib區分K線,其實talib提供給我們的K線形態函式一共44個,那么如果通過軟體進行標記呢?
其實在眾多的股票交易軟體中,并不會主動給我們標記K線形態資料,而且K線形態這么多,哪怕程式員記下來恐怕也無能為力,所以,我們需要使用pyqt5設計界面給我們標記K線形態,并提示使用者那種K線預示漲,哪些K線預示跌,
這里,我們首先需要使用python的反射來完成用戶的切換,不然通過ifelse陳述句一句一句去區分呼叫,完全是重復的代碼勞動,得不償失,具體反射使用以及K線繪圖方式如下:
import talib
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import mpl_finance as mpf
from matplotlib import gridspec
class KMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
plt.rcParams['font.sans-serif'] = ['SimHei']
self.fig = Figure(figsize=(width, height), dpi=dpi)
FigureCanvas.__init__(self, self.fig)
spec = gridspec.GridSpec(4, 1, height_ratios=[3, 1, 1, 1])
self.ax1 = self.fig.add_subplot(spec[0])
self.ax2 = self.fig.add_subplot(spec[1])
self.ax3 = self.fig.add_subplot(spec[2])
self.ax4 = self.fig.add_subplot(spec[3])
self.setParent(parent)
self.k_text = ['十字星', '兩只烏鴉', '三只烏鴉', '三內部上漲和下跌', '三線打擊',
'三外部上漲和下跌', '南方三星', '三個白兵', '棄嬰', '大敵當前',
'捉腰帶線', '脫離', '收盤缺影線', '藏嬰吞沒', '反擊線'
, '烏云壓頂', '蜻蜓十字/T形十字', '吞噬模式', '十字暮星', '暮星',
'向上/下跳空并列陽線', '墓碑十字/倒T十字', '錘頭', '上吊線', '母子線',
'十字孕線', '風高浪大線', '陷阱', '修正陷阱', '家鴿',
'三胞胎烏鴉', '頸內線', '倒錘頭', '反沖形態', '由較長缺影線決定的反沖形態',
'停頓形態', '條形三明治', '探水竿', '跳空并列陰陽線', '插入',
'三星', '奇特三河床', '向上跳空的兩只烏鴉', '上升/下降跳空三法']
FigureCanvas.updateGeometry(self)
def start_staict_plot(self, df, method="CDLDOJISTAR", numb=0):
self.ax1.clear()
self.ax2.clear()
self.ax3.clear()
self.ax4.clear()
self.fig.canvas.draw_idle()
mytalib = talib
f = getattr(mytalib, method)
df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].apply(lambda x: x.strftime('%Y-%m-%d'))
mpf.candlestick2_ochl(self.ax1, df["open"], df["close"], df["high"], df["low"], width=0.6, colorup='r',
colordown='green',
alpha=1.0)
df['star'] = f(df['open'].values, df['high'].values, df['low'].values, df['close'].values)
pattern = df[(df['star'] == 100) | (df['star'] == -100)]
for key, val in df.items():
for index, today in pattern.iterrows():
x_posit = df.index.get_loc(index)
self.ax1.annotate("{}\n{}".format(self.k_text[numb], today["date"]), xy=(x_posit, today["high"]),
xytext=(0, pattern["close"].mean()), xycoords="data",
fontsize=8, textcoords="offset points",
arrowprops=dict(arrowstyle="simple", color="r"))
df["SMA5"] = df["close"].rolling(5).mean()
df["SMA10"] = df["close"].rolling(10).mean()
df["SMA30"] = df["close"].rolling(30).mean()
df["SMA60"] = df["close"].rolling(60).mean()
self.ax1.plot(np.arange(0, len(df)), df['SMA5'], label="5日均線") # 繪制5日均線
self.ax1.plot(np.arange(0, len(df)), df['SMA10'], label="10日均線") # 繪制10日均線
self.ax1.plot(np.arange(0, len(df)), df['SMA30'], label="30日均線") # 繪制30日均線
self.ax1.plot(np.arange(0, len(df)), df['SMA60'], label="60日均線") # 繪制30日均線
self.ax1.legend()
red_pred = np.where(df["close"] > df["open"], df["volume"], 0)
blue_pred = np.where(df["close"] < df["open"], df["volume"], 0)
self.ax2.bar(np.arange(0, len(df)), red_pred, facecolor="red")
self.ax2.bar(np.arange(0, len(df)), blue_pred, facecolor="blue")
self.ax2.set(ylabel=u"成交量")
low_list = df["close"].rolling(9, min_periods=1).min()
high_list = df["high"].rolling(9, min_periods=1).max()
rsv = (df["close"] - low_list) / (high_list - low_list) * 100
df["K"] = rsv.ewm(com=2, adjust=False).mean()
df["D"] = df["K"].ewm(com=2, adjust=False).mean()
df["J"] = 3 * df["K"] - 2 * df["D"]
self.ax3.plot(df["date"], df["K"], label="K")
self.ax3.plot(df["date"], df["D"], label="D")
self.ax3.plot(df["date"], df["J"], label="J")
self.ax3.legend()
self.ax3.set(ylabel=u"KDJ")
EMA1 = df["close"].ewm(span=12, adjust=False).mean()
EMA2 = df["close"].ewm(span=26, adjust=False).mean()
DIF = EMA1 - EMA2
DEA = DIF.ewm(span=9, adjust=False).mean()
BAR = 2 * (DIF - DEA)
red_bar = np.where(BAR > 0, BAR, 0)
blue_bar = np.where(BAR < 0, BAR, 0)
self.ax4.plot(np.arange(0, len(df)), DIF)
self.ax4.plot(np.arange(0, len(df)), DEA)
self.ax4.bar(np.arange(0, len(df)), red_bar, color="red")
self.ax4.bar(np.arange(0, len(df)), blue_bar, color="blue")
self.ax4.set(ylabel=u"MACD")
self.ax1.xaxis.set_major_locator(ticker.MaxNLocator(9))
def format_date(x, pos=None):
if x < 0 or x > len(df['date']) - 1:
return ''
return df['date'][int(x)]
self.ax1.xaxis.set_major_formatter(ticker.FuncFormatter(format_date))
self.ax1.grid(True)
plt.setp(self.ax1.get_xticklabels(), visible=True)
plt.setp(self.ax2.get_xticklabels(), visible=False)
plt.setp(self.ax3.get_xticklabels(), visible=False)
plt.setp(self.ax4.get_xticklabels(), visible=False)
plt.setp(plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
這里,我們通過getattr函式,將talib庫賦值給它,然后,只需要通過方法名就可以切換K線形態資料,這里博主為了簡便,沒有將文本資料單獨設定為全域變數,在實際的開發中,還是要將其獨立,免得重復copy造成代碼混亂,
pyqt5繪制K線圖
如上面代碼所示,我們不僅僅繪制了K線圖,而且還繪制了成交量,KDJ,以及MACD,這里對比起來看某個股票往往更具有參考價值,那么界面的代碼如下所示:
class MyFrom(QMainWindow):
# K線模塊
def init_kTab(self):
self.grid_k = QGridLayout()
self.grid_k.setSpacing(5)
k_text = ['十字星', '兩只烏鴉', '三只烏鴉', '三內部上漲和下跌', '三線打擊',
'三外部上漲和下跌', '南方三星', '三個白兵', '棄嬰', '大敵當前',
'捉腰帶線', '脫離', '收盤缺影線', '藏嬰吞沒', '反擊線'
, '烏云壓頂', '蜻蜓十字/T形十字', '吞噬模式', '十字暮星', '暮星',
'向上/下跳空并列陽線', '墓碑十字/倒T十字', '錘頭', '上吊線', '母子線',
'十字孕線', '風高浪大線', '陷阱', '修正陷阱', '家鴿',
'三胞胎烏鴉', '頸內線', '倒錘頭', '反沖形態', '由較長缺影線決定的反沖形態',
'停頓形態', '條形三明治', '探水竿', '跳空并列陰陽線', '插入',
'三星', '奇特三河床', '向上跳空的兩只烏鴉', '上升/下降跳空三法']
self.k_content = ['預示著當前趨勢反轉', '預示股價下跌', '預示股價下跌', '預示著股價上漲', '預示股價下跌',
'預示著股價上漲', '預示下跌趨勢反轉,股價上升', '預示股價上升', '預示趨勢反轉,發生在頂部下跌,底部上漲', '預示股價下跌'
, '收盤價接近最高價,預示價格上漲', '預示價格上漲', '預示著趨勢持續', '預示著底部反轉', '預示趨勢反轉'
, '預示著股價下跌', '預示趨勢反轉', '預示趨勢反轉', '預示頂部反轉', '預示頂部反轉',
'趨勢持續', '預示底部反轉', '處于下跌趨勢底部,預示反轉', '處于上升趨勢的頂部,預示著趨勢反轉', '預示趨勢反轉,股價上升',
'預示著趨勢反轉', '預示著趨勢反轉', '趨勢繼續', '趨勢繼續', '預示著趨勢反轉',
'預示價格下跌', '預示著下跌繼續', '在下跌趨勢底部,預示著趨勢反轉', '存在跳空缺口', '與反沖形態類似,較長缺影線決定價格的漲跌',
'預示著上漲結束', '預示著股價上漲', '預示趨勢反轉', '上升趨勢持續', '預示著趨勢持續',
'預示著趨勢反轉', '收盤價不高于第二日收盤價,預示著反轉,第二日下影線越長可能性越大', '預示股價下跌', '收盤價高于第一日收盤價,預示股價上升']
self.K_method = ['CDLDOJISTAR', 'CDL2CROWS', 'CDL3BLACKCROWS', 'CDL3INSIDE', 'CDL3LINESTRIKE',
'CDL3OUTSIDE', 'CDL3STARSINSOUTH', 'CDL3WHITESOLDIERS', 'CDLABANDONEDBABY', 'CDLADVANCEBLOCK',
'CDLBELTHOLD', 'CDLBREAKAWAY', 'CDLCLOSINGMARUBOZU', 'CDLCONCEALBABYSWALL', 'CDLCOUNTERATTACK',
'CDLDARKCLOUDCOVER', 'CDLDRAGONFLYDOJI', 'CDLENGULFING', 'CDLEVENINGDOJISTAR',
'CDLEVENINGSTAR',
'CDLGAPSIDESIDEWHITE', 'CDLGRAVESTONEDOJI', 'CDLHAMMER', 'CDLHANGINGMAN', 'CDLHARAMI',
'CDLHARAMICROSS', 'CDLHIGHWAVE', 'CDLHIKKAKE', 'CDLHIKKAKEMOD', 'CDLHOMINGPIGEON',
'CDLIDENTICAL3CROWS', 'CDLINNECK', 'CDLINVERTEDHAMMER', 'CDLKICKING', 'CDLKICKINGBYLENGTH',
'CDLSTALLEDPATTERN', 'CDLSTICKSANDWICH', 'CDLTAKURI', 'CDLTASUKIGAP', 'CDLTHRUSTING',
'CDLTRISTAR', 'CDLUNIQUE3RIVER', 'CDLUPSIDEGAP2CROWS', 'CDLXSIDEGAP3METHODS']
self.cb = QComboBox()
self.cb.addItems(k_text)
self.cb.currentIndexChanged.connect(self.selectionchange)
self.cb_label = QLabel("預示著當前趨勢反轉")
self.k_label = QLabel("選擇K線圖的形態:")
self.grid_k.addWidget(self.k_label, 0, 0, 1, 1)
self.grid_k.addWidget(self.cb, 0, 2, 1, 2)
self.grid_k.addWidget(self.cb_label, 0, 5, 1, 5)
self.kTab2.setLayout(self.grid_k)
self.kLineThread = KLineThread()
self.kLineThread.setValue("sh600690")
self.kLineThread._signal.connect(self.kLineThread_callbacklog)
self.kLineThread.start()
def kLineThread_callbacklog(self, df):
self.df = df
self.mplK = KMplCanvas(self, width=5, height=4, dpi=100)
self.mplK.start_staict_plot(df)
mpl_ntb = NavigationToolbar(self.mplK, self)
mpl_ntb.setStyleSheet("background-color:white;color:black")
self.grid_k.addWidget(self.mplK, 2, 0, 13, 12)
self.grid_k.addWidget(mpl_ntb, 2, 0, 1, 5)
def selectionchange(self, i):
self.cb_label.setText(self.k_content[i])
self.mplK.start_staict_plot(self.df, self.K_method[i], i)
同樣的,我們這里也需要通過執行緒獲取K線圖的基本資料,具體代碼如下所示:
from PyQt5 import QtCore
from PyQt5.QtCore import pyqtSignal
import pandas as pd
from pandas import DataFrame
class KLineThread(QtCore.QThread):
_signal = pyqtSignal(DataFrame)
def __init__(self):
super(KLineThread, self).__init__()
def setValue(self, shareNumber):
self.share_num = shareNumber
def run(self):
df = pd.read_excel("海爾智家k.xlsx")
self._signal.emit(df)
需要注意的是,如上篇博文說的一樣,最好是先獲取網路資料存盤在xlsx中后,在獲取詳細資料,這樣在非交易時間段不會造成延遲,后續,這里我們會通過資料庫進行更改,暫時先這里處理,
運行之后,顯示效果如下圖所示:

在界面中,我們可以通過QComboBox控制元件進行切換K線圖,同時圖片也會標記符合K線圖的資料,而且文字上面也會提示這種K線圖代表什么,意味著什么,這是不是散戶最想擁有的K線識別器呢?畢竟一般股票交易軟體都需要付費才能這么玩,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/258435.html
標籤:python
