diff --git a/AuraTrader/AuraTrader.dproj b/AuraTrader/AuraTrader.dproj
index db13ae8..08ef546 100644
--- a/AuraTrader/AuraTrader.dproj
+++ b/AuraTrader/AuraTrader.dproj
@@ -4,7 +4,7 @@
20.3
FMX
True
- Release
+ Debug
Win64
AuraTrader
3
diff --git a/Src/AST/Myc.Ast.Compiler.TypeChecker.pas b/Src/AST/Myc.Ast.Compiler.TypeChecker.pas
index a2b260e..aee166d 100644
--- a/Src/AST/Myc.Ast.Compiler.TypeChecker.pas
+++ b/Src/AST/Myc.Ast.Compiler.TypeChecker.pas
@@ -775,7 +775,7 @@ begin
if allScalar then
begin
- def := TScalarRecordRegistry.Intern(scalarDefFields);
+ def := TScalarRecord.TRegistry.Intern(scalarDefFields);
staticType := TTypes.CreateRecord(def);
Result := TAst.RecordLiteral(Node.Identity, fieldList, def, nil, staticType);
end
diff --git a/Src/Data/Myc.Data.Scalar.JSON.pas b/Src/Data/Myc.Data.Scalar.JSON.pas
index b26d1a8..e544364 100644
--- a/Src/Data/Myc.Data.Scalar.JSON.pas
+++ b/Src/Data/Myc.Data.Scalar.JSON.pas
@@ -63,7 +63,7 @@ begin
fields[i] := TScalarRecordField.Create(fieldKey, TScalar.TKind(GetEnumValue(TypeInfo(TScalar.TKind), kindStr)));
end;
- Result := TScalarRecordRegistry.Intern(fields);
+ Result := TScalarRecord.TRegistry.Intern(fields);
finally
jsonValue.Free;
end;
diff --git a/Src/Myc.Trade.DataFeed.pas b/Src/Myc.Trade.DataFeed.pas
index 87df3a6..92880f2 100644
--- a/Src/Myc.Trade.DataFeed.pas
+++ b/Src/Myc.Trade.DataFeed.pas
@@ -53,8 +53,8 @@ type
function GetIsValid: Boolean;
public
constructor Create(const APath, ASymbol, AExtension: String; AYear, AMonth: Integer; const ABasename: String);
- function GetBaseFileName: string;
function GetFullFileName: string;
+ property BaseFileName: string read FBasename;
property IsValid: Boolean read GetIsValid;
property Extension: String read FExtension;
property Path: String read FPath;
@@ -84,10 +84,14 @@ type
// Loading Logic
function DoLoad(const FileName: string; const Gate: TLatch): TFuture>;
function LoadDataFile(const DataFile: TDataFile): TFuture>;
- function GetNextFile(const Curr: TDataFile): TDataFile;
// Processing Logic
- function ProcessFile(FileInfo: TDataFile; const DataFile: TFuture>; const Terminated: TState): TState;
+ function ProcessFile(
+ const Files: TArray;
+ Index: Integer;
+ const DataFile: TFuture>;
+ const Terminated: TState
+ ): TState;
function ProcessChunks(const Batches: TArray; Terminated: TState): TState;
@@ -97,7 +101,6 @@ type
// Helpers
function ParseFileName(const FileName: string): TDataFile;
- function FindFirstFile(const Symbol: string): TFuture;
procedure UpdateSymbols;
private
@@ -213,14 +216,9 @@ begin
FBasename := ABasename;
end;
-function TScalarRecordFeed.TDataFile.GetBaseFileName: string;
-begin
- Result := FBasename;
-end;
-
function TScalarRecordFeed.TDataFile.GetFullFileName: string;
begin
- Result := TPath.Combine(FPath, GetBaseFileName + FExtension);
+ Result := TPath.Combine(FPath, FBasename + FExtension);
end;
function TScalarRecordFeed.TDataFile.GetIsValid: Boolean;
@@ -350,51 +348,6 @@ begin
);
end;
-function TScalarRecordFeed.FindFirstFile(const Symbol: string): TFuture;
-begin
- var symName := Symbol;
- Result :=
- FSymbols.Chain(
- function(const Symbols: TDictionary>): TDataFile
- var
- symbolFiles: TArray;
- begin
- if Symbols.TryGetValue(symName, symbolFiles) and (Length(symbolFiles) > 0) then
- Result := symbolFiles[0]
- else
- Result := Default(TDataFile);
- end
- );
-end;
-
-function TScalarRecordFeed.GetNextFile(const Curr: TDataFile): TDataFile;
-var
- allSymbolFiles: TArray;
- foundIndex: Integer;
-begin
- Result := Default(TDataFile);
- if not Curr.IsValid or not FSymbols.Done.IsSet then
- exit;
-
- if not FSymbols.Value.TryGetValue(Curr.Symbol, allSymbolFiles) then
- exit;
-
- foundIndex := -1;
- for var i := 0 to High(allSymbolFiles) do
- begin
- if allSymbolFiles[i].GetBaseFileName() = Curr.GetBaseFileName() then
- begin
- foundIndex := i;
- break;
- end;
- end;
-
- if (foundIndex <> -1) and (foundIndex < High(allSymbolFiles)) then
- begin
- Result := allSymbolFiles[foundIndex + 1];
- end;
-end;
-
function TScalarRecordFeed.ParseFileName(const FileName: string): TDataFile;
var
path, fileNameNoPath, baseName, ext, symbol: string;
@@ -608,32 +561,64 @@ end;
function TScalarRecordFeed.ProcessData(const Symbol: String; const Terminated: TState): TState;
begin
var cTerminated := Terminated;
+ var cSymbol := Symbol;
+ // We fetch the list once, then iterate by index.
Result :=
- FindFirstFile(Symbol)
- .Chain(
- function(const FirstInfo: TDataFile): TState
+ FSymbols.Chain(
+ function(const AllSymbols: TDictionary>): TState
+ var
+ files: TArray;
+ begin
+ if AllSymbols.TryGetValue(cSymbol, files) and (Length(files) > 0) then
begin
- Result := ProcessFile(FirstInfo, LoadDataFile(FirstInfo), cTerminated);
- end);
+ // Start with Index 0
+ Result := ProcessFile(files, 0, LoadDataFile(files[0]), cTerminated);
+ end
+ else
+ begin
+ Result := TState.Null;
+ end;
+ end
+ );
end;
-function TScalarRecordFeed.ProcessFile(FileInfo: TDataFile; const DataFile: TFuture>; const Terminated: TState): TState;
+function TScalarRecordFeed.ProcessFile(
+ const Files: TArray;
+ Index: Integer;
+ const DataFile: TFuture>;
+ const Terminated: TState
+): TState;
begin
- if not FileInfo.IsValid or Terminated.IsSet then
+ // Check bounds and termination
+ if (Index < 0) or (Index > High(Files)) or Terminated.IsSet then
exit(DataFile.Done);
- var nextInfo := GetNextFile(FileInfo);
- var nextFuture := LoadDataFile(nextInfo);
+ var currentInfo := Files[Index];
+ if not currentInfo.IsValid then
+ exit(DataFile.Done);
+
+ // Prefetch logic: Prepare the next file immediately (if available)
+ var nextIndex := Index + 1;
+ var nextFuture: TFuture>;
+
+ if nextIndex <= High(Files) then
+ nextFuture := LoadDataFile(Files[nextIndex])
+ else
+ nextFuture := TFuture>.Construct(TArray(nil)); // End of stream
var cTerminated := Terminated;
+
+ // Process current data, then recurse to next index
Result :=
DataFile.Chain(
function(const Batches: TArray): TState
begin
var done := ProcessChunks(Batches, Terminated);
- Result := TaskManager.RunTask(done, function: TState begin Result := ProcessFile(nextInfo, nextFuture, cTerminated); end);
+ // Recurse with Index + 1
+ Result :=
+ TaskManager.RunTask(done, function: TState begin Result := ProcessFile(Files, nextIndex, nextFuture, cTerminated); end);
end
);
end;