iT邦幫忙

1

如何讓程式碼快速在1900個csv檔案中找到相對應的檔案?

  • 分享至 

  • xImage

最近開始在回測股票,後來發現因為1900家的股票資訊存成csv檔案,然後用python抓這些檔案來回測,可是程式碼慢在帶入csv檔案這個地方,因為變成電腦要在1900家的csv檔案中找到相對應的檔案?

想請教先進有沒有什麼方法可以讓電腦更快的搜尋到相對應的檔但呢?
stocdid=[0050,0051,.......................]
for j in stockid:
tempdf = pd.read_csv(j+'.csv', parse_dates=True)

看更多先前的討論...收起先前的討論...
你只能往硬體去處理了。至少要將記體加大。讓作業在記憶體工作。
再來就是核心處理了。只是這樣成本很高。
我找到解決方法了 謝謝
程式碼如下
先把1900個股票交易資料csv檔案分別建立一個 dataframe,然後加入到dict中

li = []

for i in stockidnew:
df_name = f'df{i}'
print(df_name)
df_name= pd.read_csv('./newcsv/'+i+'new.csv', parse_dates=True)
li.append(df_name)


for df in li:
print(df)
不用高效能資料庫來篩選...用CSV檔@@...
我後來改成資料庫版本,令人驚訝的如果回測一天,跑一千多家公司去讀取資料庫然後就只是當純的print(df)居然要跑13分鐘?比讀取csv檔案還要慢,如果用csv檔案跑一天只需要一分鐘?照理說節省了IO搜尋1900個csv檔案的時間才對?應該要更快才是?
還是說我程式碼有什麼問題嗎?如果回測一天讀取1900次資料庫,居然要跑13分鐘?CSV才一分半耶?
stockidnew=[1900家公司代號略過 '9960', '9962']
for tempstockid in stockidnew:
tempdf = pd.read_sql('select * from daily_price where stock_id='+tempstockid, conn, index_col=['Date'], parse_dates=['Date'])
print(tempdf)
原本一開始程式碼有很多地方有拖累速度,可是在慢回測一天也只需要7分鐘,現在改成資料庫版本反而要13分鐘?而且還只是print(df)而已,還沒跑一堆策略。
後來改成把資料庫一次全部讀到記憶體中,有比把1900個csv寫到記憶體快多,原本1900個CSV寫到記憶體要13分鐘,把資料庫一次寫到記憶體只需要一分多。
後來想到之所以用資料庫回測要13分鐘的原因是因為
比如每間公司有400多天的交易紀錄,變成每次電腦都要去1900*400天的交易紀錄去找指定公司的交易紀錄,比去1900個csv檔還要更多。
所以應該即使我把資料庫一次全部寫到記憶體,那電腦還是一樣要去1900*400天的交易紀錄去搜尋,所以csv的架構會比較快。
後來有測試過即使根據股票代號在資料庫建立1900個資料表,
然後再從資料庫叫出這1900個資料表,要一分鐘4X秒,還是比CSV慢了10秒左右。
我後來猜想原因是因為即使在資料庫裏頭建立1900個資料表
這不是又回到原來的問題,一樣都要在1900個檔案搜尋所要的檔案。
而且還比搜尋csv多了"SELECT * FROM '{table_name}'"之類的讀取sql語法
所以相對資料庫架構而言,直接搜尋csv還省了好幾行執行指令cpu的時間

frames_dict = []
select_template = "SELECT * FROM '{table_name}'"
for i in stockidnew:
# table_name=str(i)
# table_name_list.append(str(i))
#print(table_name_list)
#for tname in table_name_list:
query = select_template.format(table_name = i)
testdf = pd.read_sql(query, conn)
frames_dict.append(testdf)
Peter iT邦新手 4 級 ‧ 2024-04-24 09:19:31 檢舉
努力不懈的精神值得大家學習,加油。

看完你的討論串後,你的需求應該就是每天會做股票回測,可能是某一個策略跑1900檔股票得出結果,針對這個需求我提供一些我的建議。

首先是要先有一個基本觀念,資料庫一定比CSV快,這是資料結構決定的,所以根據你的需求,請使用資料庫,可選擇MySQL或BigQuery之類的簡單易用即可(這裡只求簡單,DBA專家請勿抬槓),接著是運算都是在RAM中進行的,所以無論使用資料庫或是CSV,你都避不開載入的過程,但資料庫的好處是你可以更快速的找到並載入指定的資料。

基於以上,你應該進行的調整是:
1. 將所有csv寫進同一個table中,而不是分1900個table
因為股票交易的結構完全相同,回測需求不需要分表,然後增加"股票代號"的欄位來區分每一個資料屬於哪間公司即可。

2. 建立索引
針對"股票代號"建立索引,以利後續的回測可快速找到對應的資料。

3. 調整程式邏輯(若資料量非常大)
不要一次載入全部股票交易紀錄,而是每一個回測只針對特定的股票代碼進行SELECT,然後處理完後,在進行下一個。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
海綿寶寶
iT邦大神 1 級 ‧ 2024-04-11 22:19:27

你不是已經用股票代碼(0050,0051)當檔名了嗎?
還需要用什麼方式找到檔案
/images/emoticon/emoticon19.gif

看更多先前的回應...收起先前的回應...

我找到解決方法了 謝謝
程式碼如下
先把1900個股票交易資料csv檔案分別建立一個 dataframe,然後加入到dict中

li = []

for i in stockidnew:
df_name = f'df{i}'
print(df_name)
df_name= pd.read_csv('./newcsv/'+i+'new.csv', parse_dates=True)
li.append(df_name)

for df in li:
print(df)

我是說回測的時候會一直不斷在1900個csv擋去找,cpu時間會浪費很多時間在這上面,後來用如上的方法,原本要回測某一天1900家某技術指標會需要花一分半,但現在只需要六秒鐘。所以說每次回測一天會整整花了1分鐘2X秒在搜尋檔案。

問題出在於程式每一次要花0.04秒上下找到0050.CSV檔案。
測一天是1900乘0.04,然後如果要測100天就變成1900乘0.04乘100,那就很可怕了。萬一要回測10年-20年呢?

froce iT邦大師 1 級 ‧ 2024-04-12 08:18:35 檢舉

寫隻程式把1900個檔案讀進資料庫,後續用資料庫去做才是正途。
你也提到要回測多年的問題,那怎麼還會用CSV檔?

harry731 iT邦新手 2 級 ‧ 2024-04-12 10:43:16 檢舉

我也覺得把csv轉存到資料庫比較好
用資料庫方式處理資料不好嗎?
這麼堅持要用CSV是受了啥刺激?還是有啥外部制約?

kk999 iT邦新手 2 級 ‧ 2024-04-12 15:44:00 檢舉

@grissonlin 這其實就是是資料結構中最基本的收尋問題,大牛早就幫你實做好了

每次回測一天會整整花了1分鐘2X秒在搜尋檔案

時間與其說花在「搜尋檔案」
倒不如說是「讀寫檔案硬體I/O」
改成通通一股腦兒讀進dataframe
也只不過是改成「讀寫記憶體」而獲得的效率提升

跟你的題目「如何讓程式碼快速在1900個csv檔案中找到相對應的檔案?」沒有太大關係...

總之
問題解決就好
/images/emoticon/emoticon12.gif

謝謝各位先進的建議,晚點會找時間改成資料庫架構的。謝謝。
改成資料庫應該也是好處多多,不用每次要測的時候重複下戴行情,弄個sql每天更新一次行情,會節省很多時間。

0
japhenchen
iT邦超人 1 級 ‧ 2024-04-12 10:43:49

開始 → powershell

複制貼上以下指令(一行),內容自己按實際情況更改,找出"C:\path\to\folder"所有CSV檔裡含有michael字串的檔案,放心不會破壞任何資料也沒有危險性,難度★☆☆☆☆

Get-ChildItem -Path "C:\path\to\folder" -Recurse -Filter *.csv | Select-String -Pattern "michael" | Select-Object -Unique Path

我要發表回答

立即登入回答