DataServer
Bugfix in DataSeries
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user