請依序嘗試以下三種方法
pip install TA-Lib
!
!brew install ta-lib
windows還可以直接使用wheel檔下載:
(a) 請點網址
(b) 找尋適合的版本的檔案
ex:
TA_Lib‑0.4.17‑cp37‑cp37m‑win_amd64.whl (cp右邊的是python版本,‑win_amd右邊是windows位元)
如何看python版本
1.spyder視窗上方
2.IPython console顯示
如何看windows位元
1.點選左下角搜尋
2.搜尋'系統資訊'
3.一堆項目中找到系統類型
import talib
import pandas as pd
tech = pd.Series([1,2,3,4,5,6,7,8])
print(talib.MA(tech,5))
(1)英文github
https://github.com/mrjbq7/ta-lib
文檔
https://mrjbq7.github.io/ta-lib/doc_index.html
(2)中文翻譯github
https://github.com/HuaRongSAO/talib-document
import talib
import pandas_datareader as pdr
import numpy as np
data = pdr.DataReader('0050.TW', 'yahoo') # 從yahoo數據庫得到數據
close = data['Close'] # 股票收盤價
# 印出來看看!
ma5 = talib.MA(close,5) # 5日均線
print(ma5)
補充
numpy的np.nan
在pandas中視為None
(空)值。
不過使用bool()函數
轉型,python視為True
# 將倒數第10個值改成缺失值
close.iloc[-10] = np.nan # np.nan類似None
# 查看是不是變成缺失值了
print(close.tail(11)) # tail可以看尾端的數據
ma5 = talib.MA(close,5)
print(ma5.tail(11))
close = close.ffill() # 將缺失值變成前一個數
data = data.ffill() # 或者將每一欄的缺失值變成前一個數
# 查看是不是變成缺失值了
print(close.tail(11))
ma5 = talib.MA(close,5).tail(11)
print(ma5)
RSI
是經典的轉折指標。傳統將RSI>70
視為行情過熱,RSI<30
視為行情過冷。
rsi = talib.RSI(close,14)
#印出來看看!
print(rsi)
KD
需要用到高低收三種資料,詳細KD原理可以參考文章
傳統方法是將K
黃金交叉(向上交叉)D
,視為買進訊號,反之為賣出訊號。
high = data['High']
low = data['Low']
close = data['Close']
slowk, slowd = talib.STOCH(high,
low,
close,
slowk_period=5,
slowd_period=5,
fastk_period=9)
#印出來看看!
print(slowk)
print(slowd)
matplotlib
是一個簡單好用的python視覺化繪圖庫。
後面的範例我們會直接使用pandas搭配其中的功能
pip install matplotlib
試著在IPyton console 輸入 %matplotlib qt5, 可以切換圖形介面
而用完之可以輸入 %matplotlib inline 換回原本圖形介面
一次執行兩行,輕鬆繪出美美的圖
close.plot()
ma5.plot()
使用pandas DataFrame的plot
功能繪圖,可輕鬆達到效果
ploter = pd.DataFrame({'Close':close,'RSI':rsi})
ploter.plot(subplots=True) # subplots 功能可以將內容分開成不同圖片(子圖)
加上水平線
ax = ploter.plot(subplots=True)
print(ax)
ax[1].axhline(70)
ax[1].axhline(30)
較正統,也比較靈活
# 製作兩個畫板
fig, ax = plt.subplots(2, 1) # 2*1的子圖
# -----畫第一張圖---- #
close.plot(ax=ax[0], sharex=True)
# 加上標題與圖例
# close.plot(title='Close',legend=True,ax=ax[0])
# -----畫第二張圖----- #
# k,d要先fillna(將缺失值填補)x軸才不會錯呦!
slowk.fillna(0).plot(ax=ax[1], sharex=True)
slowd.fillna(0).plot(ax=ax[1], sharex=True)
# 加上標題與圖例
# slowk.fillna(0).plot(sharex=True,title='KD',legend=True,ax=ax[1])
# slowd.fillna(0).plot(sharex=True,legend=True,ax=ax[1])
ax[1].axhline(30) # 30水平線
ax[1].axhline(70) # 70水平線
plt.tight_layout() # 加上這個可以調整成舒適的格式
撰寫策略時,策略的邏輯核心就是條件
。
條件最終都會以True
或False
的方式呈現。
由於這些條件是可以重複拿出來被使用的,所以我們可以用DataFrame整理寫過的條件。
將數值互相比大小,即為比較法。或者達到
程式碼,以黃金交叉為例
condition = pd.DataFrame([])
# 將數值放進condition中並命名
condition['股價>均線5'] = close > ma5
condition['標準差>1.5'] = close.rolling(10).std() > 1.5
# 黃金交叉做法
a1 = k
b1 = d
a2 = a1.shift(1)
b2 = b1.shift(1)
crossover = (a1>a2) & (a1>b1) & (b2>a2)
condition['KD黃金交叉'] = crossover
以下為黃金交叉及死亡交叉函數,可直接取用
def crossover(over,down):
a1 = over
b1 = down
a2 = a1.shift(1)
b2 = b1.shift(1)
crossover = (a1>a2) & (a1>b1) & (b2>a2)
return crossover
# 死亡交叉
def crossunder(down,over):
a1 = down
b1 = over
a2 = a1.shift(1)
b2 = b1.shift(1)
crossdown = (a1<a2) & (a1<b1) & (b2<a2)
return crossdown
信號是將各種條件濃縮成進場和出場的唯一條件
條件
condition = pd.DataFrame([])
condition['KD黃金交叉'] = crossover(k,d)
condition['KD死亡交叉'] = crossunder(k,d)
建立一個空的訊號DataFrame表,存放買進及賣出訊號
signal = pd.DataFrame([])
# 各項條件用'&'方式處理
# '*1'是為了轉成數字訊號方便大家看
signal['買進'] = (condition['KD黃金交叉'] & condition['D值低檔']) * 1
signal['賣出'] = condition['KD死亡交叉'] * -1
交易策略:買進一單位,並續抱到直到賣出訊號出現為止
這邊的操作是讓買進與賣出訊號變成一進一出(pair)的訊號
此操作可有可無,供學員大家參考
signal['持有'] = signal['買進'] + signal['賣出']
signal['持有'] = signal['持有'].replace(0,method='ffill')
signal['持有'] = signal['持有'].replace(-1, 0)
def tool(x):
if x[0]==1 and x[1]==0:
return 1
else:
return x[-1]
signal['持有'] = signal['持有'].rolling(2).apply(tool, raw=True).fillna(0)
建立一個總資料表research
將所需資訊放在一起
research = pd.DataFrame([])
research = research.join([data['Open']],how='outer') # 開盤價資訊
research = research.join([close],how='outer') # 收盤價資訊
research = research.join([signal],how='outer') # 訊號
research['權益'] = np.nan # 拿來紀錄權益用的欄位
# 計入初始資金
capital = 100000
# 記錄權益(目前現金+部位價值)
equity = capital
# 記錄部位狀況
marketposition=0
# 記錄買入股數
share=0
# 記錄入場價得
entryprice = 0
"""
research = research.to_dict('record')
使用這行會加快速度很多。
原理是把dataframe轉成成list+字典形式,
不過在下面for要改成:
for values in research:
"""
for index,values in research.iterrows():
'''step3,賣出'''
if marketposition == 1 and values['賣出'] == -1:
# sell this bar at close
# 賣在什麼價格
exitprice = values['Close']
# 帳戶處理:收款
capital += exitprice * share * 1000 # share就是上一次買進的股數
marketposition=0
share = 0
'''step1,買進'''
if marketposition == 0 and values['買進'] == 1:
#buy this bar at close
#買了多少股
share = capital // (values['Close']*1000)
#買在什麼價格
entryprice = values['Close']
#帳戶處理:扣款
capital -= entryprice * share * 1000
# 將狀態改為"買進"
marketposition=1
'''step2,記錄權益狀況'''
if marketposition == 1:
#權益就是假設直接賣出可以獲得多少錢(目前現金+部位價值)
equity = capital + (share * values['Close'] * 1000)
else:
equity = capital
# 在research中記錄權益
research.loc[index,'權益'] = equity
# 將訊號產生的地方塗上顏色
hold = close.copy()
hold[signal['持有']==0] = np.nan
fig, ax = plt.subplots(4, 1)# 4*1的子圖
ax[0].set_title('Equity') # 將0號圖標上標題
research['權益'].plot(ax=ax[0]) # 繪出權益
ax[1].set_title('Close') # 將1號圖標上標題
close.plot(ax=ax[1]) # 繪出股價
hold.plot(ax=ax[1]) # 將買進的區域塗上顏色
#k,d要先fillna(將缺失值填補)x軸才不會錯呦!
ax[2].set_title('KD') # 將2號圖標上標題
k.fillna(0).plot(sharex=True,ax=ax[2]) # 繪出K值
d.fillna(0).plot(sharex=True,ax=ax[2]) # 繪出D值
ax[3].set_title('Signal') # 將3號圖標上標題
signal['持有'].plot(sharex=True,ax=ax[3]) # 繪出訊號
plt.tight_layout() # 將畫板調成適合的大小
請說明比大盤績效好或壞的原因
試說明,有沒有讓績效更好的做法