Rovan

      一个犁牛半块田,收也凭天,荒也凭天, 清茶淡饭饱三餐,早也香甜,晚也香甜, 布衣得暖胜丝绵,长也可穿,短也可穿, 草舍茅屋有几间,行也安然,待也安然, 雨过天青驾小船,鱼在一边,酒在一边, 夜归儿女话灯前,今也有言,古也有言, 日上三竿我独眠,请是神仙,我是神仙.

首页 新随笔 联系 订阅 管理

大智慧日K线的数据结构

大智慧日K线的数据结构
    大智慧股票行情软件是目前应用广泛的一个炒股工具,有时我们需要自编炒股的算法进行研究,如提取某只股票的收盘价,成交量等,这时候如果能直接读大智慧股票分析系统的数据格式,将对软件的编制带来极大的方便。(注:大智慧用的钱龙数据格式,本文适用于钱龙股票行情软件中的日k线数据)。本文主要描述了在Delphi下大智慧日K线的数据结构,和以动态数组方式提取数据的方法。
    一、数据文件和数据结构:
    大智慧数据文件和数据结构:(假设大智慧股票行情软件安装在D:dzh目录下)
    上海日线存储路径为:D:dzhDATASHaseDay,文件扩展名为:.day
    上海周线存储路径为:D:dzhDATASHaseweek,文件扩展名为: .wek
    上海月线存储路径为:D:dzhDATASHasemonth,文件扩展名为: .mnt
    深圳日线存储路径为:D:dzhDATASZnseDay
    深圳周线存储路径为:D:dzhDATASZnseweek
    深圳月线存储路径为:D:dzhDATASZnsemonth
    周线,月线格式与日线格式一致.
    以深发展日线为例:
    1A76:0100 D6 CD 2F 01 52 07 01 00-52 07 01 00 52 07 01 00
    1A76:0110 52 07 01 00 86 0F 00 00-4D 02 00 00 00 00 00 00
    1A76:0120 00 00 00 00 00 00 00 00-D7 CD 2F 01 60 03 01 00
    1A76:0130 60 03 01 00 60 03 01 00-60 03 01 00 82 05 00 00
    1A76:0140 D4 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00

每一条记录的长度为40字节:
1-4字节为日期,D6 CD 2F 01转换为十进制是:19910102
5-8字节=开盘价(元)*1000
9-12字节=最高价(元)*1000
13-16字节=最低价(元)*1000
17-20字节=收盘价(元)*1000
21-24字节=成交金额(元)/1000
25-28字节=成交量(手)
其余12字节未使用
实现步骤:
1、先定义日线数据结构数组
2、再以实际记录数分配动态数组空间
3、然后把数据读入相应数组中

Procedure  TFormKXianMain.ReadData(Sender: Tobject);//读取日k线数据文件中的开盘价、最高价、最低价、收盘价、成交金额、成交量
Var I:Integer;
Var FileName:String;//日k线数据文件
Var DataFile:File;
//-----------------定义日线数据结构数组----------
Var DataDate: LongWord;//日期数组
Var DataOpen: LongWord;//开盘价数组
Var DataHigh: LongWord;//最高价数组
Var DataLow: LongWord;//最低价数组
Var DataClose: LongWord;//收盘价数组
Var DataShuLiang: LongWord;//成交量数组
Var DataJinE: LongWord;//成交金额数组
Var DataNoOne: LongWord;
Var DataNoTwo: LongWord;
Var DataNoThree: LongWord;
//----------------------------------------------
Begin
  Try
    DayCount:=0;
   FileName:=‘D:dzhDATASZnseDay001.day‘;//此处根据文件的具体路径填写
    If FileExists(FileName) Then
    Begin
    AssignFile(DataFile, Filename);
    Reset(DataFile,1);
    //-------以实际记录数分配动态数组空间--------
    DayCount:=Round(FileSize(DataFile)/40);
    //基本数据
    SetLength(DayData,7);
    For I := Low(DayData) to High(DayData) do
       SetLength(DayData[I],DayCount);
    I:=0;
    //------------------------------------------
    //============把数据读入相应数组中===========
    while not Eof(DataFile) do
    Begin
        BlockRead(DataFile, DataDate, SizeOf(DataDate));
        DayData[0][I]:=DataDate;//读取日期数据放入日期数组中
        BlockRead(DataFile, DataOpen, SizeOf(DataOpen));
        DayData[1][I]:=DataOpen; //读取开盘数据放入开盘数组中
        BlockRead(DataFile, DataClose, SizeOf(DataHigh));
        DayData[4][I]:=DataClose; //读取收盘数据放入收盘数组中
        BlockRead(DataFile, DataHigh, SizeOf(DataLow));
        DayData[2][I]:=DataHigh;  //读取最高价数据放入最高价数组中
        BlockRead(DataFile, DataLow, SizeOf(DataClose));
        DayData[3][I]:=DataLow; //读取最低价数据放入最低价数组中
        BlockRead(DataFile, DataJinE, SizeOf(DataShuLiang));
        DayData[5][I]:=Not DataJinE;//读取成交金额数据放入成交金额数组中
        BlockRead(DataFile, DataShuLiang, SizeOf(DataJinE));
        DayData[6][I]:=DataShuLiang;//读取成交量数据放入成交量数组中
        BlockRead(DataFile, DataNoOne, SizeOf(DataNoOne));
        BlockRead(DataFile, DataNoTwo, SizeOf(DataNoTwo));
        BlockRead(DataFile, DataNoThree, SizeOf(DataNoThree));
        I:=I+1;
    End;
    //========================================
    CloseFile(DataFile);
    End//数据文件存在
    Else
      MessageDlg(‘数据文件不存在,请检查程序中文件路径!‘, mtInformation,[mbOk], 0);
  Except
    MessageDlg(‘文件读写错误,请检查程序中文件路径!‘, mtInformation,[mbOk], 0);
  End;
End;

    二、引用日线数据文件中的数据
    只要在需要的地方进行调用上述定义的数组即可。部分示例如下:   
Procedure  TFormKXianMain.DrawLineInIt(Sender: Tobject);
Var I,FlagExit,x1:Integer;
Begin
    If DayCount>0 Then
    Begin
       BeginDate:=0;
       EndDate:=DayCount-1;
       x1:=LeftX;
       FlagExit:=0;
       I:=DayCount-1;
       While (I>-1) And (FlagExit=0) Do
       Begin
           x1:=x1+DefaultWidth;
           If (x1+DefaultWidth)>(PaintWidth-RightX) Then
              FlagExit:=1
           Else
              I:=I-1;
       End;
       If (I=-1) Then
          LeftDate:=0
       Else
          LeftDate:=I;
       RightDate:=DayCount-1;
       CurrentDate:=DayCount-1;
       CurrentX:=x1-Round((DefaultWidth+1)/2);
    End;
End;

Procedure  TFormKXianMain.DrawLine(Sender: Tobject);
Var kpjg,spjg,zgjg,zdjg:Integer;
Var x1,x2,y1,y2,x3,y3,x4,y4:Integer;
Var I,Kheight:Integer;
Var TempString,OutStr:String;
Var TempLen,StrLen:Integer;
Begin
    If DayCount>0 Then
    Begin
       //清空屏幕
       Canvas.Brush.Color:=clblack;
       Canvas.Brush.style:=bsSolid;
       Canvas.FillRect(Rect(0,0,PaintWidth,PaintHeight));

       //左边竖直线
       Canvas.Pen.Color:=clRed;
       Canvas.MoveTo(LeftX-1,0);
       Canvas.LineTo(LeftX-1,PaintHeight);
       //上边水平线
       Canvas.MoveTo(0,TopY);
       Canvas.LineTo(PaintWidth,TopY);
       //右边竖直线
       Canvas.MoveTo(PaintWidth-RightX,TopY);
       Canvas.LineTo(PaintWidth-RightX,PaintHeight);
       //下边水平线
       Canvas.MoveTo(0,PaintHeight-BottomY);
       Canvas.LineTo(PaintWidth-RightX,PaintHeight-BottomY);

       PageTopY:=PaintHeight-BottomY;

       Canvas.Pen.Style:=psDot;
       Canvas.Pen.Color:=clMaroon;
       Canvas.MoveTo(LeftX-1,Round(PageTopY/3));
       Canvas.LineTo(PaintWidth-RightX,Round(PageTopY/3));
       Canvas.MoveTo(LeftX-1,Round(2*PageTopY/3));
       Canvas.LineTo(PaintWidth-RightX,Round(2*PageTopY/3));

       Canvas.Pen.style:=psSolid;

       //求价格的最大、最小值
       Maxjg:=DayData[2][LeftDate];
       MinJg:=DayData[3][LeftDate];
       I:=LeftDate;
       While (I<RightDate) Or (I=RightDate) Do
       Begin
           If DayData[2][I]>MaxJg Then
              MaxJg:=DayData[2][I];
           If DayData[3][I]<MinJg Then
              MinJg:=DayData[3][I];
           I:=I+1;
       End;

       //画右侧成交价格坐标数值
      OutStr:=‘.‘;
      Canvas.Font.Color := clRed;
      Canvas.Brush.Color:=clBlack;
      Canvas.Font.Size:=11;
      Canvas.Font.name:=‘宋体‘;
      Canvas.Brush.style:=bsSolid;
      Canvas.Pen.color:=clred;
      TempString:=IntToStr(Round(MinJg+(MaxJg-MinJg)*2/3));
      TempLen:=Length(TempString);
      Insert(OutStr,TempString,TempLen-2);
      StrLen:=Length(TempString);
      If TempString[StrLen]=‘0‘ Then
         TempString[StrLen]:=‘ ‘;
      Canvas.TextOut(PaintWidth-RightX+2,Round(PageTopY/3)-9,TempString);

      TempString:=IntToStr(Round(MinJg+(MaxJg-MinJg)/3));
      TempLen:=Length(TempString);
      Insert(OutStr,TempString,TempLen-2);
      StrLen:=Length(TempString);
      If TempString[StrLen]=‘0‘ Then
         TempString[StrLen]:=‘ ‘;
      Canvas.TextOut(PaintWidth-RightX+2,Round(PageTopY*2/3)-9,TempString);


       //画K线图
       Kheight:=PageTopY-TopY-10;
       HeightXiShu:=(MaxJg-MinJg)/Kheight;
       x1:=LeftX-DefaultWidth;
       I:=LeftDate;
       While (I<RightDate) Or  (I=RightDate) Do
       Begin
           kpjg:=DayData[1][I];
           spjg:=DayData[4][I];
           zgjg:=DayData[2][I];
           zdjg:=DayData[3][I];
           x1:=x1+DefaultWidth;
           x2:=x1+DefaultWidth-1;
           x3:=Round((x1+x2)/2);
           x4:=x3;
           If spjg<kpjg Then
           Begin
               Canvas.Pen.Color:=clAqua;
               Canvas.Brush.Color:=clAqua;
               Canvas.Brush.style:=bsSolid;
               y3:=PageTopY-Round((zgjg-MinJg)/HeightXiShu)-2;
               y1:=PageTopY-Round((kpjg-MinJg)/HeightXiShu)-2;
               y2:=PageTopY-Round((spjg-MinJg)/HeightXiShu)-2;
               y4:=PageTopY-Round((zdjg-MinJg)/HeightXiShu)-2;
               If (y1=y2) Then
                  y2:=y2+1;
               If (zgjg=kpjg) Then
                   y3:=y1;
               If (zdjg=spjg) Then
                   y4:=y2;
               If (zgjg<>kpjg) And (y1=y3) Then
                   y3:=y3-1;
               If (zdjg<>spjg) And (y2=y4) Then
                   y4:=y4+1;
               Canvas.MoveTo(x3,y3);
               Canvas.LineTo(x3,y1);
               Canvas.FillRect(Rect(x1,y1,x2,y2));
               Canvas.MoveTo(x4,y2);
               Canvas.LineTo(x4,y4);
           End//收盘价小于开盘价,阴线
           Else
           Begin
               Canvas.Pen.Color:=clred;
               x2:=x2-1;
               y3:=PageTopY-Round((zgjg-MinJg)/HeightXiShu)-2;
               y1:=PageTopY-Round((spjg-MinJg)/HeightXiShu)-2;
               y2:=PageTopY-Round((kpjg-MinJg)/HeightXiShu)-2;
               y4:=PageTopY-Round((zdjg-MinJg)/HeightXiShu)-2;
               If (y1=y2) And (spjg<>kpjg) Then
                  y2:=y2+1;
               If (zdjg=kpjg) Then
                   y4:=y2;
               If (zgjg=spjg) Then
                   y3:=y1;
               If (zdjg<>kpjg) And (y2=y4) Then
                   y4:=y4+1;
               If (zgjg<>spjg) And (y1=y3) Then
                   y3:=y3-1;
               Canvas.MoveTo(x3,y3);
               Canvas.LineTo(x3,y1);
               Canvas.MoveTo(x1,y1);
               Canvas.LineTo(x2,y1);
               Canvas.LineTo(x2,y2);
               Canvas.LineTo(x1,y2);
               Canvas.LineTo(x1,y1);
               Canvas.MoveTo(x4,y2);
               Canvas.LineTo(x4,y4);
           End;//收盘价大于开盘价,阳线
              I:=I+1;
       End;//画K线图


     Canvas.Font.Color := clRed;
     Canvas.Brush.Color:=clBlack;
     Canvas.Font.Size:=11;
     Canvas.Font.name:=‘宋体‘;
     //输出证券名称
     TempString:=ZqjcData[ZqRecordNo];
     Canvas.TextOut(1,1,TempString);
     //输出基本信息
     TempString:=‘代码 ‘;
     TempString:=TempString+ZqdmData[ZqRecordNo]+‘ ‘;
     TempString:=TempString+‘流通股本‘;
     TempString:=TempString+IntToStr(ZqltgbData[ZqRecordNo])+‘ ‘;
     Canvas.TextOut(LeftX+1,1,TempString);
     End;//数据集中数据个数大于0
End;

Procedure  TFormKXianMain.DrawNowLine(Sender: Tobject);
Var TempStr,OutStr:String;
Var TempLen,StrLen:Integer;
Begin
   If DayCount>0 Then
   Begin
   Canvas.Pen.Color:=clred;
   OutStr:=‘.‘;
   Canvas.Font.Color := clRed;
   Canvas.Brush.Color:=clBlack;
   Canvas.Font.Size:=11;
   Canvas.Font.name:=‘宋体‘;
   //输出日期
   TempStr:=‘-‘+IntToStr(DayData[0][CurrentDate])+‘-‘;
   Canvas.TextOut(2,PaintHeight-BottomY+1,TempStr);
   //输出开盘价
   TempStr:=IntToStr(DayData[1][CurrentDate]);
   TempLen:=Length(TempStr);
   Insert(OutStr,TempStr,TempLen-2);
   StrLen:=Length(TempStr);
   If TempStr[StrLen]=‘0‘ Then
      TempStr[StrLen]:=‘ ‘;
   Canvas.TextOut(1,TopY+1,‘开盘‘);
   Canvas.TextOut(41,TopY+1,TempStr);
   //输出最高价
   TempStr:=IntToStr(DayData[2][CurrentDate]);
   TempLen:=Length(TempStr);
   Insert(OutStr,TempStr,TempLen-2);
   StrLen:=Length(TempStr);
   If TempStr[StrLen]=‘0‘ Then
      TempStr[StrLen]:=‘ ‘;
   Canvas.TextOut(1,TopY+21,‘最高‘);
   Canvas.TextOut(41,TopY+21,TempStr);
   //输出最低价
   TempStr:=IntToStr(DayData[3][CurrentDate]);
   TempLen:=Length(TempStr);
   OutStr:=‘.‘;
   Insert(OutStr,TempStr,TempLen-2);
   StrLen:=Length(TempStr);
   If TempStr[StrLen]=‘0‘ Then
      TempStr[StrLen]:=‘ ‘;
   Canvas.TextOut(1,TopY+41,‘最低‘);
   Canvas.TextOut(41,TopY+41,TempStr);
   //输出收盘价
   TempStr:=IntToStr(DayData[4][CurrentDate]);
   TempLen:=Length(TempStr);
   Insert(OutStr,TempStr,TempLen-2);
   StrLen:=Length(TempStr);
   If TempStr[StrLen]=‘0‘ Then
      TempStr[StrLen]:=‘ ‘;
   Canvas.TextOut(1,TopY+61,‘收盘‘);
   Canvas.TextOut(41,TopY+61,TempStr);


   Canvas.MoveTo(LeftX-1,0);
   Canvas.LineTo(LeftX-1,PaintHeight);

   Canvas.Pen.Color:=clwhite;
   Canvas.Brush.style:=bsSolid;
   Canvas.MoveTo(CurrentX,TopY);
   Canvas.LineTo(CurrentX,PaintHeight-BottomY);

End;//DayCount>1
End;


Procedure  TFormKXianMain.MoveLineLeft(Sender: Tobject);
Var CurrentNow:Integer;
Begin
  If CurrentDate>BeginDate Then
  Begin
     CurrentNow:=CurrentX;
     If CurrentDate<>LeftDate Then
        CurrentNow:=CurrentX-DefaultWidth
     Else
        Begin
        LeftDate:=LeftDate-1;
        RightDate:=RightDate-1;
        End;
     CurrentDate:=CurrentDate-1;
     CurrentX:=CurrentNow;
     DrawLine(EditCode);
     DrawNowLine(EditCode);
  End;
End;


Procedure  TFormKXianMain.MoveLineRight(Sender: Tobject);
Var CurrentNow:Integer;
Begin
  If CurrentDate<EndDate Then
  Begin
     CurrentNow:=CurrentX;
     If CurrentDate<>RightDate Then
        CurrentNow:=CurrentX+DefaultWidth
     Else
        Begin
        LeftDate:=LeftDate+1;
        RightDate:=RightDate+1;
        End;
     CurrentDate:=CurrentDate+1;
     CurrentX:=CurrentNow;
     DrawLine(EditCode);
     DrawNowLine(EditCode);
  End;
End;

Procedure  TFormKXianMain.MoveLineHome(Sender: Tobject);
Begin
  If CurrentDate<>BeginDate Then
  Begin
     CurrentDate:=LeftDate;
     CurrentX:=LeftX+Round(DefaultWidth/2);
     DrawLine(EditCode);
     DrawNowLine(EditCode);
  End;
End;


Procedure  TFormKXianMain.MoveLineEnd(Sender: Tobject);
Var CurrentNow:Integer;
Begin
  If CurrentDate<>EndDate Then
  Begin
     CurrentNow:=CurrentX;
     While (CurrentDate<>RightDate) Do
        Begin
        CurrentNow:=CurrentNow+DefaultWidth;
        CurrentDate:=CurrentDate+1;
        End;
     CurrentX:=CurrentNow;
     DrawLine(EditCode);
     DrawNowLine(EditCode);
  End;
End;


procedure TFormKXianMain.EditCodeKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
If (key=VK_RETURN) And (EditCode.Text<>CurrentCode) Then
   Begin
      CurrentCode:=‘‘;
      If ZqdmFind(EditCode.Text)<>-1 Then
         CurrentCode:=ZqdmData[ZqRecordNo]
      Else If ZqkjmFind(EditCode.Text)<>-1 Then
         CurrentCode:=ZqdmData[ZqRecordNo]
      Else
         MessageDlg(‘证券代码不存在,请重新输入!‘, mtInformation,[mbOk], 0);
      EditCode.Text:=‘‘;
      If CurrentCode<>‘‘ Then
      Begin
      ReadData(EditCode);
      DrawLineInit(EditCode);
      DrawLine(EditCode);
      DrawNowLine(EditCode);
      End;
   End;
If (Key=VK_PRIOR) Then//Page Up key
   Begin
   If (ZqRecordNo=0) Then
      ZqRecordNo:=ZqRecordCount-1;
   ZqRecordNo:=ZqRecordNo-1;
   CurrentCode:=ZqdmData[ZqRecordNo];
   ReadData(EditCode);
   DrawLineInit(EditCode);
   DrawLine(EditCode);
   DrawNowLine(EditCode);
   End;
If (Key=VK_NEXT) Then//Page Down key
   Begin
   If (ZqRecordNo=(ZqRecordCount-1)) Then
      ZqRecordNo:=0;
   ZqRecordNo:=ZqRecordNo+1;
   CurrentCode:=ZqdmData[ZqRecordNo];
   ReadData(EditCode);
   DrawLineInit(EditCode);
   DrawLine(EditCode);
   DrawNowLine(EditCode);
   End;
If (Key=VK_DOWN) And (DefaultWidth>3) Then//Virtual key codes
   Begin
   DefaultWidth:=DefaultWidth-2;
   ReadData(EditCode);
   DrawLineInit(EditCode);
   DrawLine(EditCode);
   DrawNowLine(EditCode);
   End;
If (Key=VK_UP) And (DefaultWidth<50) Then
   Begin
   DefaultWidth:=DefaultWidth+2;
   ReadData(EditCode);
   DrawLineInit(EditCode);
   DrawLine(EditCode);
   DrawNowLine(EditCode);
   End;
If (Key=VK_HOME) Then
   MoveLineHome(EditCode);
If (Key=VK_END) Then
   MoveLineEnd(EditCode);
If (Key=VK_LEFT) Then
   MoveLineLeft(EditCode);
If (Key=VK_RIGHT) Then
   MoveLineRight(EditCode);
end;

procedure TFormKXianMain.PaintBoxMainPaint(Sender: TObject);
Begin
      If CurrentCode<>‘‘ Then
      Begin
         ReadData(EditCode);
         DrawLineInit(EditCode);
         DrawLine(EditCode);
         DrawNowLine(EditCode);
      End;
end;


procedure TFormKXianMain.NTuiChuClick(Sender: TObject);
begin
   FormKXianMain.Close;
end;


procedure TFormKXianMain.NShuJuYuanSheZhiClick(Sender: TObject);
begin
   FormShuJuYuanSheZhi.ShowModal;
end;



procedure TFormKXianMain.PaintBoxMainMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
Var DayNumber:Integer;
begin
     MouseX:=X;
     MouseY:=Y;
     If CurrentCode<>‘‘ Then
     Begin
     If (X>CurrentX) Then
        Begin
        DayNumber:=Trunc((X-CurrentX)/DefaultWidth+0.5);
        If DayNumber>(RightDate-CurrentDate) Then
           DayNumber:=RightDate-CurrentDate;
        CurrentDate:=CurrentDate+DayNumber;
        CurrentX:=CurrentX+DayNumber*DefaultWidth;
        DrawLine(EditCode);
        DrawNowLine(EditCode);
        End
     Else If (X<CurrentX) Then
        Begin
        DayNumber:=Trunc((CurrentX-X)/DefaultWidth+0.5);
        If DayNumber>(CurrentDate-LeftDate) Then
           DayNumber:=CurrentDate-LeftDate;
        CurrentDate:=CurrentDate-DayNumber;
        CurrentX:=CurrentX-DayNumber*DefaultWidth;        
        DrawLine(EditCode);
        DrawNowLine(EditCode);
        End;
     End;

end;

 

 

http://www.winu.cn/thread-51497-1-1.html

posted on 2007-09-25 09:05  Ruxuan  阅读(5420)  评论(3编辑  收藏  举报