Skip to content
This repository has been archived by the owner on Apr 15, 2020. It is now read-only.

data 解析. tic_reader 分支 #149

Closed
yssource opened this issue Feb 12, 2018 · 22 comments
Closed

data 解析. tic_reader 分支 #149

yssource opened this issue Feb 12, 2018 · 22 comments

Comments

@yssource
Copy link

yssource commented Feb 12, 2018

膜拜一下. @datochan @rainx @yutiansut

当前 tic_reader 分支, 解析了 部分 tick 数据. 但是 data 这里没有进一步解析
tic_reader.py.

我看你 @datochan 把财务数据 #133 全部解析了. 太赞了. 👍 , 是否有兴趣看看 tick 数据的解析呢?

@datochan
Copy link

财务数据的格式不难,至于每个键值的含义不是我解析的呀,是通达信公式可以获取财务数据,找到公式的说明文档,直接复制粘贴就可以了。

至于分笔数据,我是自己计划做量化定投策略的,日线数据已经是很小粒度了,没想过要分析分笔数据。所以之前的笔记中没有。如果有时间的话我试着分析下看看吧,不过要过年了,估计时间比较紧,别抱太大期望..

@yssource
Copy link
Author

💯 🥇 @datochan @rainx @yutiansut 提前给你们拜一个早年吧. 2018, 🐶 📈

2017 年, 我才发现有 量化交易 这样一个领域. 也从你们的项目中学到了很多东西, 受益匪浅. 🎉 🎉 🎉

@rainx
Copy link
Owner

rainx commented Feb 12, 2018

@yssource 新年快乐,之前tic数据解析的时候确实做了一些尝试,后来发现有一些数据的解析还是有一定难度的,比如tic数据,经过一定的编码保存,如果只根据数据本身,很难解析其编码方式,如果深入研究,只能通过逆向通达信程序的方式来获取了,这方面我不是特别擅长。 如果后续有相关的线索,也欢迎一期讨论。

@datochan 的整理的那份解析财务信息代码确实很赞,前段时间一只再忙其它的项目,更新pytdx比较少,后面有机会也把那个整合进来吧

大家新年快乐

@yutiansut
Copy link
Collaborator

仰仗各位大佬了~ 我也顺着你们思路研究研究

@datochan
Copy link

datochan commented Feb 22, 2018

年假已过,在这里给大家拜个晚年。年假期间我大概的分析了一下tic文件的格式,结果如下:

  1. tic文件格式有点儿复杂,貌似股票数据与基金债券的数据要分开解析。

这个我看代码没法先有太大区别,只是转档时存储的格式不一致,所以就用解析的结构套了一下,基本通用。如下图:
image

  1. 某天的某只股票第一笔数据是明文的,后面每分钟内的交易详情中,时间、价格、成交量都是通过两个hash表存储的相对价格,需要根据hash表转换后才可以使用。

这个已经逆完了,只是还没写程序验证。

由于今天开始上班了,我这边的时间也确实无法保证,为了不让大家白等。我将我这边逆出来的结构及相关代码传上来。谁要是有时间就一起写程序验证一下吧,有问题再及时沟通。

下面是解析分笔详情的伪代码,附件是代码中用到的hash表数据:

int __stdcall SetTradeTime(int argTickObj)
{
  int result; // eax@1

  result = 0x23Au;
  if ( (_WORD)argTickObj < 0 )
  {
    if ( (_WORD)argTickObj <= (signed __int16)0x78u )
      return result;                            // 如果时间小于0则是标记570分钟=9点30.
  } else {
    if ( (_WORD)argTickObj <= (signed __int16)0x78u )
      return argTickObj + 0x23A;                // 上午时间
  }

  if ( (_WORD)argTickObj <= (signed __int16)0xF0u )
    result = argTickObj + 0x294;                // 下午时间需要补齐中午的时间
  return result;
}

/**
 * argTickTradeDetail 用于存放解析后的结果
 * argTickFileData tic文件数据的指针
 * argDateTime 时间日期
 */
__int16 __stdcall ParseTickDetail(TickTradeDetail *argTickTradeDetail, TickItem *argTickFileData, signed int argDateTime)
{                                                                             
  int tickDetail_type; // edx@1                                               
  signed int _tmpCount; // ecx@1                                              
  TickItem *tmpTiceFileItem; // ebx@1                                         
  unsigned int tmpSize; // ebp@1                                              
  unsigned int detailOffset; // edi@1                                         
  TickTradeDetail *argTmpTTDetail; // esi@1                                   
  unsigned __int8 tmpType; // al@1                                            
  int tmpPrice; // edx@1                                                      
  __int16 tmpCount; // cx@1                                                   
  unsigned int nextType; // eax@3                                             
  signed int tmpCheckSum; // ebx@6                                            
  int tmpValue; // eax@7                                                      
  int hashItem; // eax@9                                                      
  int tmpIdx; // esi@9                                                        
  int v17; // eax@14                                                          
  int v18; // esi@14                                                          
  char *v19; // eax@17                                                        
  int hashItemIdx; // ebx@17                                                  
  int deltaPrice; // eax@25                                                   
  unsigned int tmpIdx1; // ecx@25                                             
  unsigned __int8 v23; // sf@31                                               
  unsigned __int8 v24; // of@31                                               
  int tmpBuffer; // eax@33                                                    
  int v26; // edi@34                                                          
  int lpVolume; // esi@34                                                     
  unsigned __int8 v28; // cl@35                                               
  int v29; // edx@36                                                          
  unsigned __int8 v31; // cl@39                                               
  unsigned __int16 v32; // cx@41                                              
  unsigned __int16 v33; // dx@43                                              
  signed int v34; // edi@48                                                   
  struc_10 *lpCurrentDetail; // [sp+0h] [bp-24h]@2                            
  signed int tmpCountBak; // [sp+4h] [bp-20h]@1                               
  signed int idx; // [sp+8h] [bp-1Ch]@1                                       
  TickItem tickFileData; // [sp+10h] [bp-14h]@1                               
  unsigned __int8 v39; // [sp+2Ch] [bp+8h]@35                                 
  unsigned __int8 v40; // [sp+2Ch] [bp+8h]@43                                 
                                                                              
  tmpTiceFileItem = argTickFileData;                                          
  tmpSize = 0x20u;                                                            
  memcpy(&tickFileData, argTickFileData, sizeof(tickFileData));               
  tmpType = LOBYTE(tickFileData.type);                                        
  argTmpTTDetail = argTickTradeDetail;                                        
  tmpPrice = tickFileData.price;                // 0x0C=                      
  argTickTradeDetail->type = (unsigned __int16)tickFileData.type >> 0xFu;     
  argTickTradeDetail->volume = tickFileData.volume;                           
  tmpCount = tickFileData.count;                                              
  argTickTradeDetail->dateTime = tmpType;                                     
  _tmpCount = (unsigned __int16)tmpCount;                                     
  detailOffset = 0x18u;                                                       
  argTickTradeDetail->price = tmpPrice;                                       
  tickDetail_type = argTickFileData[1].dateTime;// tickDetail.Type            
  idx = 1;                                                                    
  tmpCountBak = _tmpCount;                                                    
  if ( _tmpCount > 1 )                                                        
  {                                                                           
    lpCurrentDetail = (struc_10 *)&argTickTradeDetail->price;                 
    do                                                                        
    {                                                                         
      nextType = (unsigned int)tickDetail_type >> 0x1Fu;                      
      tickDetail_type *= 2;                                                   
      --tmpSize;                                                              
      lpCurrentDetail[1].type = nextType;       // 设置下一个交易类型         
      if ( !tmpSize )                                                         
      {                                                                       
        if ( detailOffset >= (unsigned __int16)tickFileData.unknown           
                           + (unsigned __int16)tickFileData.volumeOffset      
                           + 0x10u )                                          
          return 0;                                                           
        tickDetail_type = *(int *)((char *)&tmpTiceFileItem->dateTime + detailOffset);
        detailOffset += 4;                                                    
        tmpSize = 0x20u;                                                      
      }                                                                       
      tmpCheckSum = 3;                                                        
LABEL_7:
      // 解析交易时间        
      tmpValue = 2 * tmpCheckSum | ((unsigned int)tickDetail_type >> 0x1Fu);  
      tickDetail_type *= 2;                                                   
      --tmpSize;                                                              
      tmpCheckSum = tmpValue;                                                 
      if ( !tmpSize )                                                         
      {                                                                       
        detailOffset += 4;                                                    
        tmpSize = 0x20u;                                                      
        tickDetail_type = *(_DWORD *)((char *)argTickFileData + detailOffset - 4);
      }                                                                       
      tmpIdx = 0;                                                             
      hashItem = (int)&gHashTableDateTime.hashValue;                          
      while ( *(_DWORD *)hashItem != tmpCheckSum )                            
      {                                                                       
        if ( *(_DWORD *)hashItem <= (unsigned int)tmpCheckSum )               
        {                                                                     
          hashItem += 6;                                                      
          ++tmpIdx;                                                           
          if ( hashItem < (signed int)&gHashTablePrice )                      
            continue;                                                         
        }                                                                     
        goto LABEL_7;                                                         
      }                                                                       
      v17 = 3 * tmpIdx;                                                       
      v18 = 3;                                                                
      lpCurrentDetail->dateTime = *((_WORD *)lpCurrentDetail - 1) + *(&gHashTableDateTime.idx + v17);// datetime£¿
LABEL_15:
      // 解析交易价格      
      v18 = ((unsigned int)tickDetail_type >> 0x1Fu) | 2 * v18;               
      tickDetail_type *= 2;                                                   
      --tmpSize;                                                              
      if ( !tmpSize )                                                         
      {                                                                       
        detailOffset += 4;                                                    
        tmpSize = 0x20u;                                                      
        tickDetail_type = *(_DWORD *)((char *)argTickFileData + detailOffset - 4);
      }                                                                       
      hashItemIdx = 0;                                                        
      v19 = (char *)&gHashTablePrice.hashValue;                               
      while ( *(_DWORD *)v19 != v18 )                                         
      {                                                                       
        if ( (unsigned int)v18 > 0x3FFFFFF || *(_DWORD *)v19 <= (unsigned int)v18 )
        {                                                                     
          v19 += 6;                                                           
          ++hashItemIdx;                                                      
          if ( (signed int)v19 < (signed int)"%stick\\ntctmp.ntc" )// hashTable的结束地址
            continue;                                                         
        }                                                                     
        goto LABEL_15;                                                        
      }                                                                       
      if ( hashItemIdx != 4000 || argDateTime < 20011112 )                    
      {                                                                       
        lpCurrentDetail[1].price = lpCurrentDetail->price + *(&gHashTablePrice.idx + 3 * hashItemIdx);
      }                                                                       
      else                                                                    
      {                                                                       
        deltaPrice = 0;                                                       
        tmpIdx1 = 0x20u;                                                      
        do                                                                    
        {                                                                     
          deltaPrice = ((unsigned int)tickDetail_type >> 0x1Fu) | 2 * deltaPrice;
          tickDetail_type *= 2;                                               
          --tmpSize;                                                          
          if ( !tmpSize )                                                     
          {                                                                   
            detailOffset += 4;                                                
            tmpSize = 0x20u;                                                  
            tickDetail_type = *(_DWORD *)((char *)argTickFileData + detailOffset - 4);
          }                                                                   
          --tmpIdx1;                                                          
        }                                                                     
        while ( tmpIdx1 );                                                    
        lpCurrentDetail[1].price = deltaPrice + lpCurrentDetail->price;       
      }                                                                       
      _tmpCount = tmpCountBak;                                                
      tmpTiceFileItem = argTickFileData;                                      
      v24 = __SETO__(idx + 1, tmpCountBak);                                   
      v23 = idx++ + 1 - tmpCountBak < 0;                                      
      ++lpCurrentDetail;                                                      
    }                                                                         
    while ( v23 ^ v24 );                                                      
    argTmpTTDetail = argTickTradeDetail;                                      
  }
  // 解析交易量           
  tmpBuffer = (unsigned __int16)tickFileData.volumeOffset + 0x14;             
  if ( _tmpCount <= 1 )                                                       
    goto LABEL_47;                                                            
  tmpBuffer += (int)tmpTiceFileItem;                                          
  lpVolume = (int)&argTmpTTDetail[1].volume;                                  
  v26 = _tmpCount - 1;                                                        
  do                                                                          
  {                                                                           
    v28 = *(_BYTE *)tmpBuffer++;                                              
    v39 = v28;                                                                
    if ( v28 <= 0xFCu )                                                       
    {                                                                         
      v29 = v39;                                                              
LABEL_44:                                                                     
      *(_DWORD *)lpVolume = v29;                                              
      goto LABEL_45;                                                          
    }                                                                         
    if ( v28 == -3 )                                                          
    {                                                                         
      v31 = *(_BYTE *)tmpBuffer++;                                            
      v29 = v31 + 0xFD;                                                       
      goto LABEL_44;                                                          
    }                                                                         
    if ( v28 == -2 )                                                          
    {                                                                         
      v32 = *(_WORD *)tmpBuffer;                                              
      tmpBuffer += 2;                                                         
      *(_DWORD *)lpVolume = v32 + 0xFE;                                       
      goto LABEL_45;                                                          
    }                                                                         
    if ( v28 == -1 )                                                          
    {                                                                         
      v33 = *(_WORD *)(tmpBuffer + 1);                                        
      v40 = *(_BYTE *)tmpBuffer;                                              
      tmpBuffer += 3;                                                         
      v29 = 0xFFFF * v40 + v33 + 0xFF;                                        
      goto LABEL_44;                                                          
    }                                                                         
LABEL_45:                                                                     
    lpVolume += 0x10u;                                                        
    --v26;                                                                    
  }                                                                           
  while ( v26 );                                                              
  _tmpCount = tmpCountBak;                                                    
  argTmpTTDetail = argTickTradeDetail;                                        
LABEL_47:           
  if ( _tmpCount > 0 )                                                        
  {                                                                           
    v34 = _tmpCount;
    // 格式化交易时间                              
    do                                                                        
    {                                                                         
      LOWORD(tmpBuffer) = argTmpTTDetail->dateTime;                           
      tmpBuffer = SetTradeTime(tmpBuffer);                                    
      argTmpTTDetail->dateTime = tmpBuffer;                                   
      ++argTmpTTDetail;                                                       
      --v34;                                                                  
    }                                                                         
    while ( v34 );                                                            
  }                                                                           
  return tickFileData.count;                                                  
}                                                                             

raw.go.zip

@rainx
Copy link
Owner

rainx commented Feb 22, 2018

@datochan 这个太牛了,还有这个010editor感觉挺好用的,我之前一只想找一个类似的软件,感觉可以试试

@datochan
Copy link

@rainx
恩,这个编辑器很好用,逆出来的结构不需要怎么修改就可以变成它的模板,往数据文件上套一下验证数据什么的很方便。

@zzeric
Copy link

zzeric commented Feb 22, 2018

tic文件怎么获取到本地?

@datochan
Copy link

datochan commented Feb 22, 2018

@zzeric
大致流程如下:

  1. 下载这个文件: http://www.tdx.com.cn/downit.zip
  2. 解析这个压缩包中的配置文件downit5.cfg

这里面有基本面数据权息数据、日线数据、分笔数据等各种数据的下载url。

  1. /products/data/data/2ktic/这里面就是这个分支要解析的数据格式

下载过程比较简单,拼接好URL之后完全可以脚本自动化。比如下载2018年1月31日的分笔数据就是:
http://www.tdx.com.cn/products/data/data/2ktic/20180131.zip

@zzeric
Copy link

zzeric commented Feb 23, 2018

哦,直接下载解析tic就可以替代get_history_transaction_data,效率是能提高很多,唯一可惜的是tic文件里分笔数据也不带bid和ask数据,不知道downit5.cfg里的g3tic是不是也是这样的

@datochan
Copy link

datochan commented Mar 17, 2018

难得周末有时间,就大概整理了下逆向的代码,这里是链接: 通达信tic文件格式解析

由于数据解析是强类型数据转换,python这种脚本解析代码可能会比较麻烦,所以没有写python的解析例子。

代码没有整理优化(比较难看,但是应该能看懂),只是为了说明Tic的文件格式,解析的数据我也没有仔细校对,应该是差不多的,如下图:

image

@rainx @yssource @yutiansut

@datochan
Copy link

datochan commented Mar 17, 2018

最后再说明一下问题 #103 中涉及到的 .idx, .edx, .ntc, .etc的文件格式:

  • .ntc, .etc: 这些是某只股票或者基金的分笔数据文件,数据是按照顺序追加到文件中的。

.etc: 文件是基金数据文件,数据没有经过加密,格式如下:

00000000 TickTradeDetail struc ; (sizeof=0x10)
00000000 dateTime        dw ?                    ; 开市后的分钟数,通过 SetTradeTime() 转换。
00000002 price           dd ?                    ; 成交价格,需要再处理一下
00000006 volume          dd ?                    ; 成交
0000000A count           dd ?                    ; 笔数
0000000E type            dw ?                    ; 0=buy;1=sell;2=unknown
00000010 TickTradeDetail ends

.ntc: 文件是股票数据文件,数据是有加密的,结构如下:

00000000 TickDetail      struc ; (sizeof=0x8)
00000000 type            dd ?                    ; base 16
00000004 unknown2        dd ?                    ; base 16
00000008 TickDetail      ends
00000008
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 TickItem        struc ; (sizeof=0x14, variable size)
00000000 dateTime        dd ?
00000004 count           dw ?
00000006 volumeOffset    dw ?                    ; base 16
00000008 volumeSize      dw ?                    ; base 16
0000000A type            dw ?
0000000C price           dd ?
00000010 volume          dd ?
00000014 tickDetail      db 0 dup(?)             ; struct  offset
00000014 TickItem        ends
  • .idx, .edx: 这些是索引文件。是通达信同于管理这些分笔数据的索引文件。

由于用户保存分笔数据无法绝对按照顺序保存,所以通过索引文件来定位某天的分笔数据在数据文件中的偏移。

索引文件结构是统一的,格式如下:

typedef struct {
    int  itemDate;     // 指定的日期
    WORD size;         // 日期对应的逐笔数据大小
    DWORD unknown      <format=hex>;     // 
} DateNode;

typedef struct {
    int startDate;     // 分笔数据的开始日期
    int endDate;       // 分笔数据的结束日期
    WORD dayCount;     // 天数
    DateNode items[dayCount];
} TICK_IDX;

附件上传索引文件的解析格式:
TdxIdxFile.bt
TdxTicFile.bt

@rainx
Copy link
Owner

rainx commented Mar 19, 2018

@datochan cool !

@zfsamzfsam
Copy link

pytdx最好能通过Resample方式从tic文件中得到1MIN/5MIN/1Day周期的K线数据
这样似乎可以减少对通达信软件的依赖来获取1MIN/5MIN/1Day周期数据

@zzeric
Copy link

zzeric commented Mar 29, 2018

resample不是不可以,但需要注意沪深交易所对收盘价的处理,并不是最后一tick的price,而且沪深好像还有点差异。

收盘价:
沪市收盘价为当日该证券最后一笔交易前一分钟所有交易的成交量加权平均价(含最后一笔交易)。当日无成交的,以前收盘价为当日收盘价。

深市的收盘价通过集合竞价的方式产生。收盘集合竞价不能产生收盘价的,以当日该证券最后一笔交易前一分钟所有交易的成交量加权平均价(含最后一笔交易)为收盘价。当日无成交的,以前收盘价为当日收盘价。

@xiaoheige
Copy link

xiaoheige commented May 22, 2018

需要解析本地tick文件,找好久没有找到现成的python代码,参照 @datochan 的go代码写了python版的供大家参考,准确性待持续验证

import struct

def gettime(s):
    if s <= 120:
        re = s + 570
    else:
        re = s + 660
    return str(re / 60 % 24).zfill(2) + ':' + str(re % 60).zfill(2)

def getvolume(vol, fh):
    re = 0
    if vol <= 252:
        re = vol
    elif vol == 253:
        bin_tmp = fh.read(1)
        line_tmp = struct.unpack('<B', bin_tmp)
        re = vol + line_tmp[0]
    elif vol == 254:
        bin_tmp = fh.read(2)
        line_tmp = struct.unpack('<H', bin_tmp)
        re = vol + line_tmp[0]
    elif vol == 255:
        bin_tmp = fh.read(1)
        line_tmp = struct.unpack('<B', bin_tmp)
        re = 0xFFFF * line_tmp[0]
        bin_tmp = fh.read(2)
        line_tmp = struct.unpack('<H', bin_tmp)
        re += line_tmp[0] + 0xFF
    return re

def shl(val):
    val <<= 1
    if len(str(bin(val))) > 34:
        str1 = 'tmp = 0b' + str(bin(val))[len(str(bin(val)))-34+2:]
        exec(str1)
        return tmp
    return val


def get_tick_data_bin(datafile):
    items = []
    with open(datafile, 'rb') as fh:
        bin_data = fh.read(20)
        #line = struct.unpack('<IIHIHI', bin_data) # .idx: 开始日期 结束日期 天数 日期节点 日期对应的数据大小 unknown
        line = struct.unpack('<IHHHHII', bin_data) # .ntc 日期 当天总记录数 volumeOffset volumeSize type 价格 成交量
        # 注:time、type待确认准确性
        items.append({
            'date': line[0],
            'time': (line[4] & 255), #type进行LOBYTE()操作获得
            'price': line[5],
            'volume': line[6],
            'type': line[4] >> 14,
            'count': line[1], # 当天总记录数
            'voloffset': line[2],
            'volsize': line[3]
        })

        # 时间和价格
        #bin_data = fh.read(line[2])
        bin_size = 32
        bin_data = fh.read(4)
        bin_row = struct.unpack('<I', bin_data)[0]
        for i in xrange(line[1] - 1):
            per = {}
            per['type'] = int(bin_row >> 31)

            bin_row = shl(bin_row)
            bin_size -= 1
            if bin_size == 0:
                bin_data = fh.read(4)
                bin_row = struct.unpack('<I', bin_data)[0]
                bin_size = 32

            # 解析时间
            checksum = 3
            go_out = False
            while not go_out:
                # LABEL1 begin
                checksum = (2 * checksum) | (bin_row >> 31)
                bin_row = shl(bin_row)
                bin_size -= 1
                if bin_size == 0:
                    bin_data = fh.read(4)
                    bin_row = struct.unpack('<I', bin_data)[0]
                    bin_size = 32
                idx = 0
                while True:
                    if HashTableDateTime[idx].values()[0] != checksum:
                        if HashTableDateTime[idx].values()[0] < checksum:
                            idx += 1
                            if idx < len(HashTableDateTime):
                                continue
                            else:
                                #print ' - goto LABEL1-1 -'
                                break
                        else:
                            #print ' - goto LABEL1-2 -'
                            break
                    else:
                        go_out = True
                        break
            per['time'] = int(items[-1]['time']) + HashTableDateTime[idx].keys()[0]

            # 解析价格
            checksum = 3
            go_out = False
            while not go_out:
                # LABEL2 begin
                checksum = (2 * checksum) | (bin_row >> 31)
                bin_row = shl(bin_row)
                bin_size -= 1
                if bin_size == 0:
                    bin_data = fh.read(4)
                    bin_row = struct.unpack('<I', bin_data)[0]
                    bin_size = 32
                idx = 0
                while True:
                    if HashTablePrice[idx].values()[0] != checksum:
                        if checksum > 0x3FFFFFF or HashTablePrice[idx].values()[0] <= checksum:
                            idx += 1
                            if idx < len(HashTablePrice):
                                continue
                            else:
                                #print ' - goto LABEL2 -'
                                break
                        else:
                            #print ' - goto LABEL2 -'
                            break
                    else:
                        go_out = True
                        break
            if idx != 4000 or line[0] < 20011112:
                per['price'] = int(items[-1]['price']) + HashTablePrice[idx].keys()[0]
            else:
                checksum = 0
                for idx in xrange(1, 33):
                    checksum = (2 * checksum) | (bin_row >> 31)
                    bin_row = shl(bin_row)
                    bin_size -= 1
                    if bin_size == 0:
                        bin_data = fh.read(4)
                        bin_row = struct.unpack('<I', bin_data)[0]
                        bin_size = 32
                per['price'] = int(items[-1]['price']) + checksum

            items.append(per)

        # 成交量
        for k in xrange(1, line[1]):
            bin_data = fh.read(1)
            line = struct.unpack('<B', bin_data)
            items[k]['volume'] = getvolume(line[0], fh)

    # output
    print "time\tprice\tvolume\ttype"
    for per in items:
        print "%s\t%.2f\t%d\t%d" % (gettime(per['time']), per['price'] / 100.0, per['volume'], per['type'])


HashTableDateTime = (
    {0: 0x06},
    {1: 0x0F},
    {2: 0x1D},
    {3: 0x38},
    {4: 0x72},
    {6: 0x1CC},......) # 完整内容请自行补充 [raw.go](https://github.com/datochan/ParseTicFile/blob/master/tic/raw.go)

HashTablePrice = (
    {0: 0x7},
    {1: 0x19},
    {-1: 0x1B},
    {2: 0x30},
    {-2: 0x34},
    {4: 0x0C4},
    {-5: 0x0C6},
    {-4: 0x0C7},
    {3: 0x0D5},
    {-3: 0x0D7},......)


if __name__ == '__main__':
    #datafile = '/data/pystock/tdx/daily/data/vipdoc/tick/sh600136.idx'
    datafile = '/data/pystock/tdx/daily/data/vipdoc/tick/sh600136.ntc'
    get_tick_data_bin(datafile)

@yutiansut
Copy link
Collaborator

@xiaoheige

@datochan
Copy link

@xiaoheige 干得漂亮,如果准确性没问题的话,可以关闭话题了,哈哈。

@yssource
Copy link
Author

👍 💯 🥇

@rainx
Copy link
Owner

rainx commented May 30, 2018

@xiaoheige cool 👍, 呵呵,这几天一直在忙一个react native 的项目 ,好久没回来看,等项目忙完我好好整理一下

@tauruswang
Copy link

nice, great job!!!

@Iseuwei
Copy link

Iseuwei commented Feb 17, 2020

喜极而泣,,

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants