Test-Apps für Gemini Api und Blockly
This commit is contained in:
@@ -5,7 +5,7 @@ unit Myc.Trade.DataStream;
|
||||
Provides a data server for loading time-series data and streaming it.
|
||||
|
||||
This unit contains the core components for handling historical data:
|
||||
- TDataRecord: A generic record for a single time-stamped data entry.
|
||||
- TAuraFileDataRecord: A generic record for a single time-stamped data entry.
|
||||
- IDataServer/TAuraDataServer: A server component responsible for loading and caching
|
||||
series of data files from disk. Each server instance manages its own cache,
|
||||
but all instances share a central load gate.
|
||||
@@ -29,11 +29,6 @@ uses
|
||||
Myc.Trade.DataPoint;
|
||||
|
||||
type
|
||||
// A generic record for a single time-stamped data entry.
|
||||
TDataRecord<T: record> = packed record
|
||||
TimeStamp: TDateTime;
|
||||
Data: T;
|
||||
end;
|
||||
|
||||
// Represents a generic data stream capable of providing sequential data chunks.
|
||||
IDataStream<T> = interface
|
||||
@@ -69,10 +64,16 @@ type
|
||||
procedure ClearCache;
|
||||
end;
|
||||
|
||||
// A generic record for a single time-stamped data entry.
|
||||
TAuraFileDataRecord<T: record> = packed record
|
||||
TimeStamp: TDateTime;
|
||||
Data: T;
|
||||
end;
|
||||
|
||||
IAuraDataServer<T: record> = interface(IDataServer<T>)
|
||||
['{481E27DE-DC58-49AF-B8A8-B6316980C423}']
|
||||
function LoadDataFile(const FileName: string): TFuture<TArray<TDataRecord<T>>>;
|
||||
function LoadDataSeries(const FileName: string): TFuture<TArray<TDataRecord<T>>>;
|
||||
function LoadDataFile(const FileName: string): TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
function LoadDataSeries(const FileName: string): TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
function EnumerateAssetFiles: TArray<String>;
|
||||
end;
|
||||
|
||||
@@ -87,7 +88,7 @@ type
|
||||
Name: String;
|
||||
Age: TDateTime;
|
||||
LastUsed: TDateTime;
|
||||
Data: TFuture<TArray<TDataRecord<T>>>;
|
||||
Data: TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
end;
|
||||
private
|
||||
// The cache is per-instance.
|
||||
@@ -101,8 +102,8 @@ type
|
||||
FLoadGate: TLatch;
|
||||
|
||||
protected
|
||||
class function ReadCompressedData(const InputStream: TStream): TArray<TDataRecord<T>>; static;
|
||||
class function ReadUncompressedData(const InputStream: TStream): TArray<TDataRecord<T>>; static;
|
||||
class function ReadCompressedData(const InputStream: TStream): TArray<TAuraFileDataRecord<T>>; static;
|
||||
class function ReadUncompressedData(const InputStream: TStream): TArray<TAuraFileDataRecord<T>>; static;
|
||||
|
||||
public
|
||||
constructor Create(const APath: String);
|
||||
@@ -123,8 +124,8 @@ type
|
||||
procedure ClearCache;
|
||||
function EnumerateAssetFiles: TArray<String>;
|
||||
|
||||
function LoadDataFile(const FileName: string): TFuture<TArray<TDataRecord<T>>>;
|
||||
function LoadDataSeries(const FileName: string): TFuture<TArray<TDataRecord<T>>>;
|
||||
function LoadDataFile(const FileName: string): TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
function LoadDataSeries(const FileName: string): TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
|
||||
property Path: String read GetPath;
|
||||
end;
|
||||
@@ -135,9 +136,9 @@ type
|
||||
FDataServer: TAuraDataServer<T>;
|
||||
FIsLiveData: TMutable<Boolean>.IWriteable;
|
||||
FCurrentFileName: string;
|
||||
FCurrentData: TFuture<TArray<TDataRecord<T>>>;
|
||||
FCurrentData: TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
FNextFileName: string;
|
||||
FNextData: TFuture<TArray<TDataRecord<T>>>;
|
||||
FNextData: TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
FCurrPosInFile: Int64;
|
||||
FCurrentIdx: Int64;
|
||||
FLastTimeStamp: TDateTime;
|
||||
@@ -314,12 +315,12 @@ begin
|
||||
Result := FPath;
|
||||
end;
|
||||
|
||||
function TAuraDataServer<T>.LoadDataFile(const FileName: string): TFuture<TArray<TDataRecord<T>>>;
|
||||
function TAuraDataServer<T>.LoadDataFile(const FileName: string): TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
var
|
||||
parsedPath, parsedSymbol: string;
|
||||
parsedYear, parsedMonth: Integer;
|
||||
begin
|
||||
Result := TFuture<TArray<TDataRecord<T>>>.Null;
|
||||
Result := TFuture<TArray<TAuraFileDataRecord<T>>>.Null;
|
||||
|
||||
if not TryParseFileName(FileName, parsedPath, parsedSymbol, parsedYear, parsedMonth) then
|
||||
exit;
|
||||
@@ -368,8 +369,8 @@ begin
|
||||
.Construct(
|
||||
TLatch.Enqueue(FLoadGate), // Use shared class var FLoadGate
|
||||
function: TBytes begin Result := TFile.ReadAllBytes(capFileName); end)
|
||||
.Chain<TArray<TDataRecord<T>>>(
|
||||
function(bytes: TBytes): TArray<TDataRecord<T>>
|
||||
.Chain<TArray<TAuraFileDataRecord<T>>>(
|
||||
function(bytes: TBytes): TArray<TAuraFileDataRecord<T>>
|
||||
begin
|
||||
var zipMemoryStream := TBytesStream.Create(bytes);
|
||||
try
|
||||
@@ -383,9 +384,9 @@ begin
|
||||
else if TFile.Exists(FileName) then
|
||||
begin
|
||||
Result :=
|
||||
TFuture<TArray<TDataRecord<T>>>.Construct(
|
||||
TFuture<TArray<TAuraFileDataRecord<T>>>.Construct(
|
||||
TLatch.Enqueue(FLoadGate), // Use shared class var FLoadGate
|
||||
function: TArray<TDataRecord<T>>
|
||||
function: TArray<TAuraFileDataRecord<T>>
|
||||
begin
|
||||
if TFile.Exists(capFileName) then
|
||||
begin
|
||||
@@ -418,11 +419,11 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TAuraDataServer<T>.LoadDataSeries(const FileName: string): TFuture<TArray<TDataRecord<T>>>;
|
||||
function TAuraDataServer<T>.LoadDataSeries(const FileName: string): TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
var
|
||||
loadedState: TState;
|
||||
loadedFiles: TArray<TFuture<TArray<TDataRecord<T>>>>;
|
||||
liveData: TFuture<TArray<TDataRecord<T>>>;
|
||||
loadedFiles: TArray<TFuture<TArray<TAuraFileDataRecord<T>>>>;
|
||||
liveData: TFuture<TArray<TAuraFileDataRecord<T>>>;
|
||||
tabFiles: TList<string>;
|
||||
currentFile: string;
|
||||
liveFilePath: string;
|
||||
@@ -452,7 +453,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
var loadedFileList := TList<TFuture<TArray<TDataRecord<T>>>>.Create;
|
||||
var loadedFileList := TList<TFuture<TArray<TAuraFileDataRecord<T>>>>.Create;
|
||||
var loadStates := TList<TState>.Create;
|
||||
try
|
||||
for currentFile in tabFiles do
|
||||
@@ -462,7 +463,7 @@ begin
|
||||
loadStates.Add(data.Done);
|
||||
end;
|
||||
|
||||
liveData := TFuture<TArray<TDataRecord<T>>>.Null;
|
||||
liveData := TFuture<TArray<TAuraFileDataRecord<T>>>.Null;
|
||||
if liveFilePath <> '' then
|
||||
begin
|
||||
liveData := LoadDataFile(liveFilePath);
|
||||
@@ -481,11 +482,11 @@ begin
|
||||
end;
|
||||
|
||||
Result :=
|
||||
TFuture<TArray<TDataRecord<T>>>.Construct(
|
||||
TFuture<TArray<TAuraFileDataRecord<T>>>.Construct(
|
||||
loadedState,
|
||||
function: TArray<TDataRecord<T>>
|
||||
function: TArray<TAuraFileDataRecord<T>>
|
||||
begin
|
||||
var tickList := TList<TDataRecord<T>>.Create;
|
||||
var tickList := TList<TAuraFileDataRecord<T>>.Create;
|
||||
try
|
||||
var overallLastTabTickTime: TDateTime := 0;
|
||||
var cnt := 0;
|
||||
@@ -508,7 +509,7 @@ begin
|
||||
);
|
||||
end;
|
||||
|
||||
class function TAuraDataServer<T>.ReadCompressedData(const InputStream: TStream): TArray<TDataRecord<T>>;
|
||||
class function TAuraDataServer<T>.ReadCompressedData(const InputStream: TStream): TArray<TAuraFileDataRecord<T>>;
|
||||
var
|
||||
decompressionStream: TStream;
|
||||
localHeader: TZipHeader;
|
||||
@@ -547,7 +548,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TAuraDataServer<T>.ReadUncompressedData(const InputStream: TStream): TArray<TDataRecord<T>>;
|
||||
class function TAuraDataServer<T>.ReadUncompressedData(const InputStream: TStream): TArray<TAuraFileDataRecord<T>>;
|
||||
var
|
||||
fileSize: Int64;
|
||||
recordCount, bytesRead: Integer;
|
||||
@@ -555,10 +556,10 @@ begin
|
||||
SetLength(Result, 0);
|
||||
InputStream.Position := 0;
|
||||
fileSize := InputStream.Size;
|
||||
if (fileSize = 0) or ((fileSize mod SizeOf(TDataRecord<T>)) <> 0) then
|
||||
if (fileSize = 0) or ((fileSize mod SizeOf(TAuraFileDataRecord<T>)) <> 0) then
|
||||
exit;
|
||||
|
||||
recordCount := fileSize div SizeOf(TDataRecord<T>);
|
||||
recordCount := fileSize div SizeOf(TAuraFileDataRecord<T>);
|
||||
if recordCount > 0 then
|
||||
begin
|
||||
SetLength(Result, recordCount);
|
||||
@@ -596,8 +597,8 @@ end;
|
||||
|
||||
function TAuraFileStream<T>.GetChunk(var Data: array of TDataPoint<T>): Integer;
|
||||
var
|
||||
item: TDataRecord<T>;
|
||||
currData: TArray<TDataRecord<T>>;
|
||||
item: TAuraFileDataRecord<T>;
|
||||
currData: TArray<TAuraFileDataRecord<T>>;
|
||||
begin
|
||||
Result := 0;
|
||||
if not FCurrentData.Done.IsSet then
|
||||
|
||||
Reference in New Issue
Block a user