156 lines
4.5 KiB
ObjectPascal
156 lines
4.5 KiB
ObjectPascal
unit Myc.Trade.DataServer;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Generics.Collections,
|
|
Myc.Lazy,
|
|
Myc.Trade.DataPoint,
|
|
Myc.Trade.DataSeries,
|
|
Myc.Signals, // Added for TLatch
|
|
Myc.Futures; // Added for TFuture
|
|
|
|
type
|
|
IDataServer<T> = interface
|
|
['{A6E246A2-E84E-49AB-A63E-333E561E488C}']
|
|
function GetIsLiveData: TMutable<Boolean>;
|
|
function GetChunk(var Data: array of T): Integer;
|
|
property IsLiveData: TMutable<Boolean> read GetIsLiveData;
|
|
end;
|
|
|
|
TDataServer<T> = class(TInterfacedObject, IDataServer<T>)
|
|
protected
|
|
function GetIsLiveData: TMutable<Boolean>; virtual; abstract;
|
|
function GetChunk(var Data: array of T): Integer; virtual; abstract;
|
|
end;
|
|
|
|
IDataServerNode<T> = interface
|
|
['{DA3531F1-158E-4A63-8E5A-34089C537B1B}']
|
|
function CreateDataServer: IDataServer<T>;
|
|
end;
|
|
|
|
TDataServerNode<T> = class(TInterfacedObject, IDataServerNode<T>)
|
|
public
|
|
// Factory method to create the actual data server instance.
|
|
function CreateDataServer: IDataServer<T>; virtual; abstract;
|
|
end;
|
|
|
|
TTABFileServer = class(TDataServer<TDataPoint<TAskBidItem>>)
|
|
|
|
private
|
|
FFilename: String;
|
|
FIsLiveData: TMutable<Boolean>.IWriteable;
|
|
|
|
// Internal state
|
|
FCurrentFileName: string;
|
|
FCurrentData: TFuture<TArray<TAskBid.TTick>>;
|
|
FNextFileName: string;
|
|
FNextData: TFuture<TArray<TAskBid.TTick>>;
|
|
FCurrPosInFile: Int64;
|
|
FCurrentIdx: Int64;
|
|
FLastTimeStamp: TDateTime;
|
|
|
|
protected
|
|
function GetChunk(var Data: array of TDataPoint<TAskBidItem>): Integer; override;
|
|
function GetIsLiveData: TMutable<Boolean>; override;
|
|
public
|
|
constructor Create(const AFilename: String);
|
|
procedure AfterConstruction; override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.IOUtils;
|
|
|
|
{ TTABFileServer<T> }
|
|
|
|
constructor TTABFileServer.Create(const AFilename: String);
|
|
begin
|
|
inherited Create;
|
|
FFilename := AFilename;
|
|
|
|
FNextData := TFuture<TArray<TAskBid.TTick>>.Null;
|
|
FIsLiveData := TMutable<Boolean>.CreateWriteable(false);
|
|
end;
|
|
|
|
procedure TTABFileServer.AfterConstruction;
|
|
begin
|
|
inherited;
|
|
|
|
FCurrentFileName := FFilename;
|
|
FCurrentData := TAskBid.LoadDataFile(FCurrentFileName);
|
|
FCurrPosInFile := 0;
|
|
FCurrentIdx := 0;
|
|
FIsLiveData.SetValue(false);
|
|
FLastTimeStamp := 0;
|
|
FFilename := '';
|
|
|
|
FNextFileName := FindNextDataFile(FCurrentFileName);
|
|
if FNextFileName <> '' then
|
|
FNextData := TAskBid.LoadDataFile(FNextFileName);
|
|
exit;
|
|
end;
|
|
|
|
function TTABFileServer.GetChunk(var Data: array of TDataPoint<TAskBidItem>): Integer;
|
|
begin
|
|
Result := 0;
|
|
|
|
if FCurrentData.Done.IsSet then
|
|
begin
|
|
var maxLen := Length(Data);
|
|
|
|
var currData := FCurrentData.Value;
|
|
while Result < MaxLen do
|
|
begin
|
|
if FCurrPosInFile >= Length(currData) 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(FNextFileName);
|
|
|
|
if FCurrentData.Done.IsSet then
|
|
begin
|
|
currData := FCurrentData.Value;
|
|
continue;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
// We're done with this series
|
|
FIsLiveData.SetValue(true);
|
|
end;
|
|
break;
|
|
end;
|
|
|
|
var item := currData[FCurrPosInFile];
|
|
if FLastTimeStamp < item.TimeStamp then
|
|
begin
|
|
FLastTimeStamp := item.TimeStamp;
|
|
Data[Result].Create(FCurrentIdx, FLastTimeStamp, item.Data);
|
|
inc(Result);
|
|
inc(FCurrentIdx);
|
|
end;
|
|
inc(FCurrPosInFile);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TTABFileServer.GetIsLiveData: TMutable<Boolean>;
|
|
begin
|
|
Result := FIsLiveData;
|
|
end;
|
|
|
|
end.
|