├── 2317_946656000_1600272000.csv ├── 2317_最近五天.csv ├── Day11_saveToAzureDB.py ├── Day13_save2330ToAzureDB.py ├── Day15_getStockDataFromOpenData.py ├── Day16_saveApiStockToDb.py ├── Day18_saveApiStockToDb.py ├── Day19_batchSaveApiStockToDb.py ├── Day1_helloWorld.py ├── Day20_createMA.ipynb ├── Day21_createMAStrategy.ipynb ├── Day26_createLine.ipynb ├── Day5_getStockFromYahoo.py ├── Day6_getStockFromYahoo.py ├── Day7_getStockFromYahoo.ipynb ├── Day8_saveData.py ├── Pipfile └── readme.md /2317_最近五天.csv: -------------------------------------------------------------------------------- 1 | ,open,high,low,close,volume 2 | 2020-09-10 01:00:00,78.0,78.69999694824219,78.0,78.5,29117204.0 3 | 2020-09-11 01:00:00,78.5,78.5,78.0,78.5,16102726.0 4 | 2020-09-14 01:00:00,78.80000305175781,79.5,78.5999984741211,79.4000015258789,27029525.0 5 | 2020-09-15 01:00:00,79.4000015258789,79.4000015258789,78.9000015258789,79.0999984741211,16938546.0 6 | 2020-09-16 05:30:03,79.4000015258789,79.4000015258789,78.5999984741211,78.80000305175781,18027000.0 7 | -------------------------------------------------------------------------------- /Day11_saveToAzureDB.py: -------------------------------------------------------------------------------- 1 | import pyodbc 2 | 3 | server = "ey-finance.database.windows.net" 4 | database = "finance" 5 | username = "我的帳號" 6 | password = "我的密碼" 7 | driver = "{ODBC Driver 17 for SQL Server}" 8 | 9 | with pyodbc.connect( 10 | f"DRIVER={driver};SERVER={server};PORT=1433;DATABASE={database};UID={username};PWD={password}" 11 | ) as conn: 12 | with conn.cursor() as cursor: 13 | cursor.execute("SELECT * FROM Stock;") 14 | row = cursor.fetchone() 15 | print("This is data in my Azure.....by Eyelash") 16 | while row: 17 | print(f"{row[0]} {row[1]} {row[2]} {row[3]} {row[4]} {row[5]}") 18 | row = cursor.fetchone() 19 | -------------------------------------------------------------------------------- /Day13_save2330ToAzureDB.py: -------------------------------------------------------------------------------- 1 | import pyodbc 2 | import requests 3 | import json 4 | import numpy 5 | import pandas 6 | 7 | server = "ey-finance.database.windows.net" 8 | database = "finance" 9 | username = "我的帳號" 10 | password = "我的密碼" 11 | driver = "{ODBC Driver 17 for SQL Server}" 12 | 13 | # API位置 14 | start_time = 1577808000 # 2020/1/1 15 | end_time = 1600531200 # 2020/9/20 16 | stock_code = 2330 17 | stock_market = "TW" 18 | address = f"https://query1.finance.yahoo.com/v8/finance/chart/{stock_code}.{stock_market}?period1={start_time}&period2={end_time}&interval=1d&events=history&=hP2rOschxO0" 19 | 20 | # 使用requests 來跟遠端 API server 索取資料 21 | response = requests.get(address) 22 | 23 | # 序列化資料回報 24 | data = json.loads(response.text) 25 | 26 | # 把json格式資料放入pandas中 27 | df = pandas.DataFrame( 28 | data["chart"]["result"][0]["indicators"]["quote"][0], 29 | index=pandas.to_datetime( 30 | numpy.array(data["chart"]["result"][0]["timestamp"]) * 1000 * 1000 * 1000 31 | ), 32 | columns=["open", "high", "low", "close", "volume"], 33 | ) 34 | 35 | """匯入資料""" 36 | # 連線到Azure 37 | with pyodbc.connect( 38 | f"DRIVER={driver};SERVER={server};PORT=1433;DATABASE={database};UID={username};PWD={password}" 39 | ) as conn: 40 | with conn.cursor() as cursor: 41 | # 把Dataframe 匯入到SQL Server: 42 | for index, row in df.iterrows(): 43 | cursor.execute( 44 | """INSERT INTO finance.dbo.DailyPrice 45 | (StockID, Symbol, TradeDate, OpenPrice, HighPrice, LowPrice, 46 | ClosePrice,Volumn) 47 | values(?,?,?,?,?,?,?,?)""", 48 | "dd95bd5328b14d489d6f6e649233c774", 49 | "2330", 50 | index, 51 | row.open, 52 | row.high, 53 | row.low, 54 | row.close, 55 | row.volume, 56 | ) 57 | conn.commit() 58 | print("finished") 59 | -------------------------------------------------------------------------------- /Day15_getStockDataFromOpenData.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import pandas 3 | from io import StringIO 4 | 5 | # 資料說明:https://data.gov.tw/dataset/11549 6 | # API位置 7 | address = "http://www.twse.com.tw/exchangeReport/STOCK_DAY_ALL?response=open_data" 8 | 9 | # 取得資料 10 | response = requests.get(address) 11 | 12 | # 欄位:證券代號、證券名稱、成交股數、成交金額、開盤價、最高價、最低價、收盤價、漲跌價差、成交筆數 13 | # 會是:"00875","國泰網路資安","1,998,885","51,736,728","25.78","25.98","25.77","25.98","+0.46","484" 14 | 15 | # 解析 16 | data = response.text 17 | mystr = StringIO(data) 18 | df = pandas.read_csv(mystr, header=None) 19 | # print(df) # 這邊就會印出所有的資料,但是第一行也被認為是資料 20 | 21 | # 建立新dataframe 22 | new_headers = df.iloc[0] # 第一行當作header 23 | df = df[1:] # 拿掉第一行的資料 24 | df.columns = new_headers # 設定資料欄位的名稱 25 | print(df) 26 | -------------------------------------------------------------------------------- /Day16_saveApiStockToDb.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import pandas 3 | import pyodbc 4 | import datetime 5 | import time 6 | from io import StringIO 7 | 8 | 9 | def create_new_header(orignal_headers): 10 | new_headers = [] 11 | 12 | for column in orignal_headers: 13 | data = str(column) 14 | if data == "證券代號": 15 | new_headers.append("stock_symbol") 16 | elif data == "證券名稱": 17 | new_headers.append("stock_name") 18 | elif data == "成交股數": 19 | new_headers.append("volume") 20 | elif data == "成交金額": 21 | new_headers.append("total_price") 22 | elif data == "開盤價": 23 | new_headers.append("open") 24 | elif data == "最高價": 25 | new_headers.append("high") 26 | elif data == "最低價": 27 | new_headers.append("low") 28 | elif data == "收盤價": 29 | new_headers.append("close") 30 | elif data == "漲跌價差": 31 | new_headers.append("spread") 32 | elif data == "成交筆數": 33 | new_headers.append("transactions_number") 34 | 35 | return new_headers 36 | 37 | 38 | def save_data_to_azure_db(stock_data): 39 | server = "ey-finance.database.windows.net" 40 | database = "finance" 41 | username = "我的帳號" 42 | password = "我的密碼" 43 | driver = "{ODBC Driver 17 for SQL Server}" 44 | 45 | with pyodbc.connect( 46 | f"DRIVER={driver};SERVER={server};PORT=1433;DATABASE={database};UID={username};PWD={password}" 47 | ) as conn: 48 | with conn.cursor() as cursor: 49 | now = datetime.datetime.now().strftime("%Y-%m-%d") 50 | # 把Dataframe 匯入到SQL Server: 51 | for index, row in df.iterrows(): 52 | try: 53 | cursor.execute( 54 | """INSERT INTO finance.dbo.DailyPrice 55 | (StockID, Symbol, TradeDate, OpenPrice, HighPrice, LowPrice, 56 | ClosePrice,Volumn) 57 | values(?,?,?,?,?,?,?,?);""", 58 | "", 59 | row.stock_symbol, 60 | now, 61 | row.open, 62 | row.high, 63 | row.low, 64 | row.close, 65 | int(row.volume.replace(",", "")), 66 | ) 67 | conn.commit() 68 | if index % 10 == 0: 69 | time.sleep(1) 70 | except Exception as e: 71 | print(e) 72 | return True 73 | return False 74 | 75 | 76 | # 資料說明:https://data.gov.tw/dataset/11549 77 | # API位置 78 | address = "http://www.twse.com.tw/exchangeReport/STOCK_DAY_ALL?response=open_data" 79 | 80 | # 取得資料 81 | response = requests.get(address) 82 | 83 | # 欄位:證券代號、證券名稱、成交股數、成交金額、開盤價、最高價、最低價、收盤價、漲跌價差、成交筆數 84 | # 會是:"00875","國泰網路資安","1,998,885","51,736,728","25.78","25.98","25.77","25.98","+0.46","484" 85 | 86 | # 解析 87 | data = response.text 88 | mystr = StringIO(data) 89 | df = pandas.read_csv(mystr, header=None) 90 | 91 | # 建立新dataframe 92 | new_headers = df.iloc[0] # 第一行當作header 93 | new_headers = create_new_header(new_headers) 94 | df = df[1:] # 拿掉第一行的資料 95 | df.columns = new_headers # 設定資料欄位的名稱 96 | print(df) 97 | 98 | save_data_to_azure_db(df) 99 | print("===finished===") 100 | -------------------------------------------------------------------------------- /Day18_saveApiStockToDb.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import pandas 3 | import pyodbc 4 | import json 5 | 6 | 7 | def convert_date(data_ROC): 8 | """因為格式為109/1/1,為民國年,需轉換成西元年""" 9 | date_arr = data_ROC.split("/") 10 | new_year = int(date_arr[0]) + 1911 11 | return f"{new_year}-{date_arr[1]}-{date_arr[2]}" 12 | 13 | 14 | def create_new_header(orignal_headers): 15 | new_headers = [] 16 | 17 | for column in orignal_headers: 18 | data = str(column) 19 | if data == "日期": 20 | new_headers.append("trade_date") 21 | elif data == "證券名稱": 22 | new_headers.append("stock_name") 23 | elif data == "成交股數": 24 | new_headers.append("volume") 25 | elif data == "成交金額": 26 | new_headers.append("total_price") 27 | elif data == "開盤價": 28 | new_headers.append("open") 29 | elif data == "最高價": 30 | new_headers.append("high") 31 | elif data == "最低價": 32 | new_headers.append("low") 33 | elif data == "收盤價": 34 | new_headers.append("close") 35 | elif data == "漲跌價差": 36 | new_headers.append("spread") 37 | elif data == "成交筆數": 38 | new_headers.append("transactions_number") 39 | 40 | return new_headers 41 | 42 | 43 | def save_data_to_azure_db(symbol, tock_data): 44 | server = "ey-finance.database.windows.net" 45 | database = "finance" 46 | username = "我的帳號" 47 | password = "我的密碼" 48 | driver = "{ODBC Driver 17 for SQL Server}" 49 | 50 | with pyodbc.connect( 51 | f"DRIVER={driver};SERVER={server};PORT=1433;DATABASE={database};UID={username};PWD={password}" 52 | ) as conn: 53 | with conn.cursor() as cursor: 54 | # 把Dataframe 匯入到SQL Server: 55 | for index, row in df.iterrows(): 56 | try: 57 | cursor.execute( 58 | """INSERT INTO finance.dbo.DailyPrice 59 | (StockID, Symbol, TradeDate, OpenPrice, HighPrice, 60 | LowPrice, ClosePrice, Volumn) 61 | values(?,?,?,?,?,?,?,?);""", 62 | "", 63 | symbol, 64 | convert_date(row.trade_date), 65 | row.open, 66 | row.high, 67 | row.low, 68 | row.close, 69 | int(row.volume.replace(",", "")), 70 | ) 71 | conn.commit() 72 | # if index % 10 == 0: 73 | # time.sleep(1) 74 | except Exception as e: 75 | print(e) 76 | return True 77 | return False 78 | 79 | 80 | # API位置 81 | # address = "http://www.twse.com.tw/exchangeReport/STOCK_DAY_ALL?response=open_data" 82 | stock = "2330" 83 | date = "202009" 84 | address = f"https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={date}&stockNo={stock}" 85 | 86 | # 取得資料 87 | response = requests.get(address) 88 | # 解析 89 | # 有幾個部分:stat, date, title, fields, data, notes 90 | data = response.text # 這是json格式的資料 91 | a_json = json.loads(data) # 轉成dict 92 | df = pandas.DataFrame.from_dict(a_json["data"]) # 轉成dataframe 93 | 94 | # 修改欄位名稱 95 | new_headers = create_new_header(a_json["fields"]) 96 | df.columns = new_headers # 設定資料欄位的名稱 97 | # print(df) 98 | 99 | _ = save_data_to_azure_db(stock, df) 100 | print("===finished===") 101 | -------------------------------------------------------------------------------- /Day19_batchSaveApiStockToDb.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import pandas 3 | import pyodbc 4 | import json 5 | import datetime 6 | 7 | 8 | def convert_date(data_ROC): 9 | """因為格式為109/1/1,為民國年,需轉換成西元年""" 10 | date_arr = data_ROC.split("/") 11 | new_year = int(date_arr[0]) + 1911 12 | return f"{new_year}-{date_arr[1]}-{date_arr[2]}" 13 | 14 | 15 | def create_new_header(orignal_headers): 16 | new_headers = [] 17 | 18 | for column in orignal_headers: 19 | data = str(column) 20 | if data == "日期": 21 | new_headers.append("trade_date") 22 | elif data == "證券名稱": 23 | new_headers.append("stock_name") 24 | elif data == "成交股數": 25 | new_headers.append("volume") 26 | elif data == "成交金額": 27 | new_headers.append("total_price") 28 | elif data == "開盤價": 29 | new_headers.append("open") 30 | elif data == "最高價": 31 | new_headers.append("high") 32 | elif data == "最低價": 33 | new_headers.append("low") 34 | elif data == "收盤價": 35 | new_headers.append("close") 36 | elif data == "漲跌價差": 37 | new_headers.append("spread") 38 | elif data == "成交筆數": 39 | new_headers.append("transactions_number") 40 | 41 | return new_headers 42 | 43 | 44 | def save_data_to_azure_db(symbol, tock_data): 45 | server = "ey-finance.database.windows.net" 46 | database = "finance" 47 | username = "我的帳號" 48 | password = "我的密碼" 49 | driver = "{ODBC Driver 17 for SQL Server}" 50 | 51 | with pyodbc.connect( 52 | f"DRIVER={driver};SERVER={server};PORT=1433;DATABASE={database};UID={username};PWD={password}" 53 | ) as conn: 54 | with conn.cursor() as cursor: 55 | # 把Dataframe 匯入到SQL Server: 56 | for index, row in tock_data.iterrows(): 57 | try: 58 | cursor.execute( 59 | """INSERT INTO finance.dbo.DailyPrice 60 | (StockID, Symbol, TradeDate, OpenPrice, HighPrice, 61 | LowPrice, ClosePrice, Volumn) 62 | values(?,?,?,?,?,?,?,?);""", 63 | "", 64 | symbol, 65 | convert_date(row.trade_date), 66 | row.open, 67 | row.high, 68 | row.low, 69 | row.close, 70 | int(row.volume.replace(",", "")), 71 | ) 72 | conn.commit() 73 | # if index % 10 == 0: 74 | # time.sleep(1) 75 | except Exception as e: 76 | print(e) 77 | return True 78 | return False 79 | 80 | 81 | def get_stock_history_data(stock_symbol, his_month): 82 | # API位置 83 | # address = "http://www.twse.com.tw/exchangeReport/STOCK_DAY_ALL?response=open_data" 84 | 85 | stock = stock_symbol 86 | date = his_month 87 | address = f"https://www.twse.com.tw/exchangeReport/STOCK_DAY?response=json&date={date}&stockNo={stock}" 88 | 89 | # 取得資料 90 | response = requests.get(address) 91 | # 解析 92 | # 有幾個部分:stat, date, title, fields, data, notes 93 | data = response.text # 這是json格式的資料 94 | a_json = json.loads(data) # 轉成dict 95 | df = pandas.DataFrame.from_dict(a_json["data"]) # 轉成dataframe 96 | 97 | # 修改欄位名稱 98 | new_headers = create_new_header(a_json["fields"]) 99 | df.columns = new_headers # 設定資料欄位的名稱 100 | # print(df) 101 | 102 | _ = save_data_to_azure_db(stock, df) 103 | print("===finished===") 104 | 105 | 106 | # 時間不能太早:{"stat":"查詢日期小於99年1月4日,請重新查詢!"} 107 | # 取得從2010-1-1到現在的所有月份,用此可以取得資料 108 | date_list = ( 109 | pandas.date_range( 110 | "2010-1-1", 111 | datetime.datetime.now().strftime("%Y-%m-%d"), 112 | freq="MS", 113 | tz="Asia/Taipei", 114 | ) 115 | .strftime("%Y%m%d") 116 | .tolist() 117 | ) 118 | print(date_list) 119 | 120 | for data_date in date_list: 121 | print(f"start({datetime.datetime.now().strftime('%m%d-%H%M%S')}): {data_date}") 122 | get_stock_history_data("2330", data_date) 123 | -------------------------------------------------------------------------------- /Day1_helloWorld.py: -------------------------------------------------------------------------------- 1 | print("Hello world! Python") 2 | print("By Eyelash") -------------------------------------------------------------------------------- /Day5_getStockFromYahoo.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | # API位置 4 | address = "https://query1.finance.yahoo.com/v8/finance/chart/2317.TW?period1=1598889600&period2=1599926400&interval=1d&events=history&=hP2rOschxO0" 5 | 6 | # 使用requests 來跟遠端 API server 索取資料 7 | response = requests.get(address) 8 | 9 | # 印出取得的結果 10 | print(response.text) -------------------------------------------------------------------------------- /Day6_getStockFromYahoo.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import numpy 4 | import pandas 5 | 6 | # API位置 7 | start_time = 1596211200 8 | end_time = 1599926400 9 | address = f"https://query1.finance.yahoo.com/v8/finance/chart/2317.TW?period1={start_time}&period2={end_time}&interval=1d&events=history&=hP2rOschxO0" 10 | 11 | # 使用requests 來跟遠端 API server 索取資料 12 | response = requests.get(address) 13 | 14 | # 序列化資料回報 15 | data = json.loads(response.text) 16 | 17 | # 把json格式資料放入pandas中 18 | df = pandas.DataFrame( 19 | data["chart"]["result"][0]["indicators"]["quote"][0], 20 | index=pandas.to_datetime( 21 | numpy.array(data["chart"]["result"][0]["timestamp"]) * 1000 * 1000 * 1000 22 | ), 23 | ) 24 | # 印出前3行: 25 | print(df[:3]) 26 | # 印出前5行 27 | print(df.head()) 28 | -------------------------------------------------------------------------------- /Day7_getStockFromYahoo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.8.5-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python_defaultSpec_1600181150224", 18 | "display_name": "Python 3.8.5 64-bit ('12-ithome': pipenv)" 19 | } 20 | }, 21 | "nbformat": 4, 22 | "nbformat_minor": 2, 23 | "cells": [ 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": { 28 | "tags": [] 29 | }, 30 | "outputs": [ 31 | { 32 | "output_type": "stream", 33 | "name": "stdout", 34 | "text": "Hello world! Python & Jupyter\nBy Eyelash\n" 35 | } 36 | ], 37 | "source": [ 38 | "print(\"Hello world! Python & Jupyter\")\n", 39 | "print(\"By Eyelash\")" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 2, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "import requests\n", 49 | "import json\n", 50 | "import numpy\n", 51 | "import pandas" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": 3, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "# API位置\n", 61 | "start_time = 1596211200\n", 62 | "end_time = 1599926400\n", 63 | "address = f\"https://query1.finance.yahoo.com/v8/finance/chart/2317.TW?period1={start_time}&period2={end_time}&interval=1d&events=history&=hP2rOschxO0\"" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 4, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "# 使用requests 來跟遠端 API server 索取資料\n", 73 | "response = requests.get(address)\n", 74 | "\n", 75 | "# 序列化資料回報\n", 76 | "data = json.loads(response.text)\n", 77 | "\n", 78 | "# 把json格式資料放入pandas中\n", 79 | "df = pandas.DataFrame(\n", 80 | " data[\"chart\"][\"result\"][0][\"indicators\"][\"quote\"][0],\n", 81 | " index=pandas.to_datetime(\n", 82 | " numpy.array(data[\"chart\"][\"result\"][0][\"timestamp\"]) * 1000 * 1000 * 1000\n", 83 | " ),\n", 84 | ")" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": 5, 90 | "metadata": { 91 | "tags": [] 92 | }, 93 | "outputs": [ 94 | { 95 | "output_type": "stream", 96 | "name": "stdout", 97 | "text": "low close high volume open\n2020-08-03 01:00:00 77.099998 77.099998 78.900002 61172243 78.400002\n2020-08-04 01:00:00 77.500000 78.099998 78.199997 23051382 77.699997\n2020-08-05 01:00:00 77.900002 77.900002 78.500000 27876127 78.300003\n" 98 | } 99 | ], 100 | "source": [ 101 | "# 印出前3行\n", 102 | "print(df[:3])" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 6, 108 | "metadata": { 109 | "tags": [] 110 | }, 111 | "outputs": [ 112 | { 113 | "output_type": "stream", 114 | "name": "stdout", 115 | "text": "low close high volume open\n2020-08-03 01:00:00 77.099998 77.099998 78.900002 61172243 78.400002\n2020-08-04 01:00:00 77.500000 78.099998 78.199997 23051382 77.699997\n2020-08-05 01:00:00 77.900002 77.900002 78.500000 27876127 78.300003\n2020-08-06 01:00:00 78.500000 79.000000 79.699997 33250505 79.300003\n2020-08-07 01:00:00 78.300003 78.300003 79.599998 21862438 79.599998\n" 116 | } 117 | ], 118 | "source": [ 119 | "# 印出前5行\n", 120 | "print(df.head())" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 7, 126 | "metadata": {}, 127 | "outputs": [ 128 | { 129 | "output_type": "execute_result", 130 | "data": { 131 | "text/plain": "" 132 | }, 133 | "metadata": {}, 134 | "execution_count": 7 135 | }, 136 | { 137 | "output_type": "display_data", 138 | "data": { 139 | "text/plain": "
", 140 | "image/svg+xml": "\n\n\n\n \n \n \n \n 2020-09-15T23:22:27.956509\n image/svg+xml\n \n \n Matplotlib v3.3.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", 141 | "image/png": "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\n" 142 | }, 143 | "metadata": { 144 | "needs_background": "light" 145 | } 146 | } 147 | ], 148 | "source": [ 149 | "# 印出圖表\n", 150 | "df.close.plot()" 151 | ] 152 | } 153 | ] 154 | } -------------------------------------------------------------------------------- /Day8_saveData.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import numpy 4 | import pandas 5 | 6 | # API位置 7 | start_time = 946656000 # 2000/1/1 8 | end_time = 1600272000 # 2020/9/17 9 | stock_code = 2317 10 | stock_market = "TW" 11 | address = f"https://query1.finance.yahoo.com/v8/finance/chart/{stock_code}.{stock_market}?period1={start_time}&period2={end_time}&interval=1d&events=history&=hP2rOschxO0" 12 | 13 | # 使用requests 來跟遠端 API server 索取資料 14 | response = requests.get(address) 15 | 16 | # 序列化資料回報 17 | data = json.loads(response.text) 18 | 19 | # 把json格式資料放入pandas中 20 | df = pandas.DataFrame( 21 | data["chart"]["result"][0]["indicators"]["quote"][0], 22 | index=pandas.to_datetime( 23 | numpy.array(data["chart"]["result"][0]["timestamp"]) * 1000 * 1000 * 1000 24 | ), 25 | columns=["open", "high", "low", "close", "volume"], 26 | ) 27 | # 印出前3行 28 | print(df[:3]) 29 | # 印出前5行 30 | print(df.head()) 31 | # 印出後5行 32 | print(df.tail()) 33 | 34 | # 寫成csv 35 | df.tail().to_csv(f"{stock_code}_最近五天.csv") 36 | df.to_csv(f"{stock_code}_{start_time}_{end_time}.csv") 37 | 38 | print("===finished===") 39 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | name = "pypi" 3 | url = "https://pypi.org/simple" 4 | verify_ssl = true 5 | 6 | [dev-packages] 7 | flake8 = "*" 8 | 9 | [packages] 10 | requests = "*" 11 | numpy = "*" 12 | pandas = "*" 13 | matplotlib = "*" 14 | jupyter = "*" 15 | pyodbc = "*" 16 | 17 | [requires] 18 | python_version = "3.8" 19 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 目的 2 | 3 | 參加2020年舉辦的12th iT邦幫忙鐵人賽,主題是: Python X 金融分析 X Azure 4 | * https://ithelp.ithome.com.tw/users/20103826/ironman/3032 5 | * https://ithelp.ithome.com.tw/users/20103826 6 | 7 | # 安裝 8 | 9 | 會額外安裝: 10 | * flake8 11 | * black: pip install -U black 12 | 13 | # blog 14 | 15 | * https://dotblogs.com.tw/Eyelash 16 | * https://dotblogs.com.tw/Eyelash/Series?qq=Python%20X%20金融分析%20X%20Azure 17 | --------------------------------------------------------------------------------