
簡介一份專為通達信本地數據使用者準備的小型轉換工具面向需要將day行情轉化為CSV的股票、基金及港股分析者。它覆蓋上證、深證與港股目錄針對股票、基金及港股在字段結構上的差異逐一適配解析后輸出整潔的CSV可顯著減少手工二進制解析與格式兼容成本。壓縮包共2個文件僅8KB內含一個免安裝的stock.exe和一個C語言源文件exe適合直接下載后復制到對應行情目錄即用源碼則方便開發者理解轉換邏輯、自行調整字段或移植到其他場景。目前已有6251人學習瀏覽足見其在量化備數、盤后復盤等場景下的實用需求。通過這版小工具用戶既能快速完成通達信day文件到通用表格數據的批量轉換也能從C源碼中掌握不同市場、不同品種的底層格式差異為后續擴展或獨立開發打下基礎。 打開通達信的數據目錄你會看到一堆后綴為.day的文件。很多人在本地做量化回測、遷移歷史數據、或者把通達信數據喂給別的軟件時第一道坎就是怎么把這堆二進制文件轉成自己能用的格式。這個需求看似基礎但真做起來牽扯的細節不少尤其是當你面對的不只是A股還有港股、場內基金這些品種時很多通用腳本會直接翻車。我自己在處理這批文件時踩過不少坑也把格式和轉換流程完整摸了一遍。這篇文章就從格式結構、轉換方案、實操代碼到問題排查把通達信day文件轉換這件事一次說透。1. 項目概述與整體設計思路1.1 核心需求解析day文件也叫日線數據文件是通達信本地存儲K線數據的主要格式之一。它記錄了一只股票或基金從上市以來的每一個交易日開盤價、最高價、最低價、收盤價、成交量、成交額等核心信息。對于做策略回測、數據遷移、或是多平臺數據同步的人來說這些文件是最原始也是最可靠的數據源。但問題在于通達信的day文件是二進制格式不是我們常見的CSV或者JSON直接用文本編輯器打開全是亂碼。而且不同市場滬深A股、港股、基金的數據字段含義和處理細節有差異一個不留神就會解析出錯誤的價格和成交量。這個項目的核心目標就很清晰寫一個健壯的轉換程序把通達信的.day二進制文件解析成通用格式通常是CSV同時兼容A股、港股和基金三類品種并且處理掉成交量單位、價格精度、復權標記這些容易踩坑的細節。1.2 為什么需要自行轉換而非導出有人會問通達信軟件本身不就能導出數據嗎確實能但局限性很大。通達信自帶的“數據導出”功能在菜單里操作一次只能導出一只股票而且導出的是當前界面顯示的周期。如果你有幾百只股票的歷史日線要導出手動操作會讓人崩潰。更關鍵的是導出的數據往往經過了軟件層面的處理比如復權計算、格式化精度你拿到的不是最原始的底層數據。而直接解析.day文件有幾大優勢一次腳本批量處理所有股票拿到的是最底層、未經過多處理的原始數據不依賴通達信軟件是否運行可以精確控制輸出格式和字段這個方案本質上是一個“二進制解析格式轉換”的項目核心難點不在于寫代碼本身而在于理解通達信的數據存儲規則。下面深入拆解。2. day文件二進制格式深入解析2.1 day文件基礎結構通達信day文件的格式是公開的秘密網上流傳的資料不少我實測核對后確認結構如下。每一條記錄固定占用32個字節按順序排列偏移量長度字節字段名數據類型說明04日期int32實際日期 該值 1900年1月1日的偏移天數44開盤價int32實際價格 該值 / 10084最高價int32實際價格 該值 / 100124最低價int32實際價格 該值 / 100164收盤價int32實際價格 該值 / 100204成交額float32單位元244成交量int32單位股A股284保留字段int32通常為0我最初在解析時有個誤區以為日期字段是Unix時間戳直接轉就出錯了。后來才確認它存的是一個相對天數基準日是1900年1月1日。所以要將它轉換成“YYYY-MM-DD”格式需要做一步換算。比如文件中日期字段的十進制值是43831那么實際日期就是1900-01-01加上43831天計算出來是2020-01-02。注意這個計算不是直接用Excel的日期序列號規則而是以1900年1月1日為基準的累計天數。2.2 不同市場的字段差異如果只用上面這套結構去解析所有文件很快就會發現不對勁。因為港股和基金的day文件在某些細節上跟A股不一樣。先說成交量單位。A股和場內基金的成交量day文件里記錄的是“股”或“份”這一點比較直觀。但港股不一樣港股交易單位是按“股”記錄的但很多股票的面值、每手股數差異很大例如騰訊控股每手100股而有些港股每手是1000股甚至2000股。在.day文件中港股的成交量字段記錄的是“股”數這一點跟A股沒有本質區別。不過真正要小心的是價格單位。A股價格精確到分所以存的是“元”乘以100后的整數。港股因為價格跨度大有些股票股價上千元比如騰訊曾到過700多港元有些仙股只有幾分錢但day文件的規則同樣是乘以100后存整數。這里有個風險一旦某個股票價格超過一定范圍或者有3位小數的情況比如某些港股報價是0.125港元直接除以100能得到正確結果但如果遇到5位小數的港股比如部分渦輪和牛熊證單純除以100就不夠了這類數據在普通股票日線里碰不到不需要過度擔心。但對于做港股衍生品研究的人來說day文件可能不一定覆蓋到還是要提醒一句。再說份額和單位的問題。不少人在轉換基金文件時發現成交量數字大得離譜以為是解析錯了。其實場內基金的成交量字段單位和A股股票一樣是“份”比如某ETF一天成交了1億份字段值就是100000000不需要額外處理。但如果你希望輸出到其他軟件時是“手”為單位那就需要在腳本里做一次除以100的換算。2.3 復權標記的真相關于day文件是否包含復權信息這是一個高頻疑問。我的實測結論是標準的.day文件里沒有復權因子它存的是不復權的原始價格。通達信界面默認顯示的前復權、后復權價格是軟件在讀取day文件之后實時計算的計算依據是另一個文件通常叫gbbq即股本變遷文件里的除權除息記錄。這意味著你用腳本直接解析day文件拿到的價格如果期間有分紅送股看到的價格是不連續的跳變。比如某股票10轉10之前價格100元轉增后開盤價可能是50元day文件里記錄的就是這個50元而不會自動處理成復權后的連續價格。所以如果你的量化策略需要復權數據在解析day文件之后還需要額外加載除權除息數據做復權計算。這個點后面會在常見問題部分詳細說。在網上搜索“通達信股本變遷文件(gbbq)解密”也能看到很多人在研究這個正因為它是復權計算的關鍵。3. 轉換方案選型與工具準備3.1 方案對比Python腳本、通達信導出、第三方工具做這個轉換本質上有三條路可以走方案優點缺點適用場景Python自寫解析腳本靈活、支持批量、可定制輸出格式需要會寫代碼主力方案推薦通達信自帶導出簡單、無需編程一次只能導一只、效率低臨時導一兩只用第三方轉換工具開箱即用安全風險不明、格式不可控不推薦有腳本風險我自己最終采用的是Python方案。原因很簡單第一我需要批量處理整個股票池幾千個文件第二我需要輸出成特定格式供其他程序讀取第三后續要做復權處理自己寫腳本可以無縫銜接。3.2 Python環境準備這一步沒有任何特殊之處核心依賴只有兩個Python 3.6任何較新版本都可以pandas用于CSV輸出和處理數據表如果你不愿意裝pandas純用csv模塊也可以但pandas會讓后續的過濾、排序、去重操作高效很多。pip install pandas然后就沒了。解析二進制文件用的是Python內置的struct模塊不需要額外安裝。3.3 數據文件準備在動手之前先明確你要解析哪些文件。通達信的安裝路徑通常是類似C:\new_tdx\vipdoc\sh\lday\ C:\new_tdx\vipdoc\sz\lday\ C:\new_tdx\vipdoc\hk\lday\其中sh目錄放上交所股票日線sz目錄放深交所股票日線hk目錄放港股日線文件命名規則是市場代碼證券代碼.day。例如sh600000.day是浦發銀行sz000001.day是平安銀行hk00700.day是騰訊控股?;鸷凸善钡拇娣盼恢靡粯游募惨粯颖热鐂z159915.day是易方達創業板ETF。需要提醒一下如果你在軟件里看不到港股數據本地可能沒有hk目錄或者目錄為空。這個跟通達信版本和數據下載范圍有關不是你的腳本有問題。4. 實操過程與核心代碼實現4.1 單文件解析核心函數先把最核心的解析函數寫出來。這個函數負責把.day文件二進制內容讀出來套用struct的解包格式逐條解析成可讀的數據行。import struct import pandas as pd from datetime import datetime, timedelta def parse_day_file(filepath): # 32字節一條記錄 record_size 32 results [] with open(filepath, rb) as f: data f.read() # 文件總長度必須是32的倍數否則文件可能損壞或不是day文件 record_count len(data) // record_size for i in range(record_count): offset i * record_size record data[offset:offset record_size] date_raw, open_raw, high_raw, low_raw, close_raw, amount_raw, volume_raw, _ struct.unpack(IIIIIIfI, record) # 注意成交額是float成交量是int順序不要搞反 # 日期換算 date datetime(1900, 1, 1) timedelta(daysdate_raw) date_str date.strftime(%Y-%m-%d) # 價格換算 open_price open_raw / 100.0 high_price high_raw / 100.0 low_price low_raw / 100.0 close_price close_raw / 100.0 results.append({ date: date_str, open: open_price, high: high_price, low: low_price, close: close_price, amount: amount_raw, # 成交額單位元 volume: volume_raw, # 成交量 }) return pd.DataFrame(results)這段代碼就完成了最核心的解析工作。簡單測試一下df parse_day_file(sh600000.day) print(df.head())如果解析正確你會看到類似這樣的輸出date open high low close amount volume 0 1999-11-10 29.50 29.80 29.01 29.18 1.191912e09 10000000 1 1999-11-11 29.00 29.30 28.80 29.10 1.000000e09 9800000這里有一個先易后難的經驗第一次解析時先用一只最近上市的新股測試確保數據量少、容易核對。如果新股的解析結果跟軟件顯示一致說明格式肯定沒錯再去跑老股票。4.2 批量轉換與跨市場兼容單個文件解析沒問題之后批量轉換就是水到渠成的事。但這里需要處理一個問題港股成交量單位與A股可能不同至少要做到不搞錯。A股和基金的成交量單位是股/份港股也是股但如果你的下游系統要求統一為手就按100股/手換算。不過我建議默認不做換算保留最原始的數據把換算留給下游處理。寫一個批量轉換函數import os import glob def batch_convert(source_dir, output_dir, market_typesh): os.makedirs(output_dir, exist_okTrue) # 匹配所有.day文件 pattern os.path.join(source_dir, *.day) day_files glob.glob(pattern) for filepath in day_files: filename os.path.basename(filepath) # 例如 sh600000.day code filename.split(.)[0] # 例如 sh600000 try: df parse_day_file(filepath) if df.empty: continue # 輸出CSV以代碼命名 output_path os.path.join(output_dir, f{code}.csv) df.to_csv(output_path, indexFalse, float_format%.3f) print(f轉換完成: {code} - {output_path}共{len(df)}條記錄) except Exception as e: print(f解析失敗: {filepath}錯誤: {e})這個腳本對sh、sz、hk目錄均適用只要傳入對應的source_dir即可。唯一需要留意的點是不要在循環里用print輸出太多日志幾千個文件全打印會拖慢速度。如果文件量很大建議最后統一匯總生成一個轉換報告。4.3 輸出格式設計與數據校驗輸出CSV只是最基礎的做法。實際項目中我通常會在CSV基礎上增加幾個字段方便下游使用。擴展后的輸出包括date交易日期code證券代碼open, high, low, close四價格volume成交量A股/基金單位是股/份港股是股amount成交額元pct_change日漲跌幅可選日漲跌幅可以直接在轉換時算出來df[pct_change] df[close].pct_change() * 100為什么建議加這個字段因為很多量化框架入參加載數據時都要求有漲跌幅你在轉換階段算好后面省一次遍歷。關于校驗有一個非常實用的小技巧檢查解析出的數據末尾日期是否和通達信軟件最新交易日一致。如果不一致說明day文件沒更新需要先在通達信里下載完整日線數據。另外價格字段的數值范圍可以用來判斷單位換算是否正確——如果出現某只股票收盤價超過10000元而它明明不可能是這個價那大概率是文件沒找對或解析字節順序錯了。5. 常見問題與排查技巧實錄5.1 日期相差8小時或完全錯亂這個問題非常典型。當你用datetime.fromtimestamp()直接把日期字段當Unix時間戳解析時得到的結果會時區錯亂或者日期明顯不對。解決方案就是回到格式本身去理解不要猜。日期字段是相對1900年1月1日的天數偏移不是Unix時間戳。正確做法是date datetime(1900, 1, 1) timedelta(daysdate_raw)如果這樣還錯檢查一下你讀取文件時是否用了二進制模式。Windows下如果你用文本模式打開.day文件會被做換行符轉換導致字節錯位解析結果完全亂掉。5.2 成交量單位是股還是手這個問題我在前面提過但值得再強調。不少人在轉換時習慣性把成交量除以100理由是“交易軟件里顯示的是手”。但這個觀念是錯誤的通達信day文件里存的就是股精確到1股A股不是手。你直接除以100反而把數據搞小了。什么時候需要除以100只有當你確認下游系統要求以“手”為單位時才需要。而且港股的“每手股數”因股票而異有些是100有些是500有些是2000絕對不能用統一的100來除。我覺得最穩妥的做法是day文件解析后保持原始股數涉及單位換算的交給下游系統處理。5.3 復權數據怎么處理前面說過day文件里是裸價格不含復權因子。但有很多人拿到數據后發現某天的價格跳變巨大就來問是不是解析錯了。這里要分兩種情況如果跳變正好發生在某次分紅送股除權日那說明解析完全正確。那天的價格本身就出現了臺階是市場行為不是程序bug。如果你確實需要復權后的連續價格那必須去解析gbbq文件股本變遷文件。這是一個代價更高的解析任務gbbq文件的格式比day文件復雜得多涉及送股比例、配股比例、分紅金額等多個字段。具體做法是先加載gbbq按日期排序用前復權或后復權公式一行一行修正價格。網上關于“通達信股本變遷文件(gbbq)解密方法”的討論也很多核心原理都一樣就是要讀懂這個文件的二進制結構。5.4 遇到加密或損壞文件正常情況下day文件沒有加密。如果你用上面的代碼解析某些文件時報錯或者發現文件長度不是32的倍數有幾個可能文件下載不完整。在通達信里重新下載一次日線數據。文件根本不是day文件比如你把day和其他的文件弄混了。通達信版本升級導致格式變化。目前主流版本V7.x實測都能用這套結構解析但不排除未來版本調整的可能。遇到解析異常我的建議是別急著改代碼先用16進制編輯器打開文件看看開頭32字節是否符合預期結構。這個排查方法最直接。5.5 參數速查表參數A股港股場內基金成交量單位股股份價格精度0.01元0.01港元0.001元day文件目錄vipdoc/sh/ldayvipdoc/hk/ldayvipdoc/sz/lday文件命名sh600000.dayhk00700.daysz159915.day日期基準1900-01-01同左同左6. 項目經驗總結這套轉換腳本我現在還在持續使用不管是做策略回測、跨平臺數據同步還是生成自定義格式的歷史數據它都是最底層的那個工具?;叵胝麄€開發過程有幾點經驗值得分享第一二進制解析類項目格式理解大于一切。網上能搜到很多版本的day格式說明但搜到之后一定要自己做一次驗證。我的核對方法是拿一只剛上市不久的股票用通達信軟件看某一天的數據再對比腳本解析出來的數據完全一致才算通過。第二兼容性設計考慮得越早越好。如果只是轉換上證A股代碼可以寫得非常簡潔但一旦加上港股和基金就必須在單位換算、價格精度上做分區處理。我的實現方式是在批量轉換函數里增加market_type參數針對不同市場的特性做差異化處理而不是把邏輯寫死。第三數據安全要做好。雖然轉換腳本只是讀取文件不修改原始文件但我還是建議在操作前把整個vipdoc目錄復制一份備份。數據無價尤其是在做歷史回測時原始數據的完整性直接影響策略驗證的可靠性。如果后續打算繼續深入可以在這個項目基礎上增加兩個擴展方向一是接入gbbq文件的解析實現真正的復權計算二是打通“通達信data文件轉CSV”的通道把分鐘級數據也納入轉換體系。這些我后面實際跑通了再單獨寫一篇文章展開。本文還有配套的精品資源點擊獲取