#下載資料套件
import urllib3
from bs4 import BeautifulSoup
import requests as r
#資料處理套件
import json
import pandas as pd
from datetime import datetime, date, timedelta
# 畫圖套件
import plotly.graph_objects as go
from plotly.subplots import make_subplots
def date_range(start_year, start_month, start_day, end_year, end_month, end_day):
# 將開始日跟結束日轉為時間型態
start_date = date(start_year, start_month, start_day)
end_date = date(end_year, end_month, end_day)
# 在開始日與結束日區間內 以每30天為單位切分 不含結束日
date_list = pd.date_range(start_date, end_date, freq='30D').tolist()
# 加上結束日
if date_list[-1] != end_date:
date_list.append(end_date)
return date_list
def pc_ratio(date_list):
# 設定urllib物件,下載網址,儲存資料的df
http = urllib3.PoolManager()
url = "https://www.taifex.com.tw/cht/3/pcRatio"
df = pd.DataFrame()
# 下載期交所P/C比的迴圈
for idx in range(len(date_list) - 1):
# 設定下載資料的起始日 queryStartDate & queryEndDate
if idx == 0:
start_date = date_list[idx].strftime("%Y/%m/%d")
else:
start_date = (date_list[idx] + timedelta(days = 1)).strftime("%Y/%m/%d")
end_date = date_list[idx + 1].strftime("%Y/%m/%d")
print("迴圈索引值: ", idx, "; 下載時間區間: ", start_date, "-",end_date)
# 從期交所下載資料
res = http.request(
'POST',
url,
fields={
'queryStartDate': start_date,
'queryEndDate': end_date
}
)
html_doc = res.data
table = BeautifulSoup(html_doc, 'html.parser').table
pc_ratio_df = pd.read_html(str(table))[3]
df = df.append(pc_ratio_df, ignore_index = True)
# 日期欄位資料型態從文字轉為時間
for row in range(df.shape[0]):
date2 = df.iloc[row,0].split('/')
df.iloc[row, 0] = datetime(int(date2[0]), int(date2[1]), int(date2[2]))
# dataframe 按照日期排序
df.sort_values("日期", inplace=True, ignore_index = True)
# 設定 dataframe 的欄位名稱
df.columns = ['日期', '賣權成交量', '買權成交量', '買賣權成交量比率%', '賣權未平倉量', '買權未平倉量', '買賣權未平倉量比率%']
return df
date_list = date_range(start_year = 2021,
start_month = 8,
start_day = 1,
end_year = 2021,
end_month = 9,
end_day = 26)
df_pc = pc_ratio(date_list)
df_pc
迴圈索引值: 0 ; 下載時間區間: 2021/08/01 - 2021/08/31 迴圈索引值: 1 ; 下載時間區間: 2021/09/01 - 2021/09/26
日期 | 賣權成交量 | 買權成交量 | 買賣權成交量比率% | 賣權未平倉量 | 買權未平倉量 | 買賣權未平倉量比率% | |
---|---|---|---|---|---|---|---|
0 | 2021-08-02 00:00:00 | 338059 | 305124 | 110.79 | 237570 | 201188 | 118.08 |
1 | 2021-08-03 00:00:00 | 320081 | 272288 | 117.55 | 262276 | 218840 | 119.85 |
2 | 2021-08-04 00:00:00 | 490053 | 398553 | 122.96 | 160675 | 141543 | 113.52 |
3 | 2021-08-05 00:00:00 | 158396 | 113045 | 140.12 | 210999 | 168245 | 125.41 |
4 | 2021-08-06 00:00:00 | 243829 | 228018 | 106.93 | 243176 | 195317 | 124.50 |
5 | 2021-08-09 00:00:00 | 271666 | 298988 | 90.86 | 266233 | 221434 | 120.23 |
6 | 2021-08-10 00:00:00 | 318535 | 373471 | 85.29 | 274400 | 258451 | 106.17 |
7 | 2021-08-11 00:00:00 | 671355 | 607894 | 110.44 | 175921 | 169982 | 103.49 |
8 | 2021-08-12 00:00:00 | 193014 | 206145 | 93.63 | 207351 | 205649 | 100.83 |
9 | 2021-08-13 00:00:00 | 283083 | 340522 | 83.13 | 222768 | 242353 | 91.92 |
10 | 2021-08-16 00:00:00 | 415320 | 418357 | 99.27 | 239784 | 282814 | 84.79 |
11 | 2021-08-17 00:00:00 | 407888 | 462242 | 88.24 | 244643 | 309037 | 79.16 |
12 | 2021-08-18 00:00:00 | 917697 | 839110 | 109.37 | 104401 | 92275 | 113.14 |
13 | 2021-08-19 00:00:00 | 379910 | 426670 | 89.04 | 158776 | 196889 | 80.64 |
14 | 2021-08-20 00:00:00 | 452472 | 439797 | 102.88 | 187974 | 225697 | 83.29 |
15 | 2021-08-23 00:00:00 | 468398 | 390501 | 119.95 | 244039 | 209865 | 116.28 |
16 | 2021-08-24 00:00:00 | 374358 | 346433 | 108.06 | 266889 | 226608 | 117.78 |
17 | 2021-08-25 00:00:00 | 573756 | 526340 | 109.01 | 154185 | 133497 | 115.50 |
18 | 2021-08-26 00:00:00 | 276896 | 324132 | 85.43 | 202415 | 186577 | 108.49 |
19 | 2021-08-27 00:00:00 | 296912 | 282756 | 105.01 | 233760 | 189848 | 123.13 |
20 | 2021-08-30 00:00:00 | 352230 | 303672 | 115.99 | 276241 | 206211 | 133.96 |
21 | 2021-08-31 00:00:00 | 437773 | 470053 | 93.13 | 299533 | 215778 | 138.82 |
22 | 2021-09-01 00:00:00 | 512311 | 522933 | 97.97 | 182946 | 150484 | 121.57 |
23 | 2021-09-02 00:00:00 | 290264 | 285135 | 101.80 | 233776 | 207158 | 112.85 |
24 | 2021-09-03 00:00:00 | 287571 | 276349 | 104.06 | 273554 | 212741 | 128.59 |
25 | 2021-09-06 00:00:00 | 356407 | 344565 | 103.44 | 299154 | 232007 | 128.94 |
26 | 2021-09-07 00:00:00 | 375727 | 398162 | 94.37 | 318731 | 253279 | 125.84 |
27 | 2021-09-08 00:00:00 | 672625 | 701492 | 95.88 | 215750 | 183224 | 117.75 |
28 | 2021-09-09 00:00:00 | 322761 | 292585 | 110.31 | 261144 | 216671 | 120.53 |
29 | 2021-09-10 00:00:00 | 321912 | 266189 | 120.93 | 294188 | 213482 | 137.80 |
30 | 2021-09-13 00:00:00 | 286364 | 239503 | 119.57 | 326113 | 230267 | 141.62 |
31 | 2021-09-14 00:00:00 | 353299 | 294284 | 120.05 | 342375 | 249609 | 137.16 |
32 | 2021-09-15 00:00:00 | 568878 | 586676 | 96.97 | 93336 | 80856 | 115.43 |
33 | 2021-09-16 00:00:00 | 194346 | 211453 | 91.91 | 144226 | 139071 | 103.71 |
34 | 2021-09-17 00:00:00 | 279216 | 261868 | 106.62 | 177380 | 158485 | 111.92 |
35 | 2021-09-22 00:00:00 | 491303 | 565870 | 86.82 | 121732 | 114407 | 106.40 |
36 | 2021-09-23 00:00:00 | 209553 | 197438 | 106.14 | 168356 | 150273 | 112.03 |
37 | 2021-09-24 00:00:00 | 239690 | 223569 | 107.21 | 198411 | 178111 | 111.40 |
df_pc['買賣權未平倉量比率差%'] = df_pc['買賣權未平倉量比率%'] - 100
df_pc
日期 | 賣權成交量 | 買權成交量 | 買賣權成交量比率% | 賣權未平倉量 | 買權未平倉量 | 買賣權未平倉量比率% | 買賣權未平倉量比率差% | |
---|---|---|---|---|---|---|---|---|
0 | 2021-08-02 00:00:00 | 338059 | 305124 | 110.79 | 237570 | 201188 | 118.08 | 18.08 |
1 | 2021-08-03 00:00:00 | 320081 | 272288 | 117.55 | 262276 | 218840 | 119.85 | 19.85 |
2 | 2021-08-04 00:00:00 | 490053 | 398553 | 122.96 | 160675 | 141543 | 113.52 | 13.52 |
3 | 2021-08-05 00:00:00 | 158396 | 113045 | 140.12 | 210999 | 168245 | 125.41 | 25.41 |
4 | 2021-08-06 00:00:00 | 243829 | 228018 | 106.93 | 243176 | 195317 | 124.50 | 24.50 |
5 | 2021-08-09 00:00:00 | 271666 | 298988 | 90.86 | 266233 | 221434 | 120.23 | 20.23 |
6 | 2021-08-10 00:00:00 | 318535 | 373471 | 85.29 | 274400 | 258451 | 106.17 | 6.17 |
7 | 2021-08-11 00:00:00 | 671355 | 607894 | 110.44 | 175921 | 169982 | 103.49 | 3.49 |
8 | 2021-08-12 00:00:00 | 193014 | 206145 | 93.63 | 207351 | 205649 | 100.83 | 0.83 |
9 | 2021-08-13 00:00:00 | 283083 | 340522 | 83.13 | 222768 | 242353 | 91.92 | -8.08 |
10 | 2021-08-16 00:00:00 | 415320 | 418357 | 99.27 | 239784 | 282814 | 84.79 | -15.21 |
11 | 2021-08-17 00:00:00 | 407888 | 462242 | 88.24 | 244643 | 309037 | 79.16 | -20.84 |
12 | 2021-08-18 00:00:00 | 917697 | 839110 | 109.37 | 104401 | 92275 | 113.14 | 13.14 |
13 | 2021-08-19 00:00:00 | 379910 | 426670 | 89.04 | 158776 | 196889 | 80.64 | -19.36 |
14 | 2021-08-20 00:00:00 | 452472 | 439797 | 102.88 | 187974 | 225697 | 83.29 | -16.71 |
15 | 2021-08-23 00:00:00 | 468398 | 390501 | 119.95 | 244039 | 209865 | 116.28 | 16.28 |
16 | 2021-08-24 00:00:00 | 374358 | 346433 | 108.06 | 266889 | 226608 | 117.78 | 17.78 |
17 | 2021-08-25 00:00:00 | 573756 | 526340 | 109.01 | 154185 | 133497 | 115.50 | 15.50 |
18 | 2021-08-26 00:00:00 | 276896 | 324132 | 85.43 | 202415 | 186577 | 108.49 | 8.49 |
19 | 2021-08-27 00:00:00 | 296912 | 282756 | 105.01 | 233760 | 189848 | 123.13 | 23.13 |
20 | 2021-08-30 00:00:00 | 352230 | 303672 | 115.99 | 276241 | 206211 | 133.96 | 33.96 |
21 | 2021-08-31 00:00:00 | 437773 | 470053 | 93.13 | 299533 | 215778 | 138.82 | 38.82 |
22 | 2021-09-01 00:00:00 | 512311 | 522933 | 97.97 | 182946 | 150484 | 121.57 | 21.57 |
23 | 2021-09-02 00:00:00 | 290264 | 285135 | 101.80 | 233776 | 207158 | 112.85 | 12.85 |
24 | 2021-09-03 00:00:00 | 287571 | 276349 | 104.06 | 273554 | 212741 | 128.59 | 28.59 |
25 | 2021-09-06 00:00:00 | 356407 | 344565 | 103.44 | 299154 | 232007 | 128.94 | 28.94 |
26 | 2021-09-07 00:00:00 | 375727 | 398162 | 94.37 | 318731 | 253279 | 125.84 | 25.84 |
27 | 2021-09-08 00:00:00 | 672625 | 701492 | 95.88 | 215750 | 183224 | 117.75 | 17.75 |
28 | 2021-09-09 00:00:00 | 322761 | 292585 | 110.31 | 261144 | 216671 | 120.53 | 20.53 |
29 | 2021-09-10 00:00:00 | 321912 | 266189 | 120.93 | 294188 | 213482 | 137.80 | 37.80 |
30 | 2021-09-13 00:00:00 | 286364 | 239503 | 119.57 | 326113 | 230267 | 141.62 | 41.62 |
31 | 2021-09-14 00:00:00 | 353299 | 294284 | 120.05 | 342375 | 249609 | 137.16 | 37.16 |
32 | 2021-09-15 00:00:00 | 568878 | 586676 | 96.97 | 93336 | 80856 | 115.43 | 15.43 |
33 | 2021-09-16 00:00:00 | 194346 | 211453 | 91.91 | 144226 | 139071 | 103.71 | 3.71 |
34 | 2021-09-17 00:00:00 | 279216 | 261868 | 106.62 | 177380 | 158485 | 111.92 | 11.92 |
35 | 2021-09-22 00:00:00 | 491303 | 565870 | 86.82 | 121732 | 114407 | 106.40 | 6.40 |
36 | 2021-09-23 00:00:00 | 209553 | 197438 | 106.14 | 168356 | 150273 | 112.03 | 12.03 |
37 | 2021-09-24 00:00:00 | 239690 | 223569 | 107.21 | 198411 | 178111 | 111.40 | 11.40 |
def get_tw_market_data(start_year, start_month, end_year, end_month):
start_date = str(date(start_year, start_month, 1))
end_date = str(date(end_year, end_month, 1))
month_list = pd.date_range(start_date, end_date, freq='MS').strftime("%Y%m%d").tolist()
df = pd.DataFrame()
for month in month_list:
url = "https://www.twse.com.tw/exchangeReport/FMTQIK?response=json&date="+ month
res = r.get(url)
stock_json = res.json()
stock_df = pd.DataFrame.from_dict(stock_json['data'])
df = df.append(stock_df, ignore_index = True)
# 資料轉型
for col in [0, 1, 2, 3, 4]:
for row in range(df.shape[0]):
# 把"日期"從字串(string)換成時間(datetime),並將民國年換成西元年
if col == 0:
day = df.iloc[row,0].split('/')
df.iloc[row, 0] = datetime(int(day[0]) + 1911, int(day[1]), int(day[2]))
# 把"開盤價", "最高價", "最低價", "收盤價"帶有逗號的字串(string)換成浮點數(float)
elif col != 0:
df.iloc[row, col] = float(df.iloc[row,col].replace(',', ''))
df.columns = ['日期', '成交股數', '成交金額', '成交筆數', '發行量股價加權指數', '漲跌點數']
return df
df_market = get_tw_market_data(start_year = 2021,
start_month = 8,
end_year = 2021,
end_month = 9)
df_market
日期 | 成交股數 | 成交金額 | 成交筆數 | 發行量股價加權指數 | 漲跌點數 | |
---|---|---|---|---|---|---|
0 | 2021-08-02 00:00:00 | 8433835543.0 | 440189515085.0 | 2581704.0 | 17503.28 | 255.87 |
1 | 2021-08-03 00:00:00 | 7297083331.0 | 390300020287.0 | 2300155.0 | 17553.76 | 50.48 |
2 | 2021-08-04 00:00:00 | 8674006828.0 | 379090333818.0 | 2535997.0 | 17623.89 | 70.13 |
3 | 2021-08-05 00:00:00 | 9310147655.0 | 385923439915.0 | 2803525.0 | 17603.12 | -20.77 |
4 | 2021-08-06 00:00:00 | 8507806575.0 | 401257559286.0 | 2764690.0 | 17526.28 | -76.84 |
5 | 2021-08-09 00:00:00 | 7894068144.0 | 352402466708.0 | 2493714.0 | 17485.15 | -41.13 |
6 | 2021-08-10 00:00:00 | 7424101809.0 | 352995785011.0 | 2356807.0 | 17323.64 | -161.51 |
7 | 2021-08-11 00:00:00 | 8485348305.0 | 392285506858.0 | 2702640.0 | 17227.18 | -96.46 |
8 | 2021-08-12 00:00:00 | 6583768656.0 | 322543314397.0 | 2063506.0 | 17219.94 | -7.24 |
9 | 2021-08-13 00:00:00 | 8080387820.0 | 386639052024.0 | 2570094.0 | 16982.11 | -237.83 |
10 | 2021-08-16 00:00:00 | 7549787896.0 | 336192844584.0 | 2412039.0 | 16858.77 | -123.34 |
11 | 2021-08-17 00:00:00 | 6572397068.0 | 299768629334.0 | 2172972.0 | 16661.36 | -197.41 |
12 | 2021-08-18 00:00:00 | 8581086550.0 | 424297841253.0 | 2740916.0 | 16826.27 | 164.91 |
13 | 2021-08-19 00:00:00 | 8740931351.0 | 438390385364.0 | 2953753.0 | 16375.4 | -450.87 |
14 | 2021-08-20 00:00:00 | 7563826027.0 | 354803584641.0 | 2358046.0 | 16341.94 | -33.46 |
15 | 2021-08-23 00:00:00 | 7336054319.0 | 367661958976.0 | 2131349.0 | 16741.84 | 399.90 |
16 | 2021-08-24 00:00:00 | 8218076194.0 | 418124482650.0 | 2587550.0 | 16818.73 | 76.89 |
17 | 2021-08-25 00:00:00 | 7220691717.0 | 364041511681.0 | 2250083.0 | 17045.86 | 227.13 |
18 | 2021-08-26 00:00:00 | 7176067004.0 | 377161165125.0 | 2300304.0 | 17066.96 | 21.10 |
19 | 2021-08-27 00:00:00 | 6876549054.0 | 320002450972.0 | 2061715.0 | 17209.93 | 142.97 |
20 | 2021-08-30 00:00:00 | 6286680713.0 | 274916258264.0 | 1852473.0 | 17396.52 | 186.59 |
21 | 2021-08-31 00:00:00 | 7594890429.0 | 345142070590.0 | 2051856.0 | 17490.29 | 93.77 |
22 | 2021-09-01 00:00:00 | 7417302954.0 | 365348125049.0 | 2348742.0 | 17473.99 | -16.30 |
23 | 2021-09-02 00:00:00 | 7363528319.0 | 354658918739.0 | 2367548.0 | 17319.76 | -154.23 |
24 | 2021-09-03 00:00:00 | 7417361078.0 | 366252454304.0 | 2309735.0 | 17516.92 | 197.16 |
25 | 2021-09-06 00:00:00 | 8125514641.0 | 380807908396.0 | 2551101.0 | 17495.3 | -21.62 |
26 | 2021-09-07 00:00:00 | 6809125095.0 | 337806586675.0 | 2159870.0 | 17428.87 | -66.43 |
27 | 2021-09-08 00:00:00 | 6716726562.0 | 325685541312.0 | 2204512.0 | 17270.49 | -158.38 |
28 | 2021-09-09 00:00:00 | 5177907252.0 | 246914721428.0 | 1644144.0 | 17304.33 | 33.84 |
29 | 2021-09-10 00:00:00 | 5898868907.0 | 268550691237.0 | 1765201.0 | 17474.57 | 170.24 |
30 | 2021-09-13 00:00:00 | 5932740401.0 | 260743193791.0 | 1837328.0 | 17446.31 | -28.26 |
31 | 2021-09-14 00:00:00 | 5669147686.0 | 261864808382.0 | 1863142.0 | 17434.9 | -11.41 |
32 | 2021-09-15 00:00:00 | 5732189159.0 | 269826160399.0 | 1935541.0 | 17354.0 | -80.90 |
33 | 2021-09-16 00:00:00 | 5750136284.0 | 242577208525.0 | 1872875.0 | 17278.7 | -75.30 |
34 | 2021-09-17 00:00:00 | 6567681323.0 | 316458676884.0 | 1948384.0 | 17276.79 | -1.91 |
35 | 2021-09-22 00:00:00 | 7253281012.0 | 298478639255.0 | 2353514.0 | 16925.82 | -350.97 |
36 | 2021-09-23 00:00:00 | 5730646954.0 | 253840587758.0 | 1822103.0 | 17078.22 | 152.40 |
37 | 2021-09-24 00:00:00 | 6101942091.0 | 278917064315.0 | 1952491.0 | 17260.19 | 181.97 |
# 設定圖有兩個y軸
fig = make_subplots(specs=[[{"secondary_y": True}]])
# 畫長條圖
fig.add_trace(go.Bar(x = df_pc['日期'],
y = df_pc['買賣權未平倉量比率差%'],
name = '選擇權 put/call 未平倉比率差%',
marker = dict(color = 'green'),
opacity = 0.5),
secondary_y = False)
# 畫折線圖
fig.add_trace(
go.Scatter(x = df_market['日期'],
y = df_market['發行量股價加權指數'],
name = "發行量股價加權指數",
line = dict(color = "red", width = 2)),
secondary_y = True)
# 設定圖的x跟y軸標題
fig.update_xaxes(title_text = "日期",
rangebreaks = [{ 'pattern': 'day of week', 'bounds': [6, 1]}])
fig.update_yaxes(showgrid = False,
title_text = "Put/Call 未平倉量比率差%",
secondary_y = False)
fig.update_yaxes(showgrid = False,
title_text = "發行量股價加權指數",
secondary_y = True)
# 設定圖的標題跟長寬
fig.update_layout(title_text = "Put/Call 未平倉比率圖",
title_x = 0.3,
width = 1000,
height = 800)
fig.show()