通达信V6.1概念板块分类文件格式分析

本文介绍通达信V6中block.dat文件的结构和数据格式,涵盖文件头信息、板块索引及记录详情,并提供Delphi示例代码展示如何读取这些数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通达信V6概念板块分类文件格式分析

文件位置

/jcb_zxjt/T0002/hq_cache/ block.dat

 

数据格式

1)、文件头部信息

数据含义

数据类型

备注

文件信息

Char[64]

 

板块索引信息起始位置

Integer

 

板块记录信息起始位置

Integer

 

未知

Integer * 3

 

 

2)、板块索引信息,开始于0x0054h

数据含义

数据类型

备注

索引名称

Char[64]

 

未知

Integer * 9

 

注意:

1)、每个板块索引信息占的长度为100个字节。

 

3)、板块记录信息,开始于0x0180h

数据含义

数据类型

备注

板块数量

word

起始位置为0x180h

 

板块记录结构

数据含义

数据类型

备注

板块名称

Char [9]

 

证券数量

word

 

板块级别

word

 

证券代码

Char [7] * 400

 

注意:

1)、第一个版块的起始位置为0x182h

2)、每个板块占的长度为2813个字节。

3)、每个板块最多包括400只股票。(2813 -9 - 2 - 2) / 7 =  400

 

 

示例代码

示例:显示板块数据文件信息
单元:uDataBuffer

备注:uDataBuffer单元代码在“大智慧Level2日线数据文件格式分析”文档中。

 

单元:uBlockData

unit uBlockData;

 

interface

 

uses

    uDataBuffer;

 

type

    TFileHead_Block = packed record

        FileInfo: array[0..63] of char; //--文件信息

        BlockIndexStart: Integer; //--板块索引信息起始位置

        BlockDataStart: Integer; //--板块记录信息起始位置

        Unknown: array[0..2] of Integer; //--未知

    end;

    PFileHead_Block = ^TFileHead_Block;

 

    TIndexRecord_Block = packed record

        IndexName: array[0..63] of char; //--索引名称

        Unknown: array[0..8] of Integer; //--未知

    end;

    PIndexRecord_Block = ^TIndexRecord_Block;

 

    TStockCode = array[0..6] of char;

 

    TDataRecord_Block = packed record

        BlockName: array[0..8] of char; //--板块名称

        StockCount: word; //--证券数量

        BlockLevel: word; //--板块级别

        StockCodes: array[0..399] of TStockCode; //--证券代码

    end;

    PDataRecord_Block = ^TDataRecord_Block;

 

    TStockDataStream_Block = class(TCustomStringBuffer)

    private

        FFileHead: TFileHead_Block;

        FIndexCount: Integer;

        FIndexSize: Integer;

        FDataCount: word;

        FDataSize: Integer;

        function GetDatas(Index: Integer): PDataRecord_Block;

        function GetHead: PFileHead_Block;

        function GetIndexs(Index: Integer): PIndexRecord_Block;

    protected

        procedure ClearBuffer; override;

        procedure DoBufferChange; override;

    public

        constructor Create;

        //---

        property Head: PFileHead_Block read GetHead;

        property Datas[Index: Integer]: PDataRecord_Block read GetDatas;

        property DataCount: word read FDataCount;

        property Indexs[Index: Integer]: PIndexRecord_Block read GetIndexs;

        property IndexCount: Integer read FIndexCount;

    end;

 

implementation

 

constructor TStockDataStream_Block.Create;

begin

    inherited;

    //---

    FIndexSize := sizeof(TIndexRecord_Block);

    FDataSize := sizeof(TDataRecord_Block);

end;

 

procedure TStockDataStream_Block.ClearBuffer;

begin

    inherited;

    //---

    FIndexCount := 0;

    FDataCount := 0;

end;

 

procedure TStockDataStream_Block.DoBufferChange;

    //---

    function _ReadFileHead: Boolean;

    begin

        Result := self.BufferSize >= SizeOf(FFileHead);

        if Result then

            Move(self.Buffer^,FFileHead,SizeOf(FFileHead));

    end;

    //---

    function _ReadIndex: Boolean;

    var

        ABlockIndexLen: integer;

    begin

        Result := self.BufferSize >= FFileHead.BlockDataStart;

        if Result then

        begin

            ABlockIndexLen := (FFileHead.BlockDataStart - FFileHead.BlockIndexStart);

            FIndexCount := ABlockIndexLen div FIndexSize;

            //---

            Result := ABlockIndexLen = FIndexSize * FIndexCount;

        end;

    end;

    //---

    function _ReadData: Boolean;

        //---

        function _GetDataCount: Boolean;

        var

            p: Pchar;

        begin

            Result := self.BufferSize >= FFileHead.BlockDataStart + SizeOf(FDataCount);

            if Result then

            begin

                p := self.Buffer;

                inc(p,FFileHead.BlockDataStart);

                Move(p^,FDataCount,SizeOf(FDataCount));

                //---

                Result := FDataCount > 0;

            end;

        end;

        //---

        function _CheckDataLen: Boolean;

        begin

            Result := self.BufferSize = FFileHead.BlockDataStart + SizeOf(FDataCount) + FDataSize * FDataCount;

        end;

    begin

        Result := _GetDataCount and _CheckDataLen;

    end;

begin

    inherited;

    //---

    if FDataSize <= 0 then

        self.ClearBuffer

    else

    begin

        if not (_ReadFileHead and _ReadIndex and _ReadData) then

            self.ClearBuffer;

    end;

end;

 

function TStockDataStream_Block.GetDatas(Index: Integer): PDataRecord_Block;

begin

    Result := Pointer(self.Buffer + FFileHead.BlockDataStart + SizeOf(FDataCount) + FDataSize * Index);

end;

 

function TStockDataStream_Block.GetHead: PFileHead_Block;

begin

    Result := @FFileHead;

end;

 

function TStockDataStream_Block.GetIndexs(Index: Integer): PIndexRecord_Block;

begin

    Result := Pointer(self.Buffer + FFileHead.BlockIndexStart + FIndexSize * Index);

end;

 

end.

 

 

单元:Unit1

unit Unit1;

 

interface

 

uses

    Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,

    Dialogs,StdCtrls,ExtCtrls;

 

type

    TForm1 = class(TForm)

        Button1: TButton;

        ListBox1: TListBox;

        GroupBox1: TGroupBox;

        OpenDialog1: TOpenDialog;

        RadioGroup1: TRadioGroup;

        Panel1: TPanel;

        procedure FormCreate(Sender: TObject);

        procedure Button1Click(Sender: TObject);

    private

        procedure ShowData_Block(const AFile: string; const AListBox: TListBox);

    public

        procedure ShowData(const AFile: string; const AListBox: TListBox);

    end;

 

var

    Form1: TForm1;

 

implementation

 

uses uDayData,uCacheDayData,uZstData,uBlockData;

 

{$R *.dfm}

 

procedure TForm1.FormCreate(Sender: TObject);

begin

    with RadioGroup1.Items do

    begin

        clear;

        Add('概念板块数据');

    end;

    RadioGroup1.ItemIndex := 0;

    //---

    SendMessage(ListBox1.Handle,LB_SetHorizontalExtent,2000,longint(0));

end;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

    with self.OpenDialog1 do

    begin

        if Execute then

            self.ShowData(FileName,ListBox1);

    end;

end;

 

procedure TForm1.ShowData(const AFile: string; const AListBox: TListBox);

begin

    case RadioGroup1.ItemIndex of

        0: ShowData_Block(AFile,AListBox);

    end;

end;

 

procedure TForm1.ShowData_Block(const AFile: string;

    const AListBox: TListBox);

var

    AStream: TStockDataStream_Block;

    //---

    procedure _ShowHead;

    var

        i: integer;

    begin

        with AListBox.Items,AStream.Head^ do

        begin

            Add(Format('文件信息:%s', [FileInfo]));

            Add(Format('板块索引起始位置:%d', [BlockIndexStart]));

            Add(Format('板块记录起始位置:%d', [BlockDataStart]));

            //---

            for i := low(Unknown) to high(Unknown) do

                Add(Format('未知:%d', [Unknown[i]]));

        end;

    end;

    //---

    procedure _ShowIndex;

    var

        j,AIndex: Integer;

    begin

        with AListBox.Items,AStream do

        begin

            Add('--------索引---------');

            //---

            for AIndex := 0 to IndexCount - 1 do

            begin

                with Indexs[AIndex]^ do

                begin

                    Add(Format('索引名称:%s', [IndexName]));

                    //---

                    for j := low(Unknown) to high(Unknown) do

                        Add(Format('未知:%d', [Unknown[j]]));

                end;

            end;

        end;

    end;

    //---

    procedure _ShowData;

    var

        ABlockIndex,AStockIndex: Integer;

    begin

        with AListBox.Items,AStream do

        begin

            Add('--------板块---------');

            //---

            Add(Format('板块数量:%d', [DataCount]));

            if DataCount > 0 then

                Add(Format('板块数据大小:%d', [sizeof(Datas[ABlockIndex]^) * DataCount]));

            Add(' ');

            //---

            for ABlockIndex := 0 to DataCount - 1 do

            begin

                with Datas[ABlockIndex]^ do

                begin

                    Add(Format('板块%d 板块名称:%s 证券数量:%d 板块级别:%d', [ABlockIndex + 1,BlockName,StockCount,BlockLevel]));

                    for AStockIndex := low(StockCodes) to high(StockCodes) do

                        Add(Format('%.3d 代码:%s', [AStockIndex + 1,StockCodes[AStockIndex]]));

                end;

            end;

        end;

    end;

begin

    AStream := TStockDataStream_Block.Create;

    try

        with AListBox.Items do

        begin

            BeginUpdate;

            Clear;

            with AStream do

            begin

                if ReadFile(AFile) then

                begin

                    _ShowHead;

                    _ShowIndex;

                    _ShowData;

                end;

            end;

            EndUpdate;

        end;

    finally

        AStream.Free;

    end;

end;

 

end.

 

### 如何使用Python读取和处理通达信本地文件概念板块数据 通达信软件中的`vipdoc`文件夹包含了各种股票的历史行情数据,其中包括概念板块的相关信息。为了能够利用这些数据进行进一步的分析或开发交易策略,可以通过Python解析并加载这些数据。 #### 数据路径与结构说明 通达信的数据通常存放在其安装目录下的`vipdoc`文件夹中。具体来说,不同市场的数据会按照市场分类存储在子文件夹中,例如沪深A股的日线数据位于`shlday`和`szzxlday`等文件夹下[^1]。对于概念板块数据,可能涉及多个文件组合而成,因此需要先了解具体的文件命名规则以及字段含义。 #### 解析步骤概述 以下是通过Python实现对通达信本地文件概念板块数据的操作流程: 1. **定位目标文件** 需要确认哪些文件包含所需的概念板块信息,并记录它们的具体位置。 2. **二进制方式打开文件** 使用Python内置函数以二进制模式(`rb`)打开指定文件,因为原始数据可能是经过压缩或者特殊编码保存下来的。 3. **逐条提取有效信息** 基于已知的数据格式(如每笔记录占用多少字节数),采用struct模块解码相应部分的内容。 4. **转换为易于操作的形式** 将解析后的数值映射至更直观的对象表示形式,比如Pandas DataFrame表格便于后续统计计算。 下面给出一段示范代码来展示上述过程的一部分逻辑: ```python import os import struct import pandas as pd def read_concept_data(file_path): """Read concept data from TongdaXin local files.""" records = [] with open(file_path, 'rb') as f: while True: buf = f.read(32) # Assuming each record is fixed length of bytes. if not buf or len(buf)<32: break stock_code, _, date_, opeing_price, highest_price,\ lowest_price, closing_price, turnover_volume\ = struct.unpack('<8sIIfIIIII', buf[:32]) formatted_record={ "StockCode":stock_code.decode().strip('\x00'), "Date":pd.to_datetime(date_), "OpenPrice":opeing_price/100, "HighPrice":highest_price/100, "LowPrice":lowest_price/100, "ClosePrice":closing_price/100, "Volume":turnover_volume} records.append(formatted_record) df=pd.DataFrame(records) return df if __name__ == '__main__': vip_doc_dir='path/to/vipdoc' sh_day_file=os.path.join(vip_doc_dir,'shlday','example.shd') result_df=read_concept_data(sh_day_file) print(result_df.head()) ``` 此脚本仅作为基础框架提供参考价值,在实际应用前还需调整参数适配真实环境需求[^2]。 另外需要注意的是,由于涉及到版权保护等问题,某些特定类型的文件可能会被额外加密处理,此时单纯依靠公开资料难以完成全部解读工作,则需寻求官方授权接口或其他合法途径获取标准化API支持[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值