同花顺 hd1.0 格式数据文件分析
history 下的分钟数据(*.min,*.min5)、日数据(*.day),[用户目录]\download中 Fin 和 Panhou 的 *.dat 文件都是 hd1.0 格式的数据文件。他们格式基本一致。
Fin 中的 dat 文件只分析了一点,在我这里只存了一点古老的数据,感觉没啥价值。其他的只有个别字段没分析出来,在同花顺中没找到对应的值。
用 010 Editor 的 Template 格式描述如下:
//------------------------------------------------ //--- 010 Editor v10.0.2 Binary Template // // File: 10jqka data file // Authors: lx // Version: 1.0 // Purpose: // Category: Database // File Mask: *.min,*.min5,*.day,*.dat // ID Bytes: 68 64 31 2E 30 00 // History: //------------------------------------------------ LittleEndian(); enum FileType { fUnknown, fMin, fDay, fDat }; FileType getCurrentFileType() { local string filename = GetFileName(); local string ext = FileNameGetExtension(filename); if (Strcmp(ext, ".min") == 0 || Strcmp(ext, ".min5") == 0) { return fMin; } else if (Strcmp(ext, ".day") == 0) { return fDay; } else if (Strcmp(ext, ".dat") == 0) { return fDat; } else { return fUnknown; } } local FileType fileType = getCurrentFileType(); enum <uint> FieldType { ftDateTime = 0x003001, ftOpening = 0x007007, // 开盘价 ftHighestIndex= 0x007008, // 最高指数 ftLowestIndex = 0x007009, // 最低指数 ftClose = 0x00700B, // 收盘价 ftTradeVolume = 0x007013, // 成交金额(元) ftTotalVolume = 0x00700D, // 成交量(股) ftBuyTurnover = 0x00700E, // 外盘 ftSellTurnover= 0x00700F, // 内盘 ftDate64 = 0x00312D, }; typedef struct _FieldDef { BitfieldDisablePadding(); FieldType fieldType:24; ubyte size:8; } FieldDef <optimize=false>; typedef struct _DateTime { BitfieldDisablePadding(); byte minute: 6; byte hours: 5; byte day: 5; byte month: 4; short year: 12; } DateTime <optimize=false, read=readDateTime>; string readDateTime(DateTime &date) { string s; SPrintf(s, "%d-%d-%d %d:%d", date.year + 1900, date.month, date.day, date.hours, date.minute); return s; } typedef struct _Trade { BitfieldDisablePadding(); uint value: 28; byte reserved: 4; } Trade <optimize=false, read=readTrade>; string readTrade(Trade &trade) { string s; SPrintf(s, "%.02f", trade.value / 1000.0); return s; } void defineUnknownField(uint j, ubyte size) { if (size == 4) { switch (j) { case 0: uint field00; break; case 1: uint field01; break; case 2: uint field02; break; case 3: uint field03; break; case 4: uint field04; break; case 5: uint field05; break; case 6: uint field06; break; case 7: uint field07; break; case 8: uint field08; break; case 9: uint field09; break; case 10: uint field10; break; case 11: uint field11; break; case 12: uint field12; break; case 13: uint field13; break; case 14: uint field14; break; case 15: uint field15; break; case 16: uint field16; break; case 17: uint field17; break; case 18: uint field18; break; case 19: uint field19; break; case 20: uint field20; break; case 21: uint field21; break; case 22: uint field22; break; case 23: uint field23; break; case 24: uint field24; break; case 25: uint field25; break; case 26: uint field26; break; case 27: uint field27; break; case 28: uint field28; break; case 29: uint field29; break; case 30: uint field30; break; case 31: uint field31; break; case 32: uint field32; break; case 33: uint field33; break; case 34: uint field34; break; case 35: uint field35; break; case 36: uint field36; break; case 37: uint field37; break; case 38: uint field38; break; case 39: uint field39; break; } } else if (size == 8) { switch (j) { case 0: double field00; break; case 1: double field01; break; case 2: double field02; break; case 3: double field03; break; case 4: double field04; break; case 5: double field05; break; case 6: double field06; break; case 7: double field07; break; case 8: double field08; break; case 9: double field09; break; case 10: double field10; break; case 11: double field11; break; case 12: double field12; break; case 13: double field13; break; case 14: double field14; break; case 15: uint64 field15; break; case 16: uint64 field16; break; case 17: uint64 field17; break; case 18: uint64 field18; break; case 19: uint64 field19; break; case 20: uint64 field20; break; case 21: uint64 field21; break; case 22: uint64 field22; break; case 23: uint64 field23; break; case 24: uint64 field24; break; case 25: uint64 field25; break; case 26: uint64 field26; break; case 27: uint64 field27; break; case 28: uint64 field28; break; case 29: uint64 field29; break; case 30: uint64 field30; break; case 31: uint64 field31; break; case 32: uint64 field32; break; case 33: uint64 field33; break; case 34: uint64 field34; break; case 35: uint64 field35; break; case 36: uint64 field36; break; case 37: uint64 field37; break; case 38: uint64 field38; break; case 39: uint64 field39; break; } } else { Printf("j = %d, size = %d\n", j, size); Exit(-1); } } typedef struct _Record(uint columnCount, uint columnDefs[], ubyte colSizes[], byte isDateTime) { BitfieldDisablePadding(); local uint i = 0, j = 0; for (i = 0; i < columnCount; ++i) { switch (columnDefs[i]) { case ftDateTime: if (fileType == fDay) uint date; else if (isDateTime == 1) DateTime datetime; else uint date; break; case ftOpening: Trade opening; break; case ftHighestIndex: Trade highestIndex; break; case ftLowestIndex: Trade lowestIndex; break; case ftClose: Trade close; break; case ftTradeVolume: Trade tradeVolume; break; case ftTotalVolume: uint totalVolume; break; case ftBuyTurnover: uint buyTurnover; break; case ftSellTurnover: uint sellTurnover; break; case ftDate64: uint64 date; break; default: defineUnknownField(j, colSizes[i]); ++j; } } } Record <optimize=false>; enum <byte> StockType { stHuA = 0x11, // 沪A stHuB = 0x12, // 沪B stHuBond = 0x13, // 债券 stHuFund = 0x14, // 基金 stHuDelist = 0x15, // 退市整理 stHuST = 0x16, // ST股、风险警示 stShenA = 0x21, // 深A stShenB = 0x22, // 深B stShenBond = 0x23, // 债券 stShenFund = 0x24, // 基金 stShenDelist = 0x25, // 退市整理 stShenST = 0x26, // ST股、风险警示 }; typedef struct _StockInfo { BitfieldDisablePadding(); StockType stockType; char code[9]; uint16 emptyCount; uint32 startIndex; uint16 totalCount; } StockInfo <optimize=false>; struct Body { char header[6]; uint32 recordCount; uint16 recordStartOffset; uint16 recordLength; uint16 recordColumnCount; FieldDef columnDefs[recordColumnCount]; local byte isDateTime = 1; if (fileType == fDat) { local int64 pos = FTell(); local int16 temp = ReadUShort(pos); if (temp == 0) { FSeek(pos + 32); isDateTime = 0; } else { FSeek(pos); } uint16 recordRelOffset; uint16 stockInfoCount; StockInfo stockInfos[stockInfoCount]; } FSeek(recordStartOffset); local uint tempColDefs[recordColumnCount]; local ubyte tempColSizes[recordColumnCount]; local uint i; for (i = 0; i < recordColumnCount; ++i) { tempColDefs[i] = columnDefs[i].fieldType; tempColSizes[i] = columnDefs[i].size; } Record records(recordColumnCount, tempColDefs, tempColSizes, isDateTime)[recordCount]; } body <optimize=false>;