最近股票圈最熱門的話題,不外乎就是「台積電」,以前我們都說,市值太大的股票,上漲的幅度有限。但是台積電果然是國家棟梁,身為台股最大市值的股票,竟然可以漲停板!然而現在這麼高了,還安全嗎?怎麼才能安全的享受台積電的上漲的獲利,又可以在下跌時加碼呢?我們可以針對台積電,用 Python 研發擇時買賣,文末附上完整程式範例!
3步驟帶你分析台積電
這篇文章會分享怎麼研發台積電的投資策略,主要有三個步驟:
- 使用 Colab 並安裝 yfinance 、 backtesting、talib 的函式庫
- 下載台積電股價歷史紀錄,研發買賣訊號
- 回測交易結果分析,並且研究策略如何優化
1. 使用 Colab 並下載環境
要建構一個股票策略,只要會基本的 Python ,就可以開始了,我們使用 Colab 來當作撰寫 Python 的平台,這是 Google 佛心推出的,讓我們可以線上撰寫程式,而且完全免費!我自己已經把幾乎所有程式碼搬到 Colab 上了!雖然速度比桌機稍慢,但是可以雲端任何地點編輯,就算換電腦也不用擔心!
安裝 Package
我們今天要用的 Package,有兩個,一個是 yfinance ,負責下載 yahoo finance 上的股價資料,另外一個是 backtesting,顧名思義就是用來研發策略用的!但研發策略,有時候會需要製作技術指標,並根據技術指標來交易,所以需要用到 talib 這個 Package,我們可以用簡單的三行指令完成安裝:
!pip install yfinance
!pip install Backtesting
!pip install talib-binary
上述三行,只要在程式碼輸入欄輸入,系統就會幫你安裝好這三款 package,這三行的第一個字符是驚嘆號,代表我們要執行 Shell 的語法,不是 Python 的語法!假如你不是用 Colab,而是用個人電腦,也可以在打開 Shell 輸入這些指令,記得將指令的驚嘆號移除喔!
2. 下載台積電股價,研發買賣訊號!
首先,我們先來下載台積電的歷史紀錄,在下方的程式碼中,我們已經幫大家寫好一個函式,叫做「get_historical_data」,可以直接呼叫它來獲取股價。由於 yfinance 的歷史紀錄算是滿豐富的,所以有很多股票都可以下載,包含美股台股,例如蘋果(AAPL),特斯拉(TSLA),微軟(MSFT),然而台股的部分,比較可惜的地方,就是只有上市資料,如台積電(2330.TW),以下是完整的範例。你可以 參考 yahoo finance 來下載你有興趣股票!
import yfinance as yf
import pandas as pd
def get_historical_data(ticker):
d = yf.Ticker(ticker)
df = d.history(period="max")
df.columns = df.columns.str.lower()
df.columns = pd.Series(df.columns).str.capitalize().values
return df.dropna()
df = get_historical_data('2330.TW')
df
策略訊號研發
有了股票的歷史紀錄,就可以來研發策略了,由於 Python 是個執行速度很慢的語言(比起 C、C++),所以我們不太使用 for 迴圈 來回測,而是用向量矩陣的方式產生訊號,速度會快很多,其中的「sma1」、「sma2」、「signal_long」、「signal_short」都是時間序列,下方為均線為範例,假如你不喜歡均線,可以參考 talib 來製作你有興趣的技術指標喔!
import talib
# compute simple moving average using talib
sma1 = talib.SMA(df.Close, timeperiod=20)
sma2 = talib.SMA(df.Close, timeperiod=60)
# compute buy and sell signals (golden cross and death cross)
signal_long = (sma1 > sma2) & (sma1.shift() < sma2.shift())
signal_short = (sma1 < sma2) & (sma1.shift() > sma2.shift())
# combine long and short signals
signal = signal_long.copy()
signal[signal_short] = -1
程式碼看不懂嗎?沒關係,我們將這些時間序列 2020 年的數值繪製出來:
df.Close['2020'].plot()
sma1['2020'].plot()
sma2['2020'].plot()
signal['2020'].astype(int).plot(secondary_y=True)
- 藍色:df.Close —–> 台積電的股價(一飛沖天!)
- 黃色:sma1 —-> 20日均線
- 綠色:sma2 —-> 60日均線
- 紅色:signal —-> 買賣訊號
接下來,我們就可以根據上圖中,紅色訊號為 1 時買入, -1 時賣出,這樣的的方式來交易,但是效果會如何呢?沒有人知道,所以我們還要進行「回測」,也就是將此策略放在歷史上模擬交易的報酬率!
3. 回測和參數優化
接下來我們就可以來測測看,究竟這樣子買台積電效果如何?我們可以用 backtesting 這個工具來幫我們回測,完整的程式碼如下,雖然有點長,但你會發現核心程式碼,跟剛剛是非常類似的!所以不用擔心太複雜!你也可以參考 backtesting 的官方教學,來獲得更詳細的用法喔!
from backtesting import Backtest, Strategy
class Strategy(Strategy):
n1 = 20
n2 = 60
def init(self):
super().init()
# Precompute the two moving averages
close = pd.Series(self.data.Close)
sma1 = talib.SMA(close, timeperiod=self.n1)
sma2 = talib.SMA(close, timeperiod=self.n2)
# Precompute signal
signal_long = (sma1 > sma2) & (sma1.shift() < sma2.shift())
signal_short = (sma1 < sma2) & (sma1.shift() > sma2.shift())
# combine signal
signal = signal_long
signal[signal_short] = -1
# plot sma
self.I(lambda x: sma1, 'sma1')
self.I(lambda x: sma2, 'sma2')
# set signal to trade
self.signal = self.I(lambda x: signal, 'signal')
def next(self):
super().next()
entry_size = self.signal[-1]
if entry_size > 0:
self.buy()
elif entry_size < 0:
for trade in self.trades:
trade.close()
bt = Backtest(df, Strategy)
result1 = bt.run()
bt.plot()
上圖就是我們的回測結果,這是一個動態的圖表,所以我們可以將一部分放大:
上圖從上到下,總共有五個小圖,我們一張一張解釋:
圖一:為最後的總績效結果(藍色線段),代表策略的報酬率,從2000到現在可以獲利約400%,而當中的紅色水平線段,代表最久沒有創新高的時間段,這段時間可能會讓你懷疑,這個策略有沒有效果,而放棄策略,這段時間當然是越短越好!
圖二:有很多的三角形,假如是正三角就是做多,倒三角就是做空,我們這次寫的策略是做多的策略!所以不會有做空的倒三角喔!另外顏色代表獲利或是虧損,綠色為獲利,紅色為虧損,這些三角形的高度代表獲利或虧損的程度,以虛線做區分,虛線上方是獲利,而虛線下方式虧損,可以看到這種交易方法 2008 年以後每次虧損不會太多,獲利有時候還滿驚人的!
圖三是交易的明細,除了股價 K 棒外,我們也看到了兩條均線(藍色跟橘色),方便我們核對交易的時間,另外我們可以看到綠色和紅色的虛線,每一條虛線都代表一次交易,虛線的起始和結束,代表交易的價格跟時間,綠色代表獲利,而紅色代表虧損。
第四和第五張圖,則是成交量以及 signal 訊號,此策略就是模擬 signal 訊號為 1 時買進,而 -1 時賣出,比對其他圖片的數據,非常合理!
策略效果不夠好?尋找最佳參數!
剛剛我們用的均線是20日跟60日,來做交易,然而這是最好的均線嗎?我們可以將這兩個參數,當成策略的參數,分別叫 n1 和 n2 ,透過暴力枚舉(range(5, 200)),來從 5 到 200 裡面挑出 Sharpe ratio 比較好的參數:
result2 = bt.optimize(n1=range(5, 200, 10),
n2=range(5, 200, 10))
result2._strategy
# 程式碼顯示結果:
<Strategy Strategy(n1=165,n2=5)>
以上,就是整個優化的過程,程式碼非常簡潔,最後優化完的數字是
- n1 = 165
- n2 = 2
眼尖的人會發現,奇怪怎麼長短週期倒過來了?代表我們死亡交叉買入,而黃金交叉賣出,這種交易比較像是均值回歸,在低點買,高點賣,屬於逆勢策略,我們用這兩個新的參數,來測測看結果如何?
雖然報酬率雖然比較低,但是交易的風險小滿多的,我們可以將順勢跟逆勢策略結合,獲得更穩定的報酬率,下方就是程式碼
((result1._equity_curve.Equity +
result2._equity_curve.Equity)/2).plot()
基本上2008 到現在,沒什麼虧損過,台積電上漲時,會追蹤到漲幅,而下跌時也會危機入市,算是一個非常簡單,但績效很舒服的策略,分享給大家,現在就打開現成的 Colab 直接運行程式碼。假如大家對於我們這樣的分享有興趣,可以幫我們推廣一下!我們也有其他類似的文章可以參考: