Files: Database File Format
|
Ensign uses a database design to store tick data received from the live feeds from the data vendors, and from charts that are refreshed. Individual ticks and their tick volumes are stored in Tick database files, and 1-minute bars are stored in the Minute database files. The format of these files is as follows.
Tick File Format
TDataTick = class(TObject) bSource: array[0..47] of byte; {1 for each 30-min period} r: array of TBarTick; end;
TBarTick = record d: dword; {Seconds from 1970, 136 yr range, Eastern Time Zone} c: single; {price} v: dword; {volume} end;
Each tick database file contains the ticks for one day for one symbol. The file begins with a header that is 48 bytes in length, where each byte represents data for a 30-minute period. If you are writing a tick database file, set each byte to a value of 150.
Each tick follows in time sequence using a 12 byte record made up of three fields: date, price, volume. Date is a double word that is the number of seconds from January 1st, 1970, Eastern Time zone. A data time variable can be recreated using code like this:
timestamp = EncodeDate(1970,1,1) + r.d / 86400; {r.d is the tick record date field}
The tick price is a 4 byte single precision floating point value. The tick volume is a 4 byte double word integer.
Minute File Format
TDataMin = class(TObject) bSource: array[0..47] of byte; {1 for each 30-min period} r: array of TBarMin; end;
TBarMin = record d: dword; {Seconds from 1970, 136 yr range, Eastern Time Zone} o: single; {open} h: single; {high} l: single; {low} c: single; {close} vU: dword; {up volume} vD: dword; {down volume} tU: word; {up tick count} tD: word; {down tick count} end;
Each minute database file has up to 1440 bar records for one day for each symbol. The file begins with a header that is 48 bytes in length, and each byte is an indicatation that there is data in the 30-minute period. If you are writing a minute database file, set each byte to a value of 150.
The minute records follow in time sequence. There may be minute periods when data does not exist because the symbol did not trade during that minute time period.
The date field is in seconds from January 1st, 1970, same as described for the tick database date field. The next 4 fields are the prices of open, high, low and close for the 1-minute period. When the database files are being built from a live data feed, tick by tick, the tick volume is accumulated in the vU field as up volume on an up tick or on an equal tick if the last price change was an up tick. The tick volume is accumulated in the vD filed as down volume on a down tick or on an equal tick if the last price change was a down tick. A counter for the up ticks is summed in tU, and a counter for the down ticks is summed in tD.
If you are building 1-minute database files, you may not have the detail regarding how the total volume might be split between up volume and down volume, or know about tick counts. In such a case, put the total volume in the vU field and have the vD field be a zero. Set the tick count fields to a zero when they are not known. The volume fields are 4-byte double word integers. The tick counts are 2-byte word integers.
Example Delphi Code
function dReadDatabase(var dT: TDataTick; var dM: TDataMin; b: boolean; s: string): longint; var i,k: longint; begin Result:=0; if b then begin dT:=TDataTick.Create; if pos('.tick',s)=0 then s:=s+'.tick'; end else begin dM:=TDataMin.Create; SetLength(dM.r,1441); if pos('.min',s)=0 then s:=s+'.min'; end; if FileExists(s) then with TFileStream.Create(s,fmOpenRead) do try k:=Size; if k<48 then i:=0 else if b then begin i:=(k-48) div SizeOf(TBarTick); SetLength(dT.r,i); {number of records} Read(dT.bSource[0],48); Read(dT.r[0],k-48); end else begin i:=(k-48) div SizeOf(TBarMin); if i>1441 then SetLength(dM.r,i); Read(dM.bSource[0],48); Read(dM.r[0],k-48); end; finally Free; Result:=i; end end;
procedure dWriteDatabase(dT: TDataTick; dM: TDataMin; b: boolean; i: longint; s: string); begin ForceDirectories(ExtractFilePath(s)); if b then begin if pos('.tick',s)=0 then s:=s+'.tick'; end else if pos('.min',s)=0 then s:=s+'.min'; with TFileStream.Create(s,fmCreate) do try if b then begin Write(dT.bSource[0],48); Write(dT.r[0],i*SizeOf(TBarTick)); dT.Free; end else begin Write(dM.bSource[0],48); Write(dM.r[0],i*SizeOf(TBarMin)); dM.Free; end; finally Free; end; end;
read more » Database Design
Last modified 12/22/08 2:41 PM
|