網頁

2024年3月31日 星期日

Python:Dataframe 操作

續上一篇,現有一個DataFrame A,B兩個欄位,
當A > B欄位值時 A + B + (B欄位的上一個值),如果沒有上一欄就 A+B欄;
當A < B 則 A+B欄位值;將結果存入 result 欄位。

 DataFrame如下:

期望的 result 欄應該是:16,10,15,16,10

作法如下:

方法1:


方法2:先將 df['B'] 欄做一次 shift,結果放入 df['B_shift'],

將Nan值填入0,
df['B_shift'].fillna(0, inplace=True)



 

方法3:同上先將 df['B'] 欄做一次 shift,然後向量計算結果放入 df['B_shift'],







2024年3月26日 星期二

Python:基金持股爬蟲

今天來講一講用 BeautifulSoup來取得基金的持股成分,首先一樣載入相關的套件:

from bs4 import BeautifulSoup
import json, requests
import pandas as pd

我選定的基金網頁是:
https://fund.hncb.com.tw/w/wr/wr04.djhtm?a=ACDD04-005003

用 requests.get() 來爬取網頁內容:
url = 'https://fund.hncb.com.tw/w/wr/wr04.djhtm?a=ACDD04-005003'
response = requests.get(url)
web_content = response.text
soup = BeautifulSoup(web_content, 'lxml')
soup

輸出結果:

選取 table,然後將 table 轉成 list 形式:

data = soup.select('table')[1]
lst = pd.read_html(data.prettify())
lst

輸出結果: 

然後我們要取出 list[0] 4~9列股票名稱,然後放入 dataframe:

df = lst[0].iloc[4:9]
df

輸出結果: 


處理索引值:

df.reset_index(drop=True)

輸出結果:


完整程式碼:

url = 'https://fund.hncb.com.tw/w/wr/wr04.djhtm?a=ACDD04-005003'
response = requests.get(url)
web_content = response.text
soup = BeautifulSoup(web_content, 'lxml')
data = soup.select('table')[1]
lst = pd.read_html(data.prettify())
title = lst[0].iloc[2][0]
df = lst[0].iloc[4:9].reset_index()
fund_list = df[0].iloc[0:5].tolist()
fund_list.extend(df[4].iloc[0:5].tolist())
print('基金名稱:', title)
print('持股資料(Dataframe):\n', df)
print()
print('股票名稱:', fund)

輸出結果:

 
是不是很簡單!
 
這種網頁畫面:

只要選擇 table[0] 即可:
soup.select('table')[0]
 
另外 title 的部分只要直接用  soup.title.text 取出即可:
soup.title.text
 
輸出結果:

 


2024年3月16日 星期六

Python 計算股價 KDJ (2)

續上一篇:Python 計算股價 KDJ,這篇把它完備一點,再加上前一日收盤價格,今日收盤價格,差異和百分比:


我定義一個函數來取得最後日和前一日的收盤價格資料,並計算差異百分比,最後將結果傳回:

# 取得最後一天收盤資料
def last_day_data(name, df):
date = df.index[-1].strftime('%Y-%m-%d') # 取出最後一筆日期
price = round(df.Close[-1], 2) # 當日收盤價
pre_price = round(df.Close[-2], 2) # 前一日收盤價
diff = round(df.Close[-1] - df.Close[-2], 2) # 價格差異
percent = round(float(diff) * 100 / pre_price, 2) # 差異百分比
high = round(df.High[-1], 2) # 當日最高
low = round(df.Low[-1], 2) # 當日最低
return [date, name, pre_price, price, diff, percent, high, low]

完整程式碼如下:

import yfinance as yf
import pandas as pd
# 計算KDJ,以9日週期計算
def calc_kdj(df, n=9):
low_list = df['Low'].rolling(window=n).min()
low_list.fillna(value=df['Low'].expanding().min(), inplace=True)
high_list = df['High'].rolling(window=n).max()
high_list.fillna(value=df['High'].expanding().max(), inplace=True)
rsv = (df['Close'] - low_list) / (high_list - low_list) * 100

df['K'] = rsv.ewm(com=2).mean()
df['D'] = df['K'].ewm(com=2).mean()
df['J'] = 3 * df['K'] - 2 * df['D']

r = round(rsv.iloc[-1], 2)
k = round(df.iloc[-1].K, 2)
d = round(df.iloc[-1].D, 2)
j = round(df.iloc[-1].J, 2)

return [r, k, d, j]
 
# 取得最後一天收盤資料
def last_day_data(name, df):
date = df.index[-1].strftime('%Y-%m-%d') # 取出最後一筆日期
price = round(df.Close[-1], 2) # 當日收盤價
pre_price = round(df.Close[-2], 2) # 前一日收盤價
diff = round(df.Close[-1] - df.Close[-2], 2) # 價格差異
percent = round(float(diff) * 100 / pre_price, 2) # 差異百分比
high = round(df.High[-1], 2) # 當日最高
low = round(df.Low[-1], 2) # 當日最低
return [date, name, pre_price, price, diff, percent, high, low]
 
def list_conv_matrix(lst):
data, data_matrix = [], []
for val in lst:
data_matrix.append(val)
cols = ['Date', 'Name', '前一日', '收盤價', '差異', '%', '當日最高', '當日最低',
'RSV', 'K', 'D', 'J']
return pd.DataFrame(data_matrix, columns=cols).set_index('Date')
 
def get_ticker_data(ticker_list):
data = []
for ticker in ticker_list:
df = yf.download(ticker, period='30d')

kdj_list = calc_kdj(df) # 計算KDJ
data_list = last_day_data(ticker, df) # 取得最後一天收盤資料
date_str = data_list[0] # 取出日期
data_list.extend(kdj_list)
data.append(data_list)
return data

ticker_list = ['AAPL', 'AMZN', 'GOOGL']
df = list_conv_matrix(get_ticker_data(ticker_list))
df
 

執行結果:

 

你可以參考上一篇:

Python 計算股價 KDJ (1)


2024年3月11日 星期一

Python 計算股價 KDJ

KDJ是通過一個特定的周期(常見為9天)內出現的最高價、最低價和最後交易日的收市價,以及三者之間的比例關係,計出未成熟隨機值(Raw Stochastic Value,RSV),再根據平滑移動平均線(又名「指數移動平均線」,EMA) 的方法計出K值、D值和J值。


今天就來講解如何用python計算KDJ值。

1.首先匯入相關套件:

import yfinance as yf
import pandas as pd

2.下載特斯拉(美股代號:TSLA) 最近30天的股價資料,(列出最後5日資料查看):

 

3.計算 KDJ 值,以最後收盤日2024/03/08 與看盤軟體Tiger trade驗證:

Tiger trade的 K值是18.23,D值是33.04J值是-11.38,計算沒問題

4.將股票名稱,最後收盤價,KDJ值放入list

5.寫一個函數將list轉成 DataFrame 格式,欄位有:名稱(Name),最後收盤價格(Price),K,D,J,並且以股票名稱"Name"當作索引欄,並傳回DataFrame:

6.最後將上面的程式寫成3個函數,
(1)計算KDJ:calc_kdj()
(2)取得股價的資料:get_ticker_price()
(3)list轉換dataframe:list_conv_matrix()

7.我用蘋果(AAPL),輝達(NVDA),特斯拉(TSLA) 這3支股票來計算 KDJ,執行結果如下:

8.最後如果要將 dataframe 存成 csv 檔可以用下面的指令:

kdj_df.to_csv(file_name, sep=',')  # 用逗點分隔的csv檔

完整程式碼如下:

import yfinance as yf
import pandas as pd
 
def calc_kdj(df, n=9):
low_list = df['Low'].rolling(window=n).min()
low_list.fillna(value=df['Low'].expanding().min(), inplace=True)
high_list = df['High'].rolling(window=n).max()
high_list.fillna(value=df['High'].expanding().max(), inplace=True)
rsv = (df['Close'] - low_list) / (high_list - low_list) * 100
df['K'] = rsv.ewm(com=2).mean()
df['D'] = df['K'].ewm(com=2).mean()
df['J'] = 3 * df['K'] - 2 * df['D']
r = round(rsv[-1], 2)
k = round(df[-1:]['K'][0], 2)
d = round(df[-1:]['D'][0], 2)
j = round(df[-1:]['J'][0], 2)
price = round(df[-1:]['Close'][0], 2) # 最後一日收盤價
return price, r, k, d, j

def get_ticker_price(ticker_list):
price_data = []
for ticker in ticker_list:
df = yf.download(ticker, period='30d')
price, r, k, d, j = calc_kdj(df)
date = df.index[-1].strftime('%Y-%m-%d')
data_list = [date, ticker, price, r, k, d, j]
price_data.append(data_list)
return price_data, date

def list_conv_matrix(lst):
data, data_matrix = [], []
for val in lst:
data_matrix.append(val)
cols = ['Date', 'NAME', 'Price', 'RSV', 'K', 'D', 'J']
return pd.DataFrame(data_matrix, columns=cols).set_index('Date')
 
ticker_list = ['AAPL', 'NVDA', 'TSLA']
data, date = get_ticker_price(ticker_list)
kdj_df = list_conv_matrix(data)
print(kdj_df)
 


你可以參考下一篇:

Python 計算股價 KDJ