--- title: 'FINLAB擴充套件' disqus: hackmd --- Finext === >[name=吾夜遊酩,2024/6/15] <!-- ![downloads](https://img.shields.io/github/downloads/atom/atom/total.svg) ![build](https://img.shields.io/appveyor/ci/:user/:repo.svg) ![chat](https://img.shields.io/discord/:serverId.svg)--> * 這是一個基於finlab的擴充套件,提供延伸功能,假設使用者已經熟悉finlab,功能說明會慢慢補上,如果有時間ㄉ話 * finlab免費版即可使用,差在資料更新與每日能下載多少資料 * 可能會遇到版本,環境問題,需有基礎程式能力除錯 環境 --- ### 建議環境 * 作業系統:Ubuntu 22.04.3 LTS (WSL) / mac (M1) * Python 3.11.0 * finlab 1.1.1 * pyspark 3.5.0 * ipython 8.21.0 ### 下載finext ```gherkin= pip install finext ``` 初始化 --- ```python= import finlab from finext.co_tools import Codata, FinlabDataFrame #指定db儲存路徑,依照你的電腦資料夾路徑更改 db_path = "/home/sb0487/trade/finlab/finlab_db" #初始化,建構實例 c = Codata( df_type = "findf", db_path = db_path, force_download = False ) ``` * df_type有三種型態,莫認為FinlabDataFrame: 1."findf": FinlabDataFrame 2."cudf": cuda的DataFrame 3."sparkdf":spark的DataFrame >force_download為強制重新下載資料庫資料,機制詳見[finlab官方](https://doc.finlab.tw/reference/data/) 資料下載 --- ```python= eps = c.get('financial_statement:每股盈餘') ``` 與官方data.get差異在於會顯示最後一次修改時間,幫助使用者注意資料狀態 > >output: >Daily usage: 1.3 / 500 MB - financial_statement:每股盈餘 最後更新時間: 2024-06-01 19:59:32, ['financial_statement:每股盈餘'] 年報季報搜尋-1.爬蟲 --- ``` mermaid graph TD; 自行設定股票清單-->stock_list; 從finlab季報eps表中獲取股票清單-->stock_list; stock_list -->年報爬蟲; stock_list -->季報爬蟲; 年報爬蟲-->年報爬蟲失敗list; 季報爬蟲-->季報爬蟲失敗list; 年報爬蟲失敗list-->年報爬蟲; 季報爬蟲失敗list-->季報爬蟲; ``` ```python= import re import finlab from finext.co_tools import Codata, FinlabDataFrame #指定db儲存路徑,依照你的電腦資料夾路徑更改 db_path = "/home/sb0487/trade/finlab/finlab_db" #初始化 c = Codata( df_type = "findf", db_path = db_path, force_download = False ) eps = c.get('financial_statement:每股盈餘') #抓取股票清單 pattern = re.compile(r'^\d{4}$') all_stock_list = [value for value in list(eps.columns) if pattern.match(value)] ``` 首先我們需要準備一份爬蟲清單,型態為list,我們用finlab資料庫季報的eps資料,抓取所有的股票代號,並去除etf ```python= """年報爬蟲""" #指定年報儲存路徑,依照你的電腦資料夾路徑更改 save_dir = "/home/sb0487/trade/data/112年報" #先用三隻股票測試是否能順利抓取 stock_list = all_stock_list[:3] year = 112 sleep = 2 failed_list = c.crawl_annual_reports(year,stock_list,save_dir,sleep) ``` 這邊會使用到selenium套件,記得要安裝chromedriver * 參數說明 1. year: 年報年分,西元 2. sleep: 每個步驟停頓秒數,視網速,電腦效能,證交所是否會檔而定 3. failed_list: 會有許多情況導致爬不到,failed_list會記錄本次沒爬到的股票清單,可以把他做為stock_list,再爬1run >順利的話,output: >PDF 文件已保存到: /home/sb0487/trade/data/112年報/112_1101.pdf PDF 文件已保存到: /home/sb0487/trade/data/112年報/112_1102.pdf PDF 文件已保存到: /home/sb0487/trade/data/112年報/112_1103.pdf ```python= """季報爬蟲""" #指定年報儲存路徑,依照你的電腦資料夾路徑更改 save_dir = "/home/sb0487/trade/data/112季報/Q3" #先用三隻股票測試是否能順利抓取 stock_list = all_stock_list[:3] year = 112 quarter = 3 sleep = 2 failed_list = c.crawl_quarterly_reports(year,quarter,stock_list,save_dir,sleep) ``` 這邊會使用到selenium套件,記得要安裝chromedriver * 參數說明 1. year: 年報年分,西元 2. quarter: 季度 3. sleep: 每個步驟停頓秒數,視網速,電腦效能,證交所是否會檔而定 4. failed_list: 會有許多情況導致爬不到,failed_list會記錄本次沒爬到的股票清單,可以把他做為stock_list,再爬1run ```python= """檢查資料夾,查詢哪些股票尚未下載""" undownloaded_stocks_list = c.get_undownloaded_stocks(save_dir,all_stock_list) ``` 年報季報搜尋-2.載入 --- 因為檔案數量多,這邊使用pyspark以節省讀檔時間,然而因電腦性能這步驟會有出錯的可能,通常是記憶體過小,若無法解決請用一般載入 ``` mermaid graph TD; 自行設定股票清單-->stock_list; 從finlab季報eps表中獲取股票清單-->stock_list; stock_list -->載入PDF; 載入PDF-->spark載入; 載入PDF-->一般單線程載入; ``` ```python= pip install PyMuPDF ``` ```python= import re import finlab from finext.co_tools import Codata, FinlabDataFrame #指定db儲存路徑,依照你的電腦資料夾路徑更改 db_path = "/home/sb0487/trade/finlab/finlab_db" #初始化 c = Codata( df_type = "findf", db_path = db_path, force_download = False ) eps = c.get('financial_statement:每股盈餘') #抓取股票清單 pattern = re.compile(r'^\d{4}$') all_stock_list = [value for value in list(eps.columns) if pattern.match(value)] ``` 初始化並拿到股票清單 ```python= """saprk載入""" pdf_path = "/home/sb0487/trade/data/113季報/Q1" stock_list = all_stock_list df = c.load_pdf_spark(stock_list,pdf_path,memory = "5g") ``` 這邊只要給他stock_list與PDF所在資料夾即可,每個driver都需要5g以上記憶體,若kernel crash,可嘗試提高記憶體 若報錯可在網頁輸入`http://localhost:4040/jobs/`將錯誤碼貼給chat-gpt,或者一般單線程載入 ```python= """一般單線程載入""" pdf_path = "/home/sb0487/trade/data/113季報/Q1" stock_list = all_stock_list df = c.load_pdf(stock_list,pdf_path) ``` 年報季報搜尋-3.應用 --- 簡單舉例來說,以下都可以用關鍵字搜尋: 1. 如果你想知道哪些股票是與NVIDIA有關係,而還沒被提及的 2. 某檔股票漲了一大段,想知道那些公司有持有他 3. 某樣特殊產品缺貨,還有哪一家公司有在做? 4. 賴總統在再生醫療雙法三讀通過時提到"智慧醫療",想知道每家生技公司提到ai的次數? ```python= """關鍵字""" df['count'] = df['PDF Content'].str.count("NVIDIA") df_filtered = df[df['count'] >= 1] ``` 相關係數排名 --- 指定某檔股票,從股票清單中找出與該股票相關係數最高與最低的TOP30 ```python= import re import finlab from finext.co_tools import Codata, FinlabDataFrame #指定db儲存路徑,依照你的電腦資料夾路徑更改 db_path = "/home/sb0487/trade/finlab/finlab_db" #初始化 c = Codata( df_type = "findf", db_path = db_path, force_download = False ) close = c.get('price:收盤價') ``` 初始化並拿到股價df ```python= import pandas as pd import re pattern = re.compile(r'^\d{4}$') close = close[[col for col in close.columns if pattern.match(col)]] ``` 這邊去除etf等,使用者可以自行決定要去除哪些股票,如果要保留etf,這行就刪掉 ```python= start_date = '2020-08-07' end_date = '2023-08-07' close = close.loc[start_date:end_date] ``` 指定日期區間,範例如程式碼 ```python= c.get_corr_ranked("2330",close) ``` 輸出結果如下 ![image](https://hackmd.io/_uploads/BJOhhRt8R.png) 時間序列比較圖 --- 指定某兩檔股票,繪圖與計算其區間相關係數 ```python= import re import finlab from finext.co_tools import Codata, FinlabDataFrame #指定db儲存路徑,依照你的電腦資料夾路徑更改 db_path = "/home/sb0487/trade/finlab/finlab_db" #初始化 c = Codata( df_type = "findf", db_path = db_path, force_download = False ) close = data.get('price:收盤價') ``` 初始化並拿到股價df ```python= start_date = '2020-08-07' end_date = '2023-08-07' close = c.loc[start_date:end_date] ``` 指定日期區間 ```python= c.get_tm_series_chart(["2330","0050"],close,lag = 0) ``` * 如果 lag 為正數,則第二個股票的時間序列會被向後移動相應的滯後期數。 * 圖表上顯示滯後後的時間序列與滯後前的原始時間序列進行比較。 * 函數會計算滯後期數後的相關係數,並在圖表標題中顯示出來,用於分析兩數列之間在不同滯後期的相關性,從而確定領先滯後關係(Cross-Correlation Analysis)。 輸出結果如下 ![image](https://hackmd.io/_uploads/Syj6K19LC.png) * 若要嚴謹一點的統計學,在檢定兩數列之間的領先滯後關係之前,至少要有兩步驟。 1. 確定這兩個數列是否為隨機漫步(random walk),意即它們是否是平穩的(stationary),通常金融數據為一階平穩,所以通常取差分是標準步驟。推薦 Dickey-Fuller Test, H0為數列存在單根 3. 完成以上步驟後,可以進行兩數列之間的領先滯後檢驗。Granger Causality Test或Cross-Correlation Analysis,不過還是建議是不要在統計學上浪費時間TAT ### 額外範例,長榮航與wti油價相關係數 ```python= import re import finlab from finext.co_tools import Codata, FinlabDataFrame #指定db儲存路徑,依照你的電腦資料夾路徑更改 db_path = "/home/sb0487/trade/finlab/finlab_db" #初始化 c = Codata( df_type = "findf", db_path = db_path, force_download = False ) close = c.get('price:收盤價') ``` 初始化並拿到股價df ```python= start_date = '2020-08-07' end_date = '2023-08-07' close = c.loc[start_date:end_date] ``` 指定日期區間 ```python= import yfinance as yf # 下載數據並重命名欄位 wti_data = yf.download(tickers="CL=F", period="10y", interval="1d")[['Close']].rename(columns={'Close': 'wti_close'}) # 將索引轉換為日期格式 wti_data.index = wti_data.index.date # 併入finlab的dataframe merged_df = close.join(wti_data, how='inner') ``` 記得要下載yfinance ```python= c.get_tm_series_chart(["2618","wti_close"],close = merged_df,lag = 0) ``` 輸出結果如下 ![image](https://hackmd.io/_uploads/SyY15mqLR.png) <!-- User flows --- ```sequence Alice->Bob: Hello Bob, how are you? Note right of Bob: Bob thinks Bob->Alice: I am good thanks! Note left of Alice: Alice responds Alice->Bob: Where have you been? ``` > Read more about sequence-diagrams here: http://bramp.github.io/js-sequence-diagrams/ Project Timeline --- ```mermaid gantt title A Gantt Diagram section Section A task :a1, 2014-01-01, 30d Another task :after a1 , 20d section Another Task in sec :2014-01-12 , 12d anther task : 24d ``` > Read more about mermaid here: http://mermaid-js.github.io/mermaid/ ## Appendix and FAQ :::info **Find this document incomplete?** Leave a comment! ::: ###### tags: `Templates` `Documentation` -->