From ef4583c2aeafd290f668a4eacbf1fbf498715d9b Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Wed, 21 Jan 2026 14:09:26 +0100 Subject: [PATCH] DataStream updated --- ASTPlayground/ASTPlayground.delphilsp.json | 2 +- AuraTrader/AuraTrader.dpr | 3 +- AuraTrader/AuraTrader.dproj | 9 +- AuraTrader/MainForm.fmx | 7 - AuraTrader/MainForm.pas | 100 --- Src/Data/Myc.Data.Decimal.pas | 17 +- Src/Data/Myc.Data.Pipeline.pas | 6 +- Src/Myc.Trade.DataFeed.pas | 697 --------------------- Src/Myc.Trade.DataStream.pas | 637 ++++++------------- 9 files changed, 198 insertions(+), 1280 deletions(-) delete mode 100644 Src/Myc.Trade.DataFeed.pas diff --git a/ASTPlayground/ASTPlayground.delphilsp.json b/ASTPlayground/ASTPlayground.delphilsp.json index feff693..771498a 100644 --- a/ASTPlayground/ASTPlayground.delphilsp.json +++ b/ASTPlayground/ASTPlayground.delphilsp.json @@ -1 +1 @@ -{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Analysis.Purity", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Analysis.Purity.pas" }, { "name": "Myc.Ast.Identities", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Identities.pas" }, { "name": "Myc.Fmx.AstEditor.Visualizer", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Layout", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Layout.pas" }, { "name": "Myc.Fmx.AstEditor.Node", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Node.pas" }, { "name": "Myc.Ast.Refactoring.Remove", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Refactoring.Remove.pas" }, { "name": "Myc.Fmx.AstEditor.Render", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Render.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Lists", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Lists.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Primitives", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Primitives.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Control", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Control.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Data", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Data.pas" }, { "name": "Myc.Ast.RTL.TypeRegistry", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.TypeRegistry.pas" }, { "name": "Myc.Trade.Broker", "file": "file:///T%3A/Myc/Src/Myc.Trade.Broker.pas" }, { "name": "Myc.Data.Stream.Pipes", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Stream.Pipes.pas" }, { "name": "Myc.Data.Stream", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Stream.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Pipes", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Pipes.pas" }, { "name": "Demo.Finance", "file": "file:///T%3A/Myc/Test/Demo.Finance.pas" }, { "name": "Myc.Ast.Script.Print", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.Print.pas" }, { "name": "Myc.Ast.Json.Schema.Old", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Json.Schema.Old.pas" }, { "name": "Myc.Ast.Attributes", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Ast.Attributes.pas" }, { "name": "Myc.Ast.Json.Schema", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Json.Schema.pas" }, { "name": "Myc.Ast.RTL.Math", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Math.pas" }, { "name": "Myc.Ast.RTL.DateTime", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.DateTime.pas" }, { "name": "Myc.Ast.RTL.Series", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Series.pas" } ] , "includeDCUsInUsesCompletion": true, "enableKeyWordCompletion": false, "browsingPaths": [ "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/OCX/Servers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/VCL","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/RTL/SYS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win/winrt","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/ToolsAPI","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/IBX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Internet","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/PROPERTY%20EDITORS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/XML","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Core","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/System","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Protocols","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/fmx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/components","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/engine","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/graph","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ado","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/cloud","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dbx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dsnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/vclctrls","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/connectors","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/proxygen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DataExplorer","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/src","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/tests","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Experts","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/abstraction","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/implementation","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indyimpl","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Property%20Editors/Indy10","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap/wsdlimporter","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Visualizers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XMLReporting","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XPGen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/rest","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/firedac","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/tethering","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnitX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ems","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/net","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/FlatBox2D","file:///C%3A/Users/Public/Documents/Embarcadero/Studio/37.0/Dcp/%25PLATFORM%25","file:///%25TP%25/runtime/vcl","file:///S%3A/sc_famos_src/svn_vcl/cpxedits","file:///S%3A/sc_famos_src/svn_vcl/dzChart","file:///S%3A/sc_famos_src/svn_vcl/eaeditor","file:///S%3A/sc_famos_src/svn_vcl/FamosEvents","file:///S%3A/sc_famos_src/svn_vcl/HTML_Viewer/source","file:///S%3A/sc_famos_src/svn_vcl/Myc_ChartEdit","file:///S%3A/sc_famos_src/svn_vcl/Myc_HemiDrag","file:///S%3A/sc_famos_src/svn_vcl/Myc_SplitControl","file:///S%3A/sc_famos_src/svn_vcl/NiceChart","file:///S%3A/sc_famos_src/svn_vcl/plotter","file:///S%3A/sc_famos_src/svn_vcl/SimpleIPC","file:///S%3A/sc_famos_src/svn_vcl/SynEdit-master/Source","file:///S%3A/sc_famos_src/svn_vcl/ValEdits","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib/win32","file:///S%3A/sc_famos_src/svn_vcl/Virtual-TreeView/Source","file:///S%3A/sc_famos_src/svn_common/caHelpSys","file:///S%3A/sc_famos_src/svn_common/Misc","file:///S%3A/sc_famos_src/svn_common/Myc_VecMath","file:///S%3A/sc_famos_src/svn_common/PascalScript/source","file:///S%3A/sc_famos_src/svn_common/TreeBase","file:///S%3A/sc_famos_src/svn_common/TreeBase/Medien","file:///S%3A/3rdParty/spring4d/Source","file:///S%3A/3rdParty/spring4d/Source/Base","file:///S%3A/3rdParty/spring4d/Source/Base/Collections","file:///S%3A/3rdParty/spring4d/Source/Base/Logging","file:///S%3A/3rdParty/spring4d/Source/Base/Patches","file:///S%3A/3rdParty/spring4d/Source/Core/Container","file:///S%3A/3rdParty/spring4d/Source/Core/Interception","file:///S%3A/3rdParty/spring4d/Source/Core/Logging","file:///S%3A/3rdParty/spring4d/Source/Core/Mocking","file:///S%3A/3rdParty/spring4d/Source/Core/Services","file:///S%3A/3rdParty/spring4d/Source/Extensions/Cryptography","file:///S%3A/3rdParty/spring4d/Source/Extensions/Utils","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCommon%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressGDI%2B%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLibrary/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/XP%20Theme%20Manager/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLayout%20Control/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressPageControl/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressEditors%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDocking%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressBars/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressOfficeCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressMemData/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDataController/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressNavBar/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressSkins%20Library/Sources","file:///T%3A/Myc/Src","file:///T%3A/Myc/Src/Data","file:///T%3A/Myc/Src/AST" ] , "CommonAppData": "file:///C%3A/Users/Brummel/AppData/Roaming/Embarcadero/BDS/37.0/" , "Templates": "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/ObjRepos/" } } \ No newline at end of file +{ "settings": { "project": "file:///T%3A/Myc/ASTPlayground/ASTPlayground.dpr", "dllname": "dcc64370.dll", "dccOptions": "-$O- -$W+ --inline:off -$R+ -$Q+ --no-config -Q -TX.exe -AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults;WinTypes=Winapi.Windows;WinProcs=Winapi.Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE -DDEBUG;;FRAMEWORK_FMX -E.\\Win64\\Debug -I\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -LEC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Bpl\\Win64 -LNC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NU.\\Win64\\Debug -NSWinapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;System;Xml;Data;Datasnap;Web;Soap; -OT:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -R\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -U\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\\DE\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\debug\";\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\\DE\";T:\\Myc\\Src\\Data;T:\\Myc\\Src\\AST;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\lib\\Win64\\release\";C:\\Users\\Brummel\\Documents\\Embarcadero\\Studio\\37.0\\Imports\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\Imports\";C:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\include\";S:\\sc_famos_src\\svn_vcl\\Virtual-TreeView\\Source;S:\\sc_famos_src\\svn_vcl\\cpxedits;S:\\sc_famos_src\\svn_vcl\\dzChart;S:\\sc_famos_src\\svn_vcl\\eaeditor;S:\\sc_famos_src\\svn_vcl\\FamosEvents;S:\\sc_famos_src\\svn_vcl\\HTML_Viewer\\source;S:\\sc_famos_src\\svn_vcl\\Myc_ChartEdit;S:\\sc_famos_src\\svn_vcl\\Myc_HemiDrag;S:\\sc_famos_src\\svn_vcl\\Myc_SplitControl;S:\\sc_famos_src\\svn_vcl\\plotter;S:\\sc_famos_src\\svn_vcl\\SimpleIPC;S:\\sc_famos_src\\svn_vcl\\SynEdit-master\\Source;S:\\sc_famos_src\\svn_vcl\\ValEdits;S:\\sc_famos_src\\svn_vcl\\ZipMaster;S:\\sc_famos_src\\svn_common\\Myc_VecMath;\"C:\\Program Files (x86)\\DevExpress VCL\\Library\\RS28\\Win64\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressCommon Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressGDI+ Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLibrary\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\XP Theme Manager\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressLayout Control\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressPageControl\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressEditors Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDocking Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressBars\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressOfficeCore Library\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressMemData\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressDataController\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressNavBar\\Sources\";\"C:\\Program Files (x86)\\DevExpress VCL\\ExpressSkins Library\\Sources\";S:\\3rdParty\\FastMM5;C:\\Users\\Brummel\\AppData\\Local\\Programs\\TestInsight\\Source;T:\\Myc\\Src;\"c:\\program files (x86)\\embarcadero\\studio\\37.0\\source\\DUnitX\" -V -VN -VR -NBC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\Dcp\\Win64 -NHC:\\Users\\Public\\Documents\\Embarcadero\\Studio\\37.0\\hpp\\Win64 -NO.\\Win64\\Debug -LU" , "projectFiles":[ { "name": "MainForm", "file": "file:///T%3A/Myc/ASTPlayground/MainForm.pas" }, { "name": "Myc.Ast.Nodes", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Nodes.pas" }, { "name": "Myc.Ast.Scope", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Scope.pas" }, { "name": "Myc.Data.Value", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Data.Value.pas" }, { "name": "Myc.Ast.Visitor", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Visitor.pas" }, { "name": "Myc.Ast.RTL", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.pas" }, { "name": "Myc.Ast.Dumper", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Dumper.pas" }, { "name": "Myc.Ast.RTL.Core", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Core.pas" }, { "name": "Myc.Utils", "file": "file:///T%3A/Myc/Src/Myc.Utils.pas" }, { "name": "Myc.Ast.Script", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.pas" }, { "name": "Myc.Ast.Types", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Types.pas" }, { "name": "Myc.Data.Keyword", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Keyword.pas" }, { "name": "Myc.Ast.Compiler.TCO", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TCO.pas" }, { "name": "Myc.Ast.Compiler.Binder", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Binder.pas" }, { "name": "Myc.Ast.Compiler.Lowering", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Lowering.pas" }, { "name": "Myc.Ast.Compiler.TypeChecker", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.TypeChecker.pas" }, { "name": "Myc.Ast.Compiler.Macros", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Macros.pas" }, { "name": "Myc.Ast.Compiler.Specializer", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Compiler.Specializer.pas" }, { "name": "Myc.Ast.Environment", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Environment.pas" }, { "name": "Myc.Ast.Debugger", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Debugger.pas" }, { "name": "Myc.Ast.Analysis.Purity", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Analysis.Purity.pas" }, { "name": "Myc.Ast.Identities", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Identities.pas" }, { "name": "Myc.Fmx.AstEditor.Visualizer", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Visualizer.pas" }, { "name": "Myc.Fmx.AstEditor.Workspace", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Workspace.pas" }, { "name": "Myc.Fmx.AstEditor.Layout", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Layout.pas" }, { "name": "Myc.Fmx.AstEditor.Node", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Node.pas" }, { "name": "Myc.Ast.Refactoring.Remove", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Refactoring.Remove.pas" }, { "name": "Myc.Fmx.AstEditor.Render", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Render.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Lists", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Lists.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Primitives", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Primitives.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Control", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Control.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Data", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Data.pas" }, { "name": "Myc.Ast.RTL.TypeRegistry", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.TypeRegistry.pas" }, { "name": "Myc.Trade.Broker", "file": "file:///T%3A/Myc/Src/Myc.Trade.Broker.pas" }, { "name": "Myc.Data.Stream.Pipes", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Stream.Pipes.pas" }, { "name": "Myc.Data.Stream", "file": "file:///T%3A/Myc/Src/Data/Myc.Data.Stream.pas" }, { "name": "Myc.Fmx.AstEditor.Handlers.Pipes", "file": "file:///T%3A/Myc/Src/AST/Myc.Fmx.AstEditor.Handlers.Pipes.pas" }, { "name": "Demo.Finance", "file": "file:///T%3A/Myc/Test/Demo.Finance.pas" }, { "name": "Myc.Ast.Script.Print", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Script.Print.pas" }, { "name": "Myc.Ast.Json.Schema.Old", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Json.Schema.Old.pas" }, { "name": "Myc.Ast.Attributes", "file": "file:///T%3A/Myc/ASTPlayground/Myc.Ast.Attributes.pas" }, { "name": "Myc.Ast.Json.Schema", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.Json.Schema.pas" }, { "name": "Myc.Ast.RTL.Math", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Math.pas" }, { "name": "Myc.Ast.RTL.DateTime", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.DateTime.pas" }, { "name": "Myc.Ast.RTL.Series", "file": "file:///T%3A/Myc/Src/AST/Myc.Ast.RTL.Series.pas" } ] , "includeDCUsInUsesCompletion": true, "enableKeyWordCompletion": true, "browsingPaths": [ "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/OCX/Servers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/VCL","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/RTL/SYS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/win/winrt","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/ToolsAPI","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/IBX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Internet","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/PROPERTY%20EDITORS","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/SOURCE/XML","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Core","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/System","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Indy10/Protocols","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/fmx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/components","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/engine","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/databinding/graph","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ado","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/cloud","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dbx","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/dsnap","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/vclctrls","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/connectors","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/datasnap/proxygen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DataExplorer","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/Common/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/Common","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/DUnitWizard/Source/DelphiExperts/DUnitProject/dunit","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/src","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/tests","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Experts","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/abstraction","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indy/implementation","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/indyimpl","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Property%20Editors/Indy10","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/soap/wsdlimporter","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/Visualizers","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XMLReporting","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnit/Contrib/XPGen","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/rest","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/firedac","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/tethering","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/DUnitX","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/data/ems","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/rtl/net","file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/source/FlatBox2D","file:///C%3A/Users/Public/Documents/Embarcadero/Studio/37.0/Dcp/%25PLATFORM%25","file:///%25TP%25/runtime/vcl","file:///S%3A/sc_famos_src/svn_vcl/cpxedits","file:///S%3A/sc_famos_src/svn_vcl/dzChart","file:///S%3A/sc_famos_src/svn_vcl/eaeditor","file:///S%3A/sc_famos_src/svn_vcl/FamosEvents","file:///S%3A/sc_famos_src/svn_vcl/HTML_Viewer/source","file:///S%3A/sc_famos_src/svn_vcl/Myc_ChartEdit","file:///S%3A/sc_famos_src/svn_vcl/Myc_HemiDrag","file:///S%3A/sc_famos_src/svn_vcl/Myc_SplitControl","file:///S%3A/sc_famos_src/svn_vcl/NiceChart","file:///S%3A/sc_famos_src/svn_vcl/plotter","file:///S%3A/sc_famos_src/svn_vcl/SimpleIPC","file:///S%3A/sc_famos_src/svn_vcl/SynEdit-master/Source","file:///S%3A/sc_famos_src/svn_vcl/ValEdits","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib","file:///S%3A/sc_famos_src/svn_vcl/ZipMaster/zlib/win32","file:///S%3A/sc_famos_src/svn_vcl/Virtual-TreeView/Source","file:///S%3A/sc_famos_src/svn_common/caHelpSys","file:///S%3A/sc_famos_src/svn_common/Misc","file:///S%3A/sc_famos_src/svn_common/Myc_VecMath","file:///S%3A/sc_famos_src/svn_common/PascalScript/source","file:///S%3A/sc_famos_src/svn_common/TreeBase","file:///S%3A/sc_famos_src/svn_common/TreeBase/Medien","file:///S%3A/3rdParty/spring4d/Source","file:///S%3A/3rdParty/spring4d/Source/Base","file:///S%3A/3rdParty/spring4d/Source/Base/Collections","file:///S%3A/3rdParty/spring4d/Source/Base/Logging","file:///S%3A/3rdParty/spring4d/Source/Base/Patches","file:///S%3A/3rdParty/spring4d/Source/Core/Container","file:///S%3A/3rdParty/spring4d/Source/Core/Interception","file:///S%3A/3rdParty/spring4d/Source/Core/Logging","file:///S%3A/3rdParty/spring4d/Source/Core/Mocking","file:///S%3A/3rdParty/spring4d/Source/Core/Services","file:///S%3A/3rdParty/spring4d/Source/Extensions/Cryptography","file:///S%3A/3rdParty/spring4d/Source/Extensions/Utils","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressCommon%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressGDI%2B%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLibrary/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/XP%20Theme%20Manager/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressLayout%20Control/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressPageControl/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressEditors%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDocking%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressBars/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressOfficeCore%20Library/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressMemData/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressDataController/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressNavBar/Sources","file:///C%3A/Program%20Files%20%28x86%29/DevExpress%20VCL/ExpressSkins%20Library/Sources","file:///T%3A/Myc/Src","file:///T%3A/Myc/Src/Data","file:///T%3A/Myc/Src/AST" ] , "CommonAppData": "file:///C%3A/Users/Brummel/AppData/Roaming/Embarcadero/BDS/37.0/" , "Templates": "file:///c%3A/program%20files%20%28x86%29/embarcadero/studio/37.0/ObjRepos/" } } \ No newline at end of file diff --git a/AuraTrader/AuraTrader.dpr b/AuraTrader/AuraTrader.dpr index 479440b..0c6aa76 100644 --- a/AuraTrader/AuraTrader.dpr +++ b/AuraTrader/AuraTrader.dpr @@ -9,8 +9,7 @@ uses DynamicFMXControl in 'DynamicFMXControl.pas', Myc.Trade.Pipeline.Impl in '..\Src\Myc.Trade.Pipeline.Impl.pas', Myc.Trade.Indicators_v2 in '..\Src\Myc.Trade.Indicators_v2.pas', - Strategy2 in 'Strategy2.pas', - Myc.Trade.DataFeed in '..\Src\Myc.Trade.DataFeed.pas'; + Strategy2 in 'Strategy2.pas'; {$R *.res} diff --git a/AuraTrader/AuraTrader.dproj b/AuraTrader/AuraTrader.dproj index 08ef546..96c3b37 100644 --- a/AuraTrader/AuraTrader.dproj +++ b/AuraTrader/AuraTrader.dproj @@ -4,7 +4,7 @@ 20.3 FMX True - Debug + Release Win64 AuraTrader 3 @@ -140,7 +140,6 @@ - Base @@ -190,12 +189,6 @@ true - - - AuraTrader.rsm - true - - AuraTrader.exe diff --git a/AuraTrader/MainForm.fmx b/AuraTrader/MainForm.fmx index b6df951..2b5b9f6 100644 --- a/AuraTrader/MainForm.fmx +++ b/AuraTrader/MainForm.fmx @@ -204,13 +204,6 @@ object Form1: TForm1 Text = 'Button2' OnClick = Button2Click end - object Button3: TButton - Position.X = 64.000000000000000000 - Position.Y = 152.000000000000000000 - TabOrder = 2 - Text = 'Button3' - OnClick = Button3Click - end end end end diff --git a/AuraTrader/MainForm.pas b/AuraTrader/MainForm.pas index 613b64e..d766d67 100644 --- a/AuraTrader/MainForm.pas +++ b/AuraTrader/MainForm.pas @@ -56,7 +56,6 @@ uses Myc.Trade.Indicators, Myc.Trade.Indicators.Common, Myc.Core.FileCache, - Myc.Trade.DataFeed, StrategyTest, TestMethodCallFromRecordParams; @@ -89,7 +88,6 @@ type Strat2Button: TSpeedButton; Button1: TButton; Button2: TButton; - Button3: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure StopButtonClick(Sender: TObject); @@ -97,7 +95,6 @@ type procedure AddWorkspaceActionExecute(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); - procedure Button3Click(Sender: TObject); procedure LogMemoChange(Sender: TObject); procedure Strat2ButtonClick(Sender: TObject); procedure TestActionExecute(Sender: TObject); @@ -115,8 +112,6 @@ type FProcessDone: TState; FApplication: IAuraApplication; FModulesItem: TTreeViewItem; - FFileCache: IDataFileCache>; - FFeed: IScalarBatchLoader; function SelectedSymbol: String; procedure ExecuteStrategy(const Symbol: String; Timeframe: TTimeframe; const Consumer: IConsumer>); @@ -197,8 +192,6 @@ procedure TForm1.FormCreate(Sender: TObject); begin FApplication := TMycAuraApplication.Create; - FFileCache := TDataFileCache>.Create; - FModulesItem := TTreeViewItem.Create(Self); FModulesItem.Text := 'Modules'; @@ -350,99 +343,6 @@ begin end; -procedure TForm1.Button3Click(Sender: TObject); -begin - var symbol := SelectedSymbol; - if symbol = '' then - exit; - - var layout := CurrLayout; - if layout = nil then - exit; - - // 1. Setup Chart - var chart := TMycChart.Create(Self); - AlignControl(chart); - chart.Height := layout.ChildrenRect.Width * 9 / 16; - chart.Lookback.Value := 500000; - - // 2. Define Schema (Keywords & Layout) - var kTime := TKeywordRegistry.Intern('Time'); - var kClose := TKeywordRegistry.Intern('Close'); - - var def := - TScalarRecord.TRegistry.Intern( - [ - TPair.Create(kTime, TScalar.TKind.DateTime), - TPair.Create(kClose, TScalar.TKind.Float) - ] - ); - - // 3. Build Pipeline - - var iTime := def.IndexOf(kTime); - var iClose := def.IndexOf(kClose); - - var terminated := TFlag.CreateObserver(FTerminate.Signal).State; - var path := '\\COFFEE\TickData\Pepperstone'; // Or FServer.Path if compatible - - FFeed := - TScalarBatchLoader.Create( - FFileCache, - path, - '.m1', - true, - SizeOf(TM1FileItem), - procedure(const Src: Pointer; Dst: TScalar.PValue) - var - Item: ^TM1FileItem; - begin - Item := Src; - - // Field 0: Time (DateTime is stored as Double/OADate in TScalar) - Dst.AsDouble := Item.OADateTime; - - // Move to next field in destination (TScalar values are contiguous) - Inc(Dst); - - // Field 1: Close (Float) - // Convert Int64 price to Double using Digits: Price / 10^Digits - if Item.Digits > 0 then - Dst.AsDouble := Item.Close / Power(10, Item.Digits) - else - Dst.AsDouble := Item.Close; - end - ); - - // Converter: Transforms raw IRecordSeries (Columns) into TArray - - var unpacker := TScalarBatchLoader.CreateTicker(def); - - var ticker := - unpacker.Producer.Chain>( - function(const Tick: IScalarRecord): TDataPoint - begin - Result.Time := Tick[iTime].Value.Value.AsDouble; - Result.Data := Tick[iClose].Value.Value.AsDouble; - end - ); - - FFeed.BatchProducer.Chain(unpacker.Consumer); - - // Link Chart to Ticker - chart - .SetXAxisSeries(TTimeframe.M, ticker.Chain(function(const p: TDataPoint): TDateTime begin Result := p.Time end)); - - var panel := chart.AddPanel; - panel.AddDoubleSeries( - ticker.Chain(function(const p: TDataPoint): Double begin Result := p.Data end), - TAlphaColors.Orange - ); - - // Connect pipeline: Server -> Converter - FProcessDone := FFeed.ProcessData(symbol, terminated); -end; - function TForm1.CreateStrategy2(Timeframe: TTimeframe): IConsumer>; type TSignal = record diff --git a/Src/Data/Myc.Data.Decimal.pas b/Src/Data/Myc.Data.Decimal.pas index a355506..422b5f3 100644 --- a/Src/Data/Myc.Data.Decimal.pas +++ b/Src/Data/Myc.Data.Decimal.pas @@ -86,17 +86,12 @@ begin var newValue := AValue.GetValue; var scaleDiff := ANewScale - oldScale; - if scaleDiff > 0 then + if (scaleDiff > 0) then begin - // Increasing scale: multiply by 10^scaleDiff, checking for overflow at each step. - for var i := 1 to scaleDiff do - begin - if newValue > (MAX_VALUE_61BIT div 10) then - raise EOverflow.Create('Decimal scale up resulted in an overflow.'); - if newValue < (MIN_VALUE_61BIT div 10) then - raise EOverflow.Create('Decimal scale up resulted in an overflow.'); - newValue := newValue * 10; - end; + var multiplier := PowersOf10[scaleDiff]; + if (newValue > (MAX_VALUE_61BIT div multiplier)) or (newValue < (MIN_VALUE_61BIT div multiplier)) then + raise EOverflow.Create('Decimal scale up resulted in an overflow.'); + newValue := newValue * multiplier; end else begin @@ -380,7 +375,7 @@ begin if val < 0 then exit(-1); if val > 0 then - exit(-1); + exit(1); exit(0); end; diff --git a/Src/Data/Myc.Data.Pipeline.pas b/Src/Data/Myc.Data.Pipeline.pas index dc60ea6..5e19b65 100644 --- a/Src/Data/Myc.Data.Pipeline.pas +++ b/Src/Data/Myc.Data.Pipeline.pas @@ -7,16 +7,18 @@ uses Myc.Mutable, Myc.Data.Series; +{$M+} + type TTag = Pointer; // A generic interface for components that consume data of type T. - IConsumer = interface(IInvokable) + IConsumer = interface function Consume(const Value: T): TState; end; // A producer generates data and distributes it to linked consumers. - IProducer = interface(IInvokable) + IProducer = interface function Link(const Consumer: IConsumer): TTag; procedure Unlink(Tag: TTag); end; diff --git a/Src/Myc.Trade.DataFeed.pas b/Src/Myc.Trade.DataFeed.pas deleted file mode 100644 index e5cd915..0000000 --- a/Src/Myc.Trade.DataFeed.pas +++ /dev/null @@ -1,697 +0,0 @@ -unit Myc.Trade.DataFeed; - -interface - -uses - System.SysUtils, - System.Classes, - System.Generics.Collections, - System.Generics.Defaults, - System.IOUtils, - System.TimeSpan, - Myc.Futures, - Myc.Signals, - Myc.Mutable, - Myc.Data.Scalar, - Myc.Data.Keyword, - Myc.Data.Pipeline, - Myc.Data.Pipeline.Impl, - Myc.Core.FileCache; - -type - // Callback to convert raw bytes from a file into a TScalar.TValue sequence - TImportConverter = reference to procedure(const Src: Pointer; Dst: TScalar.PValue); - - // Represents a raw block of data read from disk - TScalarBatch = record - Data: TArray; - RecCount: Integer; - end; - - IBroker = interface - function GetEquity: Double; - procedure Buy(Count: Integer); - procedure Sell(Count: Integer); - property Equity: Double read GetEquity; - end; - - IScalarBatchLoader = interface - {$region 'private'} - function GetBatchProducer: TProducer; - {$endregion} - - function EnumerateSymbols: TFuture>; - - // Streaming processing: Reads data from disk and broadcasts it via BatchProducer - function ProcessData(const Symbol: String; const Terminated: TState): TState; - - // Provides raw TScalarBatch events - property BatchProducer: TProducer read GetBatchProducer; - end; - - TScalarBatchLoader = class(TInterfacedObject, IScalarBatchLoader) - public - type - TDataFile = record - private - FExtension: String; - FPath: String; - FSymbol: String; - FYear: Integer; - FMonth: Integer; - FBasename: String; - function GetIsValid: Boolean; - public - constructor Create(const APath, ASymbol, AExtension: String; AYear, AMonth: Integer; const ABasename: String); - function GetFullFileName: string; - property BaseFileName: string read FBasename; - property IsValid: Boolean read GetIsValid; - property Extension: String read FExtension; - property Path: String read FPath; - property Symbol: String read FSymbol; - property Year: Integer read FYear; - property Month: Integer read FMonth; - end; - - var - FPath: String; - FLookback: Int64; - FFileExtension: String; - FIsCompressed: Boolean; - - FCachedFiles: IDataFileCache>; - FSymbols: TFuture>>; - - // Internal producer for raw batches - FBatchProducer: TMycContainedProducer; - - class var - FLoadGate: TLatch; - - function GetPath: String; - - // Loading Logic - function DoLoad(const FileName: string; const Gate: TLatch): TFuture>; - function LoadDataFile(const DataFile: TDataFile): TFuture>; - - // Processing Logic - function ProcessFile( - const Files: TArray; - Index: Integer; - const DataFile: TFuture>; - const Terminated: TState - ): TState; - - function ProcessChunks(const Batches: TArray; Terminated: TState): TState; - - // Binary I/O - function ReadCompressedData(const InputStream: TStream): TArray; - function ReadUncompressedData(const InputStream: TStream): TArray; - - // Helpers - function ParseFileName(const FileName: string): TDataFile; - procedure UpdateSymbols; - - private - FRecordSize: Integer; - FConverter: TImportConverter; - - function GetBatchProducer: TProducer; - - public - constructor Create( - const ACachedFiles: IDataFileCache>; - const APath, AExtension: String; - IsCompressed: Boolean; - // RecordSize defines both the input bytes per record AND the output TValues per record - ARecordSize: Integer; - const AConverter: TImportConverter - ); - destructor Destroy; override; - procedure AfterConstruction; override; - - function EnumerateSymbols: TFuture>; - - // Streaming processing: Reads data from disk and broadcasts it via BatchTicker - function ProcessData(const Symbol: String; const Terminated: TState): TState; - - class function CreateTicker(const Def: IScalarRecordDefinition): TConverter; static; - - property Path: String read GetPath; - property FileExtension: String read FFileExtension; - property IsCompressed: Boolean read FIsCompressed; - property Lookback: Int64 read FLookback write FLookback; - property BatchProducer: TProducer read GetBatchProducer; - end; - -implementation - -uses - System.Zip, - System.Math, - System.StrUtils, - Myc.TaskManager; - -const - BatchSize = 1024; - -type - // Private implementation of the view logic (Cursor Pattern). - // This object is reused to avoid allocations per tick. - TScalarRecordView = class(TInterfacedObject, IScalarRecord) - private - FDef: IScalarRecordDefinition; - FData: TScalar.PValue; - - // IKeywordMapping implementation - function IndexOf(const Key: IKeyword): Integer; - function GetCount: Integer; - function GetItems(Idx: Integer): TPair; - function GetFields(const Key: IKeyword): TScalar; - function GetDef: IScalarRecordDefinition; - public - constructor Create(const ADef: IScalarRecordDefinition); - procedure SetData(const AData: TScalar.PValue); inline; - end; - -{ TScalarRecordView } - -constructor TScalarRecordView.Create(const ADef: IScalarRecordDefinition); -begin - inherited Create; - FDef := ADef; -end; - -procedure TScalarRecordView.SetData(const AData: TScalar.PValue); -begin - FData := AData; -end; - -function TScalarRecordView.GetCount: Integer; -begin - Result := FDef.Count; -end; - -function TScalarRecordView.GetDef: IScalarRecordDefinition; -begin - Result := FDef; -end; - -function TScalarRecordView.GetFields(const Key: IKeyword): TScalar; -var - idx: Integer; -begin - idx := FDef.IndexOf(Key); - if idx < 0 then - exit(Default(TScalar)); - - // Return the raw TValue at the offset - Result.Kind := FDef[idx].Value; - Result.Value := TScalar.PValue(NativeUInt(FData) + NativeUInt(idx * SizeOf(TScalar.TValue)))^; -end; - -function TScalarRecordView.GetItems(Idx: Integer): TPair; -begin - Result.Key := FDef[Idx].Key; - Result.Value.Kind := FDef[idx].Value; - Result.Value.Value := TScalar.PValue(NativeUInt(FData) + NativeUInt(Idx * SizeOf(TScalar.TValue)))^; -end; - -function TScalarRecordView.IndexOf(const Key: IKeyword): Integer; -begin - Result := FDef.IndexOf(Key); -end; - -{ TScalarBatchLoader.TDataFile } - -constructor TScalarBatchLoader.TDataFile.Create(const APath, ASymbol, AExtension: String; AYear, AMonth: Integer; const ABasename: String); -begin - FPath := APath; - FSymbol := ASymbol; - FExtension := AExtension; - FYear := AYear; - FMonth := AMonth; - FBasename := ABasename; -end; - -function TScalarBatchLoader.TDataFile.GetFullFileName: string; -begin - Result := TPath.Combine(FPath, FBasename + FExtension); -end; - -function TScalarBatchLoader.TDataFile.GetIsValid: Boolean; -begin - Result := (FSymbol <> '') and (FYear > 0); -end; - -{ TScalarBatchLoader } - -constructor TScalarBatchLoader.Create( - const ACachedFiles: IDataFileCache>; - const APath, AExtension: String; - IsCompressed: Boolean; - ARecordSize: Integer; - const AConverter: TImportConverter -); -begin - inherited Create; - FPath := APath; - FCachedFiles := ACachedFiles; - FFileExtension := AExtension; - FIsCompressed := IsCompressed; - FLookback := -1; - - // RecordSize is used for both Input Bytes Stride AND Output TValues Count - FRecordSize := ARecordSize; - FConverter := AConverter; - - Assert(FRecordSize > 0); - Assert(Assigned(FConverter)); - - FBatchProducer := TMycContainedProducer.Create(Self); - FCachedFiles := TDataFileCache>.Create; -end; - -destructor TScalarBatchLoader.Destroy; -begin - FCachedFiles.Clear; - FBatchProducer.Free; - inherited Destroy; -end; - -procedure TScalarBatchLoader.AfterConstruction; -begin - inherited; - UpdateSymbols; -end; - -class function TScalarBatchLoader.CreateTicker(const Def: IScalarRecordDefinition): TConverter; -var - viewObj: TScalarRecordView; - view: IScalarRecord; -begin - Result := - TConverter.CreateAggregation( - function(const Value: TScalarBatch; const Broadcast: TBroadcastFunc): TState - begin - if (Length(Value.Data) > 0) and (Value.RecCount > 0) then - begin - var Stride := Length(Value.Data) div Value.RecCount; - var pCursor: TScalar.PValue := @Value.Data[0]; - - for var i := 0 to Value.RecCount - 1 do - begin - if view = nil then - begin - // Initialize reused View object (Cursor Pattern) - // This object implements IScalarRecord and is updated for each tick. - viewObj := TScalarRecordView.Create(Def); - view := viewObj as IScalarRecord; - end; - - var rc := viewObj._AddRef; - try - // Broadcast tick - viewObj.SetData(pCursor); - Broadcast(view); - finally - // If client picked it up, we release it - if viewObj._Release >= rc then - view := nil; - end; - - Inc(pCursor, Stride); - end; - end; - Result := TState.Null; - end - ); -end; - -function TScalarBatchLoader.GetPath: String; -begin - Result := FPath; -end; - -function TScalarBatchLoader.GetBatchProducer: TProducer; -begin - Result := FBatchProducer; -end; - -procedure TScalarBatchLoader.UpdateSymbols; -begin - FSymbols := - TFuture>>.Construct( - FSymbols.Done, - function: TDictionary> - var - fileNames: TArray; - tempSymbolMap: TDictionary>; - dataFile: TDataFile; - symbolList: TList; - begin - Result := TDictionary>.Create; - tempSymbolMap := TDictionary>.Create; - try - if not TDirectory.Exists(FPath) then - exit; - - fileNames := TDirectory.GetFiles(FPath); - for var currentFile in fileNames do - begin - dataFile := ParseFileName(currentFile); - if dataFile.IsValid then - begin - if not tempSymbolMap.TryGetValue(dataFile.Symbol, symbolList) then - begin - symbolList := TList.Create; - tempSymbolMap.Add(dataFile.Symbol, symbolList); - end; - symbolList.Add(dataFile); - end; - end; - - for var kvp in tempSymbolMap do - begin - symbolList := kvp.Value; - symbolList.Sort( - TComparer.Construct( - function(const Left, Right: TDataFile): Integer - begin - if Left.Year < Right.Year then - Result := -1 - else if Left.Year > Right.Year then - Result := 1 - else - Result := Left.Month - Right.Month; - end - ) - ); - Result.Add(kvp.Key, symbolList.ToArray); - end; - finally - for var kvp in tempSymbolMap do - kvp.Value.Free; - tempSymbolMap.Free; - end; - end - ); - FSymbols.Manage; -end; - -function TScalarBatchLoader.EnumerateSymbols: TFuture>; -begin - Result := - FSymbols.Chain>( - function(const Symbols: TDictionary>): TArray begin Result := Symbols.Keys.ToArray; end - ); -end; - -function TScalarBatchLoader.ParseFileName(const FileName: string): TDataFile; -var - path, fileNameNoPath, baseName, ext, symbol: string; - year, month: Integer; - parts, dateParts: TArray; -begin - Result := Default(TDataFile); - path := TPath.GetDirectoryName(FileName); - fileNameNoPath := TPath.GetFileName(FileName); - - ext := TPath.GetExtension(fileNameNoPath); - - if not fileNameNoPath.EndsWith(FFileExtension, True) then - exit; - - baseName := TPath.GetFileNameWithoutExtension(fileNameNoPath); - - parts := baseName.Split(['_']); - if Length(parts) < 3 then - exit; - - var startDatePart := parts[High(parts) - 1]; - dateParts := startDatePart.Split(['-']); - if Length(dateParts) <> 2 then - exit; - - if not TryStrToInt(dateParts[0], year) then - exit; - if not TryStrToInt(dateParts[1], month) then - exit; - - if (month < 1) or (month > 12) or (year <= 0) then - exit; - - symbol := string.Join('_', Copy(parts, 0, Length(parts) - 2)); - if symbol = '' then - exit; - - Result := TDataFile.Create(path, symbol, ext, year, month, baseName); -end; - -function TScalarBatchLoader.LoadDataFile(const DataFile: TDataFile): TFuture>; -begin - if DataFile.IsValid then - Result := - FCachedFiles.GetOrAdd( - DataFile.GetFullFileName, - function(const Filename: String): TFuture> begin Result := DoLoad(Filename, FLoadGate); end - ) - else - Result := TFuture>.Construct(TArray(nil)); -end; - -function TScalarBatchLoader.DoLoad(const FileName: string; const Gate: TLatch): TFuture>; -begin - Result := TFuture>.Null; - if not TFile.Exists(FileName) then - exit; - - var capFileName := FileName; - - if FIsCompressed then - begin - Result := - TFuture - .Construct(Gate.Enqueue, function: TBytes begin Result := TFile.ReadAllBytes(capFileName); end) - .Chain>( - function(bytes: TBytes): TArray - begin - var ms := TBytesStream.Create(bytes); - try - Result := ReadCompressedData(ms); - finally - ms.Free; - end; - end); - end - else - begin - Result := - TFuture>.Construct( - Gate.Enqueue, - function: TArray - begin - var fs := TFileStream.Create(capFileName, fmOpenRead or fmShareDenyWrite); - try - Result := ReadUncompressedData(fs); - finally - fs.Free; - end; - end - ); - end; -end; - -function TScalarBatchLoader.ReadCompressedData(const InputStream: TStream): TArray; -var - decompressionStream: TStream; - localHeader: TZipHeader; - entryIndex, i: Integer; - zip: TZipFile; -begin - Result := nil; - decompressionStream := nil; - zip := nil; - - if not Assigned(InputStream) or (InputStream.Size = 0) then - exit; - - try - InputStream.Position := 0; - zip := TZipFile.Create; - zip.Open(InputStream, TZipMode.zmRead); - - if zip.FileCount = 0 then - exit; - - entryIndex := -1; - for i := 0 to zip.FileCount - 1 do - begin - if zip.FileNames[i].EndsWith(FFileExtension, True) then - begin - entryIndex := i; - break; - end; - end; - - if entryIndex = -1 then - entryIndex := 0; - - zip.Read(entryIndex, decompressionStream, localHeader); - if not Assigned(decompressionStream) then - exit; - - Result := ReadUncompressedData(decompressionStream); - finally - decompressionStream.Free; - zip.Free; - end; -end; - -function TScalarBatchLoader.ReadUncompressedData(const InputStream: TStream): TArray; -var - fileSize, totalRecords: Int64; - numBatches, batchIdx, k: Integer; - bytesToRead, valuesToWrite: Integer; - tempBuffer: TBytes; - pSrc: PByte; - pDst: TScalar.PValue; -begin - Result := nil; - InputStream.Position := 0; - fileSize := InputStream.Size; - - if (fileSize = 0) or ((fileSize mod FRecordSize) <> 0) then - exit; - - totalRecords := fileSize div FRecordSize; - if totalRecords = 0 then - exit; - - numBatches := (totalRecords + BatchSize - 1) div BatchSize; - SetLength(Result, numBatches); - - // Buffer for reading raw data chunks before conversion - SetLength(tempBuffer, BatchSize * FRecordSize); - - for batchIdx := 0 to numBatches - 1 do - begin - var recordsInBatch := Min(BatchSize, totalRecords - (batchIdx * BatchSize)); - Result[batchIdx].RecCount := recordsInBatch; - - // FRecordSize determines both allocation count and input byte stride - valuesToWrite := recordsInBatch * FRecordSize; - SetLength(Result[batchIdx].Data, valuesToWrite); - - bytesToRead := recordsInBatch * FRecordSize; - if InputStream.Read(tempBuffer, 0, bytesToRead) <> bytesToRead then - raise EReadError.Create('Unexpected end of stream'); - - pSrc := @tempBuffer[0]; - pDst := @Result[batchIdx].Data[0]; - - // Always use the converter to transform raw bytes to TValues - for k := 0 to recordsInBatch - 1 do - begin - FConverter(pSrc, pDst); - Inc(pSrc, FRecordSize); - Inc(pDst, FRecordSize); - end; - end; -end; - -function TScalarBatchLoader.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 := - FSymbols.Chain( - function(const AllSymbols: TDictionary>): TState - var - files: TArray; - begin - if AllSymbols.TryGetValue(cSymbol, files) and (Length(files) > 0) then - begin - // Start with Index 0 - Result := ProcessFile(files, 0, LoadDataFile(files[0]), cTerminated); - end - else - begin - Result := TState.Null; - end; - end - ); -end; - -function TScalarBatchLoader.ProcessFile( - const Files: TArray; - Index: Integer; - const DataFile: TFuture>; - const Terminated: TState -): TState; -begin - // Check bounds and termination - if (Index < 0) or (Index > High(Files)) or Terminated.IsSet then - exit(DataFile.Done); - - 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); - - // Recurse with Index + 1 - Result := - TaskManager.RunTask(done, function: TState begin Result := ProcessFile(Files, nextIndex, nextFuture, cTerminated); end); - end - ); -end; - -function TScalarBatchLoader.ProcessChunks(const Batches: TArray; Terminated: TState): TState; -begin - var callProcess := - function(Idx: Integer): TFunc - begin - var cBatch := Batches[Idx]; - - Result := - function: TState - begin - if not Terminated.IsSet then - begin - // Broadcast the raw batch. - FBatchProducer.Broadcast(cBatch); - Result := TState.Null; - end; - end; - end; - - Result := TState.Null; - - for var i := 0 to High(Batches) do - if not Terminated.IsSet then - begin - var queue := TaskManager.RunTask(Result, callProcess(i)); - Result := queue; - end; -end; - -end. diff --git a/Src/Myc.Trade.DataStream.pas b/Src/Myc.Trade.DataStream.pas index 9c16278..6eff592 100644 --- a/Src/Myc.Trade.DataStream.pas +++ b/Src/Myc.Trade.DataStream.pas @@ -16,6 +16,24 @@ uses Myc.Core.FileCache; type + // Match C# M1Record (Pack = 1, 48 Bytes) + TM1Record = packed record + Time: Double; + Open: Double; + High: Double; + Low: Double; + Close: Double; + Spread: Single; + Volume: Integer; + end; + + // Match C# TickRecord (Pack = 1, 24 Bytes) + TTickRecord = packed record + Time: Double; + Ask: Double; + Bid: Double; + end; + // Interface for an instantiable data server. IDataServer = interface procedure ClearCache; @@ -23,7 +41,7 @@ type function EnumerateSymbols: TFuture>; end; - // Represents metadata for a single data file. + // Metadata for a monthly data file (SYMBOL_YYYY_MM.EXT) TDataFile = record private FExtension: String; @@ -45,12 +63,11 @@ type property Month: Integer read FMonth; end; - // Generic server for loading and managing sequential time-series data from files. - TDataServer = class(TInterfacedObject, IDataServer) + // Generic server base handling the pipeline and preloading. + TDataServer = class(TInterfacedObject, IDataServer) private FCachedFiles: TDataFileCache>>>; FPath: String; - // The cache now holds a sorted array of all files for each symbol. FSymbols: TFuture>>; function GetPath: String; @@ -72,10 +89,12 @@ type FLoadGate: TLatch; protected - // Used by cache to actually load an uncached file. Now virtual and abstract. - function DoLoad(const FileName: string; const Gate: TLatch): TFuture>>>; virtual; abstract; - // Gets the next consecutive data file from the cached, sorted list. + // Maps the raw file record to the internal TDataPoint + function MapRecord(const RecordBuffer: R): TDataPoint; virtual; abstract; + function DoLoad(const FileName: string; const Gate: TLatch): TFuture>>>; function GetNextFile(const Curr: TDataFile): TDataFile; virtual; + function ReadCompressedData(const InputStream: TStream): TArray>>; + function ReadUncompressedData(const InputStream: TStream): TArray>>; public constructor Create(const APath: String); @@ -83,58 +102,27 @@ type procedure AfterConstruction; override; procedure ClearCache; procedure UpdateSymbols; - // Scans a directory to find the oldest file for a specific symbol. function FindFirstFile(const Symbol: string): TFuture; - function ParseFileName(const FileName: string): TDataFile; virtual; abstract; + function ParseFileName(const FileName: string): TDataFile; function EnumerateSymbols: TFuture>; - - // Load data file and split content into chunks. function LoadDataFile(const DataFile: TDataFile): TFuture>>>; - function ProcessData(const Symbol: String; const Terminated: TState; const Processor: IConsumer>>): TState; property Path: String read GetPath; end; - TAskBidFileItem = packed record - Ask: Single; - Bid: Single; - end; - - TAskBidFileServer = class(TDataServer) - private - class function ReadCompressedData(const InputStream: TStream): TArray>>; - class function ReadUncompressedData(const InputStream: TStream): TArray>>; + TTickFileServer = class(TDataServer) protected - function DoLoad(const FileName: string; const Gate: TLatch): TFuture>>>; override; - public - function ParseFileName(const FileName: string): TDataFile; override; + function MapRecord(const RecordBuffer: TTickRecord): TDataPoint; override; end; - TM1FileItem = packed record - OADateTime: Double; - Open: Int64; - High: Int64; - Low: Int64; - Close: Int64; - Spread: Int64; - TickVolume: Integer; - Digits: Integer; - end; - - // File server for cTrader M1 data. Note that the generic type is TOhlcItem, - // as the server converts the file data into standard OHLC items. - TM1FileServer = class(TDataServer) - private - class function ReadCompressedData(const InputStream: TStream): TArray>>; - class function ReadUncompressedData(const InputStream: TStream): TArray>>; + TM1FileServer = class(TDataServer) protected - function DoLoad(const FileName: string; const Gate: TLatch): TFuture>>>; override; - public - function ParseFileName(const FileName: string): TDataFile; override; + function MapRecord(const RecordBuffer: TM1Record): TDataPoint; override; end; implementation + uses System.Zip, System.ZLib, @@ -143,8 +131,7 @@ uses Myc.TaskManager; const - // The number of records per data chunk when loading files. - ChunkSize = 512; + ChunkSize = 1024; { TDataFile } @@ -165,43 +152,42 @@ end; function TDataFile.GetFullFileName: string; begin - Result := TPath.Combine(FPath, GetBaseFileName + FExtension); + Result := TPath.Combine(FPath, FBasename + FExtension); end; function TDataFile.GetIsValid: Boolean; begin - Result := (FSymbol <> '') and (FYear > 0); + Result := (FSymbol <> '') and (FYear > 0) and (FMonth >= 1) and (FMonth <= 12); end; -{ TDataServer } +{ TDataServer } -constructor TDataServer.Create(const APath: String); +constructor TDataServer.Create(const APath: String); begin inherited Create; FPath := APath; - FCachedFiles := TDataFileCache>>>.Create; end; -destructor TDataServer.Destroy; +destructor TDataServer.Destroy; begin ClearCache; FCachedFiles.Free; inherited Destroy; end; -procedure TDataServer.AfterConstruction; +procedure TDataServer.AfterConstruction; begin inherited; UpdateSymbols; end; -procedure TDataServer.ClearCache; +procedure TDataServer.ClearCache; begin FCachedFiles.Clear; end; -procedure TDataServer.UpdateSymbols; +procedure TDataServer.UpdateSymbols; begin FSymbols := TFuture>>.Construct( @@ -241,10 +227,8 @@ begin TComparer.Construct( function(const Left, Right: TDataFile): Integer begin - if Left.Year < Right.Year then - Result := -1 - else if Left.Year > Right.Year then - Result := 1 + if Left.Year <> Right.Year then + Result := Left.Year - Right.Year else Result := Left.Month - Right.Month; end @@ -263,7 +247,7 @@ begin FSymbols.Manage; end; -function TDataServer.EnumerateSymbols: TFuture>; +function TDataServer.EnumerateSymbols: TFuture>; begin Result := FSymbols.Chain>( @@ -271,7 +255,7 @@ begin ); end; -function TDataServer.FindFirstFile(const Symbol: string): TFuture; +function TDataServer.FindFirstFile(const Symbol: string): TFuture; begin var symName := Symbol; Result := @@ -288,13 +272,13 @@ begin ); end; -function TDataServer.GetNextFile(const Curr: TDataFile): TDataFile; +function TDataServer.GetNextFile(const Curr: TDataFile): TDataFile; var allSymbolFiles: TArray; foundIndex: Integer; begin Result := Default(TDataFile); - if not Curr.IsValid or not FSymbols.Done.IsSet then + if (not Curr.IsValid) or (not FSymbols.Done.IsSet) then exit; if not FSymbols.Value.TryGetValue(Curr.Symbol, allSymbolFiles) then @@ -303,7 +287,7 @@ begin foundIndex := -1; for var i := 0 to High(allSymbolFiles) do begin - if allSymbolFiles[i].GetBaseFileName() = Curr.GetBaseFileName() then + if allSymbolFiles[i].GetBaseFileName = Curr.GetBaseFileName then begin foundIndex := i; break; @@ -311,51 +295,137 @@ begin end; if (foundIndex <> -1) and (foundIndex < High(allSymbolFiles)) then - begin Result := allSymbolFiles[foundIndex + 1]; - end; end; -function TDataServer.GetPath: String; +function TDataServer.GetPath: String; begin Result := FPath; end; -function TDataServer.ProcessData( - const Symbol: String; - const Terminated: TState; - const Processor: IConsumer>> -): TState; +function TDataServer.ParseFileName(const FileName: string): TDataFile; +var + fileNameNoPath, baseName, symbol, ext: string; + parts: TArray; + year, month: Integer; begin - var cProc := Processor; - var cTerminated := Terminated; + Result := Default(TDataFile); + fileNameNoPath := TPath.GetFileName(FileName); + ext := TPath.GetExtension(fileNameNoPath); + baseName := TPath.GetFileNameWithoutExtension(fileNameNoPath); - Result := - FindFirstFile(Symbol) - .Chain( - function(const FirstFileInfo: TDataFile): TState - begin - Result := ProcessFile(FirstFileInfo, LoadDataFile(FirstFileInfo), cTerminated, cProc); - end); + // Format: SYMBOL_YYYY_MM + parts := baseName.Split(['_']); + if Length(parts) < 3 then + exit; + + // Use reverse indexing for year and month + if (not TryStrToInt(parts[High(parts)], month)) or (not TryStrToInt(parts[High(parts) - 1], year)) then + exit; + + symbol := string.Join('_', Copy(parts, 0, Length(parts) - 2)); + Result := TDataFile.Create(TPath.GetDirectoryName(FileName), symbol, ext, year, month, baseName); end; -function TDataServer.LoadDataFile(const DataFile: TDataFile): TFuture>>>; +function TDataServer.LoadDataFile(const DataFile: TDataFile): TFuture>>>; begin if DataFile.IsValid then Result := FCachedFiles.GetOrAdd( DataFile.GetFullFileName, - function(const Filename: String): TFuture>>> - begin - // Pass the private load gate to the virtual DoLoad method. - Result := DoLoad(Filename, FLoadGate); - end + function(const Filename: String): TFuture>>> begin Result := DoLoad(Filename, FLoadGate); end ) else Result := TFuture>>>.Construct(TArray>>(nil)); end; -function TDataServer.ProcessChunks( +function TDataServer.DoLoad(const FileName: string; const Gate: TLatch): TFuture>>>; +begin + var capFileName := FileName; + Result := + TFuture + .Construct(Gate.Enqueue, function: TBytes begin Result := TFile.ReadAllBytes(capFileName); end) + .Chain>>>( + function(Bytes: TBytes): TArray>> + var + compStream: TBytesStream; + begin + compStream := TBytesStream.Create(Bytes); + try + Result := ReadCompressedData(compStream); + finally + compStream.Free; + end; + end); +end; + +function TDataServer.ReadCompressedData(const InputStream: TStream): TArray>>; +var + zip: TZipFile; + decompStream: TStream; + header: TZipHeader; + entryIdx: Integer; +begin + Result := nil; + InputStream.Position := 0; + zip := TZipFile.Create; + try + zip.Open(InputStream, TZipMode.zmRead); + entryIdx := -1; + // Search for the .bin entry created by C# + for var i := 0 to zip.FileCount - 1 do + begin + if zip.FileNames[i].EndsWith('.bin', true) then + begin + entryIdx := i; + break; + end; + end; + + if entryIdx = -1 then + exit; + + zip.Read(entryIdx, decompStream, header); + try + Result := ReadUncompressedData(decompStream); + finally + decompStream.Free; + end; + finally + zip.Free; + end; +end; + +function TDataServer.ReadUncompressedData(const InputStream: TStream): TArray>>; +var + totalRecords, chunkCount, i, j, recsInChunk: Integer; + rawBuffer: TArray; +begin + Result := nil; + totalRecords := InputStream.Size div sizeof(R); + if totalRecords = 0 then + exit; + + // Fast block read into memory + SetLength(rawBuffer, totalRecords); + InputStream.Position := 0; + InputStream.ReadBuffer(rawBuffer[0], InputStream.Size); + + chunkCount := (totalRecords + ChunkSize - 1) div ChunkSize; + SetLength(Result, chunkCount); + + for i := 0 to chunkCount - 1 do + begin + recsInChunk := Min(ChunkSize, totalRecords - (i * ChunkSize)); + SetLength(Result[i], recsInChunk); + for j := 0 to recsInChunk - 1 do + begin + Result[i][j] := MapRecord(rawBuffer[i * ChunkSize + j]); + end; + end; +end; + +function TDataServer.ProcessChunks( const DataChunks: TArray>>; Terminated: TState; Processor: IConsumer>> @@ -374,36 +444,34 @@ begin end; for var i := 0 to High(DataChunks) do + begin if not Terminated.IsSet then begin var q := TaskManager.RunTask(Result, callProcess(i)); Result := q; - end + end; + end; end; -function TDataServer.ProcessFile( +function TDataServer.ProcessFile( FileInfo: TDataFile; const DataFile: TFuture>>>; const Terminated: TState; Processor: IConsumer>> ): TState; begin - if not FileInfo.IsValid or Terminated.IsSet then + if (not FileInfo.IsValid) or (Terminated.IsSet) then exit(DataFile.Done); - // Read ahead the next file, while processing the current one var nextFileInfo := GetNextFile(FileInfo); var nextFile := LoadDataFile(nextFileInfo); - var cTerminated := Terminated; + Result := DataFile.Chain( function(const DataChunks: TArray>>): TState begin - // Process each chunk, checking for termination between chunks. - var done := ProcessChunks(DataChunks, Terminated, Processor); - - // Move to next file (which is currently preloading) once all Processors are done + var done := ProcessChunks(DataChunks, cTerminated, Processor); Result := TaskManager .RunTask(done, function: TState begin Result := ProcessFile(nextFileInfo, nextFile, cTerminated, Processor); end); @@ -411,370 +479,35 @@ begin ); end; -{ TAskBidFileServer } - -function TAskBidFileServer.DoLoad(const FileName: string; const Gate: TLatch): TFuture>>>; +function TDataServer.ProcessData( + const Symbol: String; + const Terminated: TState; + const Processor: IConsumer>> +): TState; begin - Result := TFuture>>>.Null; - - if not TFile.Exists(FileName) then - exit; - - var capFileName := FileName; - if FileName.EndsWith('_zip', True) then - begin - Result := - TFuture - .Construct(Gate.Enqueue, function: TBytes begin Result := TFile.ReadAllBytes(capFileName); end) - .Chain>>>( - function(bytes: TBytes): TArray>> - begin - var compMemoryStream := TBytesStream.Create(bytes); - try - compMemoryStream.Position := 0; - Result := ReadCompressedData(compMemoryStream); - finally - compMemoryStream.Free; - end; - end); - end - else - begin - Result := - TFuture>>>.Construct( - Gate.Enqueue, - function: TArray>> - begin - if TFile.Exists(capFileName) then - begin - var stream := TFileStream.Create(capFileName, fmOpenRead or fmShareDenyWrite); - try - Result := ReadUncompressedData(stream); - finally - stream.Free; - end; - end; - end - ); - end; + var cProc := Processor; + var cTerm := Terminated; + Result := + FindFirstFile(Symbol) + .Chain(function(const Info: TDataFile): TState begin Result := ProcessFile(Info, LoadDataFile(Info), cTerm, cProc); end); end; -function TAskBidFileServer.ParseFileName(const FileName: string): TDataFile; -var - fileNameNoPath, nameForParsing, baseName, ext, path, symbol: string; - year, month: Integer; - parts: TArray; +{ TTickFileServer } + +function TTickFileServer.MapRecord(const RecordBuffer: TTickRecord): TDataPoint; begin - Result := Default(TDataFile); - - path := TPath.GetDirectoryName(FileName); - fileNameNoPath := TPath.GetFileName(FileName); - nameForParsing := fileNameNoPath; - - ext := ''; - if nameForParsing.EndsWith('_zip', True) then - begin - ext := '_zip'; - nameForParsing := nameForParsing.Substring(0, nameForParsing.Length - 4); - end; - - var fileExt := TPath.GetExtension(nameForParsing) + ext; - baseName := TPath.GetFileNameWithoutExtension(nameForParsing); - - parts := baseName.Split(['_']); - - if Length(parts) < 3 then - exit; - - if not TryStrToInt(parts[High(parts)], month) then - exit; - - if (month < 1) or (month > 12) then - exit; - - if not TryStrToInt(parts[High(parts) - 1], year) then - exit; - - if year <= 0 then - exit; - - symbol := string.Join('_', Copy(parts, 0, Length(parts) - 2)); - - if symbol = '' then - exit; - - Result := TDataFile.Create(path, symbol, fileExt, year, month, baseName); -end; - -class function TAskBidFileServer.ReadCompressedData(const InputStream: TStream): TArray>>; -var - decompressionStream: TStream; - localHeader: TZipHeader; - entryIndex, i: Integer; - zipFileInstance: TZipFile; -begin - Result := nil; - decompressionStream := nil; - zipFileInstance := nil; - try - InputStream.Position := 0; - zipFileInstance := TZipFile.Create; - zipFileInstance.Open(InputStream, TZipMode.zmRead); - - if zipFileInstance.FileCount = 0 then - exit; - - entryIndex := -1; - for i := 0 to zipFileInstance.FileCount - 1 do - if zipFileInstance.FileNames[i].EndsWith('.tab', True) then - begin - entryIndex := i; - break; - end; - - if entryIndex = -1 then - entryIndex := 0; - - zipFileInstance.Read(entryIndex, decompressionStream, localHeader); - if not Assigned(decompressionStream) then - exit; - Result := ReadUncompressedData(decompressionStream); - finally - decompressionStream.Free; - zipFileInstance.Free; - end; -end; - -class function TAskBidFileServer.ReadUncompressedData(const InputStream: TStream): TArray>>; -type - TFileRecord = packed record - TimeStamp: TDateTime; - Data: TAskBidFileItem; - end; -var - fileSize: Int64; - totalRecordCount, bytesRead, chunkIndex, indexInChunk, recordIndex: Integer; - rec: TFileRecord; -begin - Result := nil; - InputStream.Position := 0; - fileSize := InputStream.Size; - if (fileSize = 0) or ((fileSize mod SizeOf(TFileRecord)) <> 0) then - exit; - - totalRecordCount := fileSize div SizeOf(TFileRecord); - if totalRecordCount > 0 then - begin - var numChunks := (totalRecordCount + ChunkSize - 1) div ChunkSize; - SetLength(Result, numChunks); - chunkIndex := 0; - indexInChunk := 0; - SetLength(Result[chunkIndex], Min(ChunkSize, totalRecordCount)); - - for recordIndex := 0 to totalRecordCount - 1 do - begin - if indexInChunk >= ChunkSize then - begin - Inc(chunkIndex); - indexInChunk := 0; - var remainingRecords := totalRecordCount - (chunkIndex * ChunkSize); - SetLength(Result[chunkIndex], Min(ChunkSize, remainingRecords)); - end; - - bytesRead := InputStream.Read(rec, SizeOf(TFileRecord)); - if bytesRead <> SizeOf(TFileRecord) then - raise EReadError.CreateFmt('Read error. Expected %d bytes, read %d.', [SizeOf(TFileRecord), bytesRead]); - - // Corrected syntax: Assign the newly created record instance. - Result[chunkIndex][indexInChunk] := TDataPoint.Create(rec.TimeStamp, rec.Data); - Inc(indexInChunk); - end; - end; + Result := TDataPoint.Create(RecordBuffer.Time, RecordBuffer); end; { TM1FileServer } -function TM1FileServer.DoLoad(const FileName: string; const Gate: TLatch): TFuture>>>; +function TM1FileServer.MapRecord(const RecordBuffer: TM1Record): TDataPoint; begin - Result := TFuture>>>.Null; - - if not TFile.Exists(FileName) then - exit; - - var capFileName := FileName; - // M1 files are always compressed with the .m1 extension - if FileName.EndsWith('.m1', True) then - begin - Result := - TFuture - .Construct(Gate.Enqueue, function: TBytes begin Result := TFile.ReadAllBytes(capFileName); end) - .Chain>>>( - function(bytes: TBytes): TArray>> - begin - var compMemoryStream := TBytesStream.Create(bytes); - try - compMemoryStream.Position := 0; - Result := ReadCompressedData(compMemoryStream); - finally - compMemoryStream.Free; - end; - end); - end; -end; - -function TM1FileServer.ParseFileName(const FileName: string): TDataFile; -var - path, fileNameNoPath, baseName, ext, symbol: string; - year, month: Integer; - parts, dateParts: TArray; -begin - Result := Default(TDataFile); - path := TPath.GetDirectoryName(FileName); - fileNameNoPath := TPath.GetFileName(FileName); - - // M1 files are compressed and have a .m1 extension - if not fileNameNoPath.EndsWith('.m1', True) then - exit; - - ext := TPath.GetExtension(fileNameNoPath); - baseName := TPath.GetFileNameWithoutExtension(fileNameNoPath); - - // Expected format: SYMBOL_YYYY-MM_YYYY-MM - parts := baseName.Split(['_']); - if Length(parts) < 3 then - exit; // Not enough parts for SYMBOL_START_END - - // The symbol can contain underscores, so we take everything before the last two parts. - var startDatePart := parts[High(parts) - 1]; - - dateParts := startDatePart.Split(['-']); - if Length(dateParts) <> 2 then - exit; // Start date is not YYYY-MM - - if not TryStrToInt(dateParts[0], year) then - exit; - - if not TryStrToInt(dateParts[1], month) then - exit; - - if (month < 1) or (month > 12) or (year <= 0) then - exit; - - symbol := string.Join('_', Copy(parts, 0, Length(parts) - 2)); - if symbol = '' then - exit; - - // The TDataFile only represents the start date of the file batch. - Result := TDataFile.Create(path, symbol, ext, year, month, baseName); -end; - -class function TM1FileServer.ReadCompressedData(const InputStream: TStream): TArray>>; -var - decompressionStream: TStream; - localHeader: TZipHeader; - entryIndex, i: Integer; - zipFileInstance: TZipFile; -begin - Result := nil; - decompressionStream := nil; - zipFileInstance := nil; - - // M1 files are now zip archives containing the actual data file. - if not Assigned(InputStream) or (InputStream.Size = 0) then - exit; - - try - InputStream.Position := 0; - zipFileInstance := TZipFile.Create; - zipFileInstance.Open(InputStream, TZipMode.zmRead); - - if zipFileInstance.FileCount = 0 then - exit; - - // Find the data file entry within the archive. - // The C# code creates an entry with the same name as the base filename, ending in .m1. - entryIndex := -1; - for i := 0 to zipFileInstance.FileCount - 1 do - begin - if zipFileInstance.FileNames[i].EndsWith('.m1', True) then - begin - entryIndex := i; - break; - end; - end; - - // Fallback to the first entry if no specific .m1 file is found inside. - if entryIndex = -1 then - entryIndex := 0; - - zipFileInstance.Read(entryIndex, decompressionStream, localHeader); - if not Assigned(decompressionStream) then - exit; - - // The decompressed stream now contains the raw binary data. - Result := ReadUncompressedData(decompressionStream); - finally - decompressionStream.Free; - zipFileInstance.Free; - end; -end; - -class function TM1FileServer.ReadUncompressedData(const InputStream: TStream): TArray>>; -type - TFileRecord = TM1FileItem; -var - fileSize: Int64; - totalRecordCount, bytesRead, chunkIndex, indexInChunk, recordIndex: Integer; - rec: TFileRecord; - ohlc: TOhlcItem; - factor: Double; -begin - Result := nil; - InputStream.Position := 0; - fileSize := InputStream.Size; - if (fileSize = 0) or ((fileSize mod SizeOf(TFileRecord)) <> 0) then - exit; - - totalRecordCount := fileSize div SizeOf(TFileRecord); - if totalRecordCount > 0 then - begin - var numChunks := (totalRecordCount + ChunkSize - 1) div ChunkSize; - SetLength(Result, numChunks); - chunkIndex := 0; - indexInChunk := 0; - SetLength(Result[chunkIndex], Min(ChunkSize, totalRecordCount)); - - for recordIndex := 0 to totalRecordCount - 1 do - begin - if indexInChunk >= ChunkSize then - begin - Inc(chunkIndex); - indexInChunk := 0; - var remainingRecords := totalRecordCount - (chunkIndex * ChunkSize); - SetLength(Result[chunkIndex], Min(ChunkSize, remainingRecords)); - end; - - bytesRead := InputStream.Read(rec, SizeOf(TFileRecord)); - if bytesRead <> SizeOf(TFileRecord) then - raise EReadError.CreateFmt('Read error. Expected %d bytes, read %d.', [SizeOf(TFileRecord), bytesRead]); - - // Convert from M1 file record to a standard OHLC item - if rec.Digits > 0 then - factor := Power(10, rec.Digits) - else - factor := 1.0; - - ohlc.Open := rec.Open / factor; - ohlc.High := rec.High / factor; - ohlc.Low := rec.Low / factor; - ohlc.Close := rec.Close / factor; - ohlc.Volume := rec.TickVolume; - - // Corrected syntax: Assign the newly created record instance. - Result[chunkIndex][indexInChunk] := TDataPoint.Create(rec.OADateTime, ohlc); - Inc(indexInChunk); - end; - end; + Result := + TDataPoint.Create( + RecordBuffer.Time, + TOhlcItem.Create(RecordBuffer.Open, RecordBuffer.High, RecordBuffer.Low, RecordBuffer.Close, RecordBuffer.Volume) + ); end; end.