DataServer

Bugfix in DataSeries
This commit is contained in:
Michael Schimmel
2025-06-06 23:24:08 +02:00
parent a6c0c3d6b3
commit 031b99acc8
11 changed files with 369 additions and 86 deletions
+149 -3
View File
@@ -7,7 +7,9 @@ uses
System.Generics.Collections,
Myc.Lazy,
Myc.Trade.DataPoint,
Myc.Trade.DataSeries;
Myc.Trade.DataSeries,
Myc.Signals, // Added for TLatch
Myc.Futures; // Added for TFuture
type
IDataProvider = interface
@@ -15,7 +17,7 @@ type
procedure Fetch;
end;
IDataServer<T> = interface
IDataServer<T> = interface(IDataProvider)
['{A6E246A2-E84E-49AB-A63E-333E561E488C}']
function GetData: TMutable<TArray<T>>;
function GetIsLiveData: TMutable<Boolean>;
@@ -41,10 +43,154 @@ type
function CreateDataServer: IDataServer<T>; virtual; abstract;
end;
TFileStreamServerNode<T> = class(TDataServerNode<T>)
TTABFileServer = class(TDataServer<ITickData>)
private
FFilename: String;
// The maximum number of data points to be produced per Fetch call.
FMaxFetch: Integer;
FHasNewData: TEvent;
FNeedNewChunk: Boolean;
FIsLiveData: TMutable<Boolean>.IWriteable;
// Internal state
FCurrentFileName: string;
FCurrentData: TFuture<TArray<TAskBid.TTick>>;
FNextFileName: string;
FNextData: TFuture<TArray<TAskBid.TTick>>;
FData: TMutable<TArray<ITickData>>;
FCurrPosInFile: Int64;
FCurrChunk: TArray<ITickData>;
FLoadGate: TLatch;
FCurrentIdx: Int64;
FLastTimeStamp: TDateTime;
function ConvertTicks(var Idx: Int64; const Ticks: TArray<TAskBid.TTick>): TArray<ITickData>;
function UpdateChunk: TArray<ITickData>;
protected
procedure Fetch; override;
function GetData: TMutable<TArray<ITickData>>; override;
function GetIsLiveData: TMutable<Boolean>; override;
public
constructor Create(const AFilename: String; AMaxFetch: Integer);
end;
implementation
uses
System.IOUtils;
{ TTABFileServer<T> }
constructor TTABFileServer.Create(const AFilename: String; AMaxFetch: Integer);
begin
inherited Create;
FFilename := AFilename;
FMaxFetch := AMaxFetch;
FNextData := TFuture<TArray<TAskBid.TTick>>.Null;
FNeedNewChunk := true;
FIsLiveData := TMutable<Boolean>.CreateWriteable(false);
FHasNewData := TEvent.CreateEvent;
FData := TMutable<TArray<ITickData>>.Construct(FHasNewData.Signal, function: TArray<ITickData> begin Result := UpdateChunk; end);
end;
function TTABFileServer.ConvertTicks(var Idx: Int64; const Ticks: TArray<TAskBid.TTick>): TArray<ITickData>;
begin
SetLength(Result, Length(Ticks));
for var i := 0 to High(Ticks) do
begin
Result[i] := TDataPoint<ITick>.Create(Idx, Ticks[i].OADateTime, 1, TTick.Create(Ticks[i].Data.Ask, Ticks[i].Data.Bid));
inc(Idx);
end;
end;
procedure TTABFileServer.Fetch;
begin
// Check if the source filename has changed.
if (FFilename <> FCurrentFileName) and (FFilename <> '') then
begin
// Filename has changed, initialize by loading the new file.
FCurrentFileName := FFilename;
FCurrentData := TAskBid.LoadDataFile(TLatch.Enqueue(FLoadGate), FCurrentFileName);
FCurrPosInFile := 0;
FCurrentIdx := 0;
FIsLiveData.SetValue(false);
FLastTimeStamp := 0;
FFilename := '';
FNextFileName := FindNextDataFile(FCurrentFileName);
if FNextFileName <> '' then
FNextData := TAskBid.LoadDataFile(TLatch.Enqueue(FLoadGate), FNextFileName);
end;
FHasNewData.Notify;
FNeedNewChunk := true;
FCurrChunk := nil;
end;
function TTABFileServer.GetData: TMutable<TArray<ITickData>>;
begin
Result := FData;
end;
function TTABFileServer.GetIsLiveData: TMutable<Boolean>;
begin
Result := FIsLiveData;
end;
function TTABFileServer.UpdateChunk: TArray<ITickData>;
begin
if not FNeedNewChunk then
exit(FCurrChunk);
FNeedNewChunk := false;
if FCurrentData.Done.IsSet then
begin
SetLength(FCurrChunk, FMaxFetch);
var n := 0;
while n < FMaxFetch do
begin
if FCurrPosInFile >= Length(FCurrentData.Value) then
begin
// Next File!
FCurrentData := FNextData;
FCurrentFileName := FNextFileName;
FCurrPosInFile := 0;
FNextFileName := '';
FNextData := TFuture<TArray<TAskBid.TTick>>.Null;
if FCurrentFileName <> '' then
begin
FNextFileName := FindNextDataFile(FCurrentFileName);
if FNextFileName <> '' then
FNextData := TAskBid.LoadDataFile(TLatch.Enqueue(FLoadGate), FNextFileName);
end
else
begin
// We're done with this series
FIsLiveData.SetValue(true);
end;
SetLength(FCurrChunk, n);
break;
end;
var currData := FCurrentData.Value[FCurrPosInFile];
if FLastTimeStamp < currData.OADateTime then
begin
FLastTimeStamp := currData.OADateTime;
FCurrChunk[n] :=
TDataPoint<ITick>.Create(FCurrentIdx, FLastTimeStamp, 1, TTick.Create(currData.Data.Ask, currData.Data.Bid));
inc(FCurrentIdx);
inc(n);
end;
inc(FCurrPosInFile);
end;
end;
Result := FCurrChunk;
end;
end.