Streamlining main app

Bugfix in Chart -> StrokeJoint set to Bevel
This commit is contained in:
Michael Schimmel
2025-07-14 19:52:40 +02:00
parent 6f0b927a05
commit d9a82365d3
8 changed files with 317 additions and 737 deletions
+1 -1
View File
@@ -4,7 +4,7 @@
<ProjectVersion>20.3</ProjectVersion>
<FrameworkType>FMX</FrameworkType>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Release</Config>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win64</Platform>
<ProjectName Condition="'$(ProjectName)'==''">AuraTrader</ProjectName>
<TargetedPlatforms>3</TargetedPlatforms>
-4
View File
@@ -42,17 +42,13 @@ type
TTicksToBars = class(TMycConverter<TDataPoint<TAskBidItem>, TDataPoint<TOhlcItem>>)
private
FTimeframe: TTimeframe;
// Stores the currently aggregating OHLC data.
FCurrentBar: TDataPoint<TOhlcItem>;
function GetBarStartTime(const TimeStamp: TDateTime; const Timeframe: TTimeframe): TDateTime;
function GetCurrentBar: TDataPoint<TOhlcItem>;
function GetTimeframe: TTimeframe;
public
constructor Create(const ATimeframe: TTimeframe);
// Process new data. This is called concurrently and must not have side effects out of the scope of this class!
function ProcessData(const Value: TDataPoint<TAskBidItem>): TState; override;
property CurrentBar: TDataPoint<TOhlcItem> read GetCurrentBar;
property Timeframe: TTimeframe read GetTimeframe;
end;
+47 -39
View File
@@ -3,7 +3,7 @@ object Form1: TForm1
Top = 0
Caption = 'Form1'
ClientHeight = 840
ClientWidth = 796
ClientWidth = 1017
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
@@ -12,7 +12,7 @@ object Form1: TForm1
DesignerMasterStyle = 0
object MainPanel: TPanel
Align = Client
Size.Width = 796.000000000000000000
Size.Width = 1017.000000000000000000
Size.Height = 712.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
@@ -27,30 +27,30 @@ object Form1: TForm1
end
object WorkspacePanel: TPanel
Align = Client
Size.Width = 619.000000000000000000
Size.Width = 840.000000000000000000
Size.Height = 712.000000000000000000
Size.PlatformDefault = False
TabOrder = 3
object TabControl: TTabControl
Align = Client
Size.Width = 619.000000000000000000
Size.Height = 672.000000000000000000
Size.Width = 840.000000000000000000
Size.Height = 678.000000000000000000
Size.PlatformDefault = False
TabIndex = 0
TabOrder = 10
TabPosition = PlatformDefault
end
object ToolBar: TToolBar
Size.Width = 619.000000000000000000
Size.Height = 40.000000000000000000
Size.Width = 840.000000000000000000
Size.Height = 34.000000000000000000
Size.PlatformDefault = False
TabOrder = 3
object AddWorkspaceButton: TSpeedButton
Action = AddWorkspaceAction
Align = FitLeft
ImageIndex = -1
Size.Width = 145.454589843750000000
Size.Height = 40.000000000000000000
Size.Width = 123.636383056640600000
Size.Height = 34.000000000000000000
Size.PlatformDefault = False
Text = 'Add'
TextSettings.Trimming = None
@@ -59,9 +59,9 @@ object Form1: TForm1
Action = TestAction
Align = FitLeft
ImageIndex = -1
Position.X = 145.454589843750000000
Size.Width = 145.454544067382800000
Size.Height = 40.000000000000000000
Position.X = 123.636383056640600000
Size.Width = 123.636322021484400000
Size.Height = 34.000000000000000000
Size.PlatformDefault = False
TextSettings.Trimming = None
object TestPopup: TPopup
@@ -88,10 +88,9 @@ object Form1: TForm1
Size.Width = 47.000000000000000000
Size.Height = 22.000000000000000000
Size.PlatformDefault = False
TabOrder = 5
TabOrder = 4
Text = 'Load'
TextSettings.Trimming = None
OnClick = LoadButtonClick
end
object RandomButton: TButton
Anchors = [akTop, akRight]
@@ -99,45 +98,54 @@ object Form1: TForm1
TabOrder = 2
Text = 'Random'
TextSettings.Trimming = None
OnClick = RandomButtonClick
end
object StopButton: TButton
Anchors = [akTop, akRight]
Position.Y = 63.000000000000000000
TabOrder = 8
Text = 'StopButton'
TextSettings.Trimming = None
OnClick = StopButtonClick
end
object ChartButton: TButton
Anchors = [akTop, akRight]
Position.Y = 85.000000000000000000
TabOrder = 7
Position.Y = 63.000000000000000000
TabOrder = 6
Text = 'ChartButton'
TextSettings.Trimming = None
OnClick = ChartButtonClick
end
object SymbolsComboBox: TComboBox
Anchors = [akTop, akRight]
Position.Y = 107.000000000000000000
Size.Width = 177.000000000000000000
Size.Height = 22.000000000000000000
Size.PlatformDefault = False
TabOrder = 4
end
end
end
end
object StrategyButton: TSpeedButton
Align = FitLeft
Position.X = 290.909118652343800000
Size.Width = 145.454467773437500000
Size.Height = 40.000000000000000000
Position.X = 247.272705078125000000
Size.Width = 123.250000000000000000
Size.Height = 34.000000000000000000
Size.PlatformDefault = False
Text = 'Strategy'
TextSettings.Trimming = None
OnClick = StrategyButtonClick
end
object SymbolsComboBox: TComboBox
Align = FitLeft
Margins.Top = 4.000000000000000000
Margins.Bottom = 4.000000000000000000
Position.X = 370.522735595703100000
Position.Y = 4.000000000000000000
Size.Width = 141.192199707031300000
Size.Height = 26.000000000000000000
Size.PlatformDefault = False
TabOrder = 3
end
object StopButton: TButton
Align = FitLeft
Margins.Left = 8.000000000000000000
Margins.Top = 4.000000000000000000
Margins.Right = 8.000000000000000000
Margins.Bottom = 4.000000000000000000
Position.X = 519.714965820312500000
Position.Y = 4.000000000000000000
Size.Width = 111.404327392578100000
Size.Height = 26.000000000000000000
Size.PlatformDefault = False
TabOrder = 7
Text = 'StopButton'
TextSettings.Trimming = None
OnClick = StopButtonClick
end
end
end
object ObjectsPanel: TPanel
@@ -191,11 +199,11 @@ object Form1: TForm1
DataDetectorTypes = []
Align = Bottom
Position.Y = 712.000000000000000000
Size.Width = 796.000000000000000000
Size.Width = 1017.000000000000000000
Size.Height = 128.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Viewport.Width = 792.000000000000000000
Viewport.Width = 1013.000000000000000000
Viewport.Height = 124.000000000000000000
end
object ActionList: TActionList
+214 -356
View File
@@ -75,32 +75,18 @@ type
TestPopup: TPopup;
FlowLayout: TFlowLayout;
StrategyButton: TSpeedButton;
procedure RandomButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LoadButtonClick(Sender: TObject);
procedure ChartButtonClick(Sender: TObject);
procedure StopButtonClick(Sender: TObject);
procedure LayoutResized(Sender: TObject);
procedure TreeViewDblClick(Sender: TObject);
procedure AddWorkspaceActionExecute(Sender: TObject);
procedure TestActionExecute(Sender: TObject);
procedure StrategyButtonClick(Sender: TObject);
private
const
cnt = 20;
type
TRndItem = record
Stream: IDataStream<TAuraAskBidFileItem>;
Data: TMutable<TDataSeries<TAuraAskBidFileItem>>;
Labl: TLabel;
end;
private
FOnEvent: TNotifyEvent;
{ Private declarations }
FServer: IDataServer<TAuraAskBidFileItem>;
FSymbols: TFuture<TArray<String>>;
FRandom: TList<TRndItem>;
FTerminate: TEvent;
FProcessDone: TState;
FApplication: IAuraApplication;
@@ -148,6 +134,184 @@ begin
FTerminate.Notify;
end;
procedure TForm1.TreeViewDblClick(Sender: TObject);
begin
var sel := TreeView.Selected as TTreeViewItem;
var parent := sel.ParentItem;
if parent = nil then
exit;
if parent = FModulesItem then
begin
if (TabControl.ActiveTab <> nil) and (TabControl.ActiveTab.Tag <> 0) then
begin
var ws := IAuraWorkspace(TabControl.ActiveTab.Tag);
var module := FApplication.Modules[sel.TagString];
if (ws <> nil) and (module <> nil) then
module.SetupWorkspace(ws);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FApplication := TMycAuraApplication.Create;
FModulesItem := TTreeViewItem.Create(Self);
FModulesItem.Text := 'Modules';
const modName = 'Test_Module';
FApplication.RegisterModule(modName, TTestModule.Create('Test-Module', 1));
TreeView.AddObject(FModulesItem);
FModulesItem.ProcessSignal(
FApplication.ModuleNames.Changed,
procedure
begin
FModulesItem.BeginUpdate;
try
while FModulesItem.Count > 0 do
FModulesItem[0].Free;
var mods := FApplication.ModuleNames.Value;
for var i := 0 to High(mods) do
begin
var ModItem := TTreeViewItem.Create(Self);
ModItem.Text := mods[i];
ModItem.DragMode := TDragMode.dmAutomatic;
ModItem.Text := 'Module-' + mods[i];
ModItem.TagString := mods[i];
FModulesItem.AddObject(ModItem);
end;
FModulesItem.ExpandAll;
finally
FModulesItem.EndUpdate;
end;
end
);
FTerminate := TEvent.CreateEvent;
// Create an instance of the TAuraTABFileServer. The server can be reused for multiple stream creations. [364]
FServer := TAuraTABFileServer.Create('\\COFFEE\TickData\Pepperstone');
SymbolsComboBox.Enabled := false;
ChartButton.Enabled := false;
LoadButton.Enabled := false;
FSymbols := FServer.EnumerateSymbols;
SymbolsComboBox.ProcessSignal(
FSymbols.Done.Signal,
procedure
begin
SymbolsComboBox.BeginUpdate;
try
SymbolsComboBox.Items.Clear;
SymbolsComboBox.Items.AddStrings(FSymbols.WaitFor);
if SymbolsComboBox.Items.Count > 0 then
begin
if SymbolsComboBox.ItemIndex < 0 then
SymbolsComboBox.ItemIndex := SymbolsComboBox.Items.IndexOf('GER40');
SymbolsComboBox.Enabled := true;
ChartButton.Enabled := true;
LoadButton.Enabled := true;
end;
finally
SymbolsComboBox.EndUpdate;
end;
end
);
NewWorkspace;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FSymbols.WaitFor;
FTerminate.Notify;
TaskManager.WaitFor(FProcessDone);
end;
procedure TForm1.TestActionExecute(Sender: TObject);
begin
TestPopup.IsOpen := TestAction.Checked;
end;
procedure TForm1.AddWorkspaceActionExecute(Sender: TObject);
begin
NewWorkspace;
end;
procedure TForm1.AlignControl(Control: TControl);
begin
var Layout := CurrLayout<TVertScrollBox>;
if Layout = nil then
exit;
Control.Parent := Layout;
Control.Width := Layout.Width;
Control.Position.Y := Layout.ChildrenRect.Bottom + 1;
Control.Anchors := [TAnchorKind.akLeft, TAnchorKind.akRight];
Control.Align := TAlignLayout.Top;
end;
function TForm1.CurrLayout<T>: T;
begin
if TabControl.ActiveTab = nil then
exit(nil);
var Res: T := nil;
TabControl.ActiveTab.EnumControls(
function(Control: TControl): TEnumControlsResult
begin
Result := TEnumControlsResult.Continue;
if Control is T then
begin
Res := Control as T;
Result := TEnumControlsResult.Stop;
end;
end
);
Result := Res;
end;
function TForm1.ExecuteStrategy(const Symbol: String; const Processor: IMycProcessor<TArray<TDataPoint<TAskBidItem>>>): TState;
var
dataProvider: IMycConverter<TArray<TDataPoint<TAuraAskBidFileItem>>, TArray<TDataPoint<TAskBidItem>>>;
begin
var terminated := TFlag.CreateObserver(FTerminate.Signal).State;
dataProvider :=
TMycGenericConverter<TArray<TDataPoint<TAuraAskBidFileItem>>, TArray<TDataPoint<TAskBidItem>>>.Create(
function(const Values: TArray<TDataPoint<TAuraAskBidFileItem>>): TArray<TDataPoint<TAskBidItem>>
begin
SetLength(Result, Length(Values));
for var i := 0 to High(Result) do
begin
Result[i].Time := Values[i].Time;
Result[i].Data.Ask := Values[i].Data.Ask;
Result[i].Data.Bid := Values[i].Data.Bid;
end;
end
);
dataProvider.Sender.Link(Processor);
Result := FServer.ProcessData(Symbol, terminated, dataProvider);
end;
function TForm1.SelectedSymbol: String;
begin
Result := '';
if RandomBox.IsChecked then
Result := FSymbols.WaitFor[Random(Length(FSymbols.WaitFor))]
else if SymbolsComboBox.ItemIndex >= 0 then
Result := FSymbols.WaitFor[SymbolsComboBox.ItemIndex];
end;
procedure TForm1.StrategyButtonClick(Sender: TObject);
begin
var Layout := CurrLayout<TVertScrollBox>;
@@ -179,7 +343,7 @@ begin
OhlcPoint.Sender.Link(TimeStamps);
chart.SetXAxisSeries(timeframe, Timestamps.Sender);
var Panel := chart.Panels[0];
var Panel := chart.AddPanel;
var Ohlc: IMycConverter<TDataPoint<TOhlcItem>, TOhlcItem> :=
TMycGenericConverter<TDataPoint<TOhlcItem>, TOhlcItem>
@@ -275,351 +439,45 @@ begin
Stoch.Sender.Link(StochD);
Panel.AddDoubleSeries(StochD.Sender, TAlphaColors.Red);
var done := ExecuteStrategy(Symbol, ticker);
/////
var tickChart := TMycChart.Create(Self);
tickChart.Height := Layout.ChildrenRect.Width * 9 / 16;
AlignControl(tickChart);
tickChart.Lookback.Value := 1000000;
var TickTime: IMycConverter<TDataPoint<TAskBidItem>, TDateTime> :=
TMycGenericConverter<TDataPoint<TAskBidItem>, TDateTime>
.Create(function(const Tick: TDataPoint<TAskBidItem>): TDateTime begin Result := Tick.Time; end);
var TickAsk: IMycConverter<TDataPoint<TAskBidItem>, Double> :=
TMycGenericConverter<TDataPoint<TAskBidItem>, Double>
.Create(function(const Tick: TDataPoint<TAskBidItem>): Double begin Result := Tick.Data.Ask; end);
var TickBid: IMycConverter<TDataPoint<TAskBidItem>, Double> :=
TMycGenericConverter<TDataPoint<TAskBidItem>, Double>
.Create(function(const Tick: TDataPoint<TAskBidItem>): Double begin Result := Tick.Data.Bid; end);
var TickSpread: IMycConverter<TDataPoint<TAskBidItem>, Double> :=
TMycGenericConverter<TDataPoint<TAskBidItem>, Double>
.Create(function(const Tick: TDataPoint<TAskBidItem>): Double begin Result := Tick.Data.Bid-Tick.Data.Ask; end);
ticker.Sender.Link( TickTime );
ticker.Sender.Link( TickAsk );
ticker.Sender.Link( TickBid );
ticker.Sender.Link( TickSpread );
tickChart.SetXAxisSeries( TTimeframe.S, TickTime.Sender );
panel := tickChart.AddPanel;
panel.AddDoubleSeries(TickAsk.Sender, TAlphaColors.Blue);
panel.AddDoubleSeries(TickBid.Sender, TAlphaColors.Red);
panel := tickChart.AddPanel;
panel.AddDoubleSeries(TickSpread.Sender);
/////
var done := ExecuteStrategy(Symbol, ticker);
FProcessDone := TState.All([FProcessDone, done]);
end;
procedure TForm1.TreeViewDblClick(Sender: TObject);
begin
var sel := TreeView.Selected as TTreeViewItem;
var parent := sel.ParentItem;
if parent = nil then
exit;
if parent = FModulesItem then
begin
if (TabControl.ActiveTab <> nil) and (TabControl.ActiveTab.Tag <> 0) then
begin
var ws := IAuraWorkspace(TabControl.ActiveTab.Tag);
var module := FApplication.Modules[sel.TagString];
if (ws <> nil) and (module <> nil) then
module.SetupWorkspace(ws);
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
FApplication := TMycAuraApplication.Create;
FModulesItem := TTreeViewItem.Create(Self);
FModulesItem.Text := 'Modules';
const modName = 'Test_Module';
FApplication.RegisterModule(modName, TTestModule.Create('Test-Module', 1));
TreeView.AddObject(FModulesItem);
FModulesItem.ProcessSignal(
FApplication.ModuleNames.Changed,
procedure
begin
FModulesItem.BeginUpdate;
try
while FModulesItem.Count > 0 do
FModulesItem[0].Free;
var mods := FApplication.ModuleNames.Value;
for var i := 0 to High(mods) do
begin
var ModItem := TTreeViewItem.Create(Self);
ModItem.Text := mods[i];
ModItem.DragMode := TDragMode.dmAutomatic;
ModItem.Text := 'Module-' + mods[i];
ModItem.TagString := mods[i];
FModulesItem.AddObject(ModItem);
end;
FModulesItem.ExpandAll;
finally
FModulesItem.EndUpdate;
end;
end
);
FTerminate := TEvent.CreateEvent;
FRandom := TList<TRndItem>.Create;
// Create an instance of the TAuraTABFileServer. The server can be reused for multiple stream creations. [364]
FServer := TAuraTABFileServer.Create('\\COFFEE\TickData\Pepperstone');
SymbolsComboBox.Enabled := false;
ChartButton.Enabled := false;
LoadButton.Enabled := false;
FSymbols := FServer.EnumerateSymbols;
SymbolsComboBox.ProcessSignal(
FSymbols.Done.Signal,
procedure
begin
SymbolsComboBox.BeginUpdate;
try
SymbolsComboBox.Items.Clear;
SymbolsComboBox.Items.AddStrings(FSymbols.WaitFor);
if SymbolsComboBox.Items.Count > 0 then
begin
if SymbolsComboBox.ItemIndex < 0 then
SymbolsComboBox.ItemIndex := SymbolsComboBox.Items.IndexOf('GER40');
SymbolsComboBox.Enabled := true;
ChartButton.Enabled := true;
LoadButton.Enabled := true;
end;
finally
SymbolsComboBox.EndUpdate;
end;
end
);
NewWorkspace;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FSymbols.WaitFor;
FTerminate.Notify;
TaskManager.WaitFor(FProcessDone);
FRandom.Free;
end;
procedure TForm1.LayoutResized(Sender: TObject);
begin
LogMemo.Lines.Add('resize');
end;
procedure TForm1.LoadButtonClick(Sender: TObject);
begin
if SymbolsComboBox.ItemIndex < 0 then
exit;
var Layout := CurrLayout<TVertScrollBox>;
if Layout = nil then
exit;
var Stream := FServer.CreateStream(FSymbols.WaitFor[SymbolsComboBox.ItemIndex]);
var Data := TDataStreamProvider.Create<TAuraAskBidFileItem>(30000, 10000, Stream);
var path := TPath.Create(Self);
path.Parent := Layout;
path.Align := TAlignLayout.None;
path.ProcessSignal(
Data.Changed,
procedure
begin
var Prices := Data.Value;
if Prices.Count > 0 then
begin
path.BeginUpdate;
try
path.Data.Clear;
path.Data.MoveTo(PointF(path.Width - 1, Prices[0].Data.Ask));
for var i := 1 to Prices.Count - 1 do
path.Data.LineTo(PointF(path.Width - i - 1, Prices[i].Data.Ask));
finally
path.EndUpdate;
end;
end;
end
);
end;
procedure TForm1.RandomButtonClick(Sender: TObject);
begin
var Layout := CurrLayout<TVertScrollBox>;
if Layout = nil then
exit;
var rnd: TRndItem;
rnd.Stream := FServer.CreateStream(FSymbols.WaitFor[Random(Length(FSymbols.WaitFor))]);
rnd.Data := TDataStreamProvider.Create<TAuraAskBidFileItem>(3000, 1000, rnd.Stream);
rnd.Labl := TLabel.Create(Self);
rnd.Labl.Parent := Layout;
rnd.Labl.Align := TAlignLayout.None;
rnd.Labl.WordWrap := false;
rnd.Labl.Width := 300;
rnd.Labl.Text := rnd.Stream.Symbol + ' loading...';
FRandom.Add(rnd);
var Proc :=
procedure(idx: Integer)
begin
FRandom[idx]
.Labl
.ProcessSignal(
FRandom[idx].Data.Changed,
procedure
begin
var data := FRandom[idx].Data.Value;
if data.Count > 0 then
begin
var dp := data[0];
FRandom[idx].Labl.Text :=
FRandom[idx].Stream.Symbol
+ ' '
+ dp.Time.ToString
+ ' '
+ data.TotalCount.ToString
+ ' '
+ dp.Data.Ask.ToString;
end;
end);
end;
Proc(FRandom.Count - 1);
end;
procedure TForm1.TestActionExecute(Sender: TObject);
begin
TestPopup.IsOpen := TestAction.Checked;
end;
procedure TForm1.AddWorkspaceActionExecute(Sender: TObject);
begin
NewWorkspace;
end;
procedure TForm1.AlignControl(Control: TControl);
begin
var Layout := CurrLayout<TVertScrollBox>;
if Layout = nil then
exit;
Control.Parent := Layout;
Control.Width := Layout.Width;
Control.Position.Y := Layout.ChildrenRect.Bottom + 1;
Control.Anchors := [TAnchorKind.akLeft, TAnchorKind.akRight];
Control.Align := TAlignLayout.Top;
end;
procedure TForm1.ChartButtonClick(Sender: TObject);
begin
var Layout := CurrLayout<TVertScrollBox>;
if Layout = nil then
exit;
var Symbol := SelectedSymbol;
if Symbol = '' then
exit;
var currPathData := TWriteable<IObjectRef<TPathData>>.CreateWriteable.Protect;
var currLog := TWriteable<String>.CreateWriteable.Protect;
const width = 300;
var terminated := TFlag.CreateObserver(FTerminate.Signal).State;
var done :=
TaskManager.RunTask(
nil,
function: TState
begin
var Prices := TDataSeries<TAuraAskBidFileItem>.CreateDataSeries(width);
Result :=
FServer.ProcessData(
Symbol,
terminated,
TMycGenericProcessor<TArray<TDataPoint<TAuraAskBidFileItem>>>.Create(
function(const Values: TArray<TDataPoint<TAuraAskBidFileItem>>): TState
begin
Result := TState.Null;
Prices := Prices.Add(Values);
currLog.Value := Prices.TotalCount.ToString;
var PathData := TPathData.Create;
if Prices.Count > 0 then
begin
var n := Prices.Count;
PathData.MoveTo(PointF(n - 1, Prices[0].Data.Ask));
for var i := 1 to n - 1 do
PathData.LineTo(PointF(n - i - 1, Prices[i].Data.Ask));
for var i := n - 1 downto 0 do
PathData.LineTo(PointF(n - i - 1, Prices[i].Data.Bid));
end;
PathData.ClosePath;
currPathData.Value := TObjectRef<TPathData>.Create(PathData);
end
)
);
end
);
FProcessDone := TState.All([FProcessDone, done]);
var path := TPath.Create(Self);
path.Parent := Layout;
path.Align := TAlignLayout.None;
path.ProcessSignal(
currPathData.Changed,
procedure(out IsDone: Boolean)
begin
if currPathData.Value <> nil then
path.Data.Assign(currPathData.Value.Obj);
IsDone := done.IsSet;
end
);
end;
function TForm1.CurrLayout<T>: T;
begin
if TabControl.ActiveTab = nil then
exit(nil);
var Res: T := nil;
TabControl.ActiveTab.EnumControls(
function(Control: TControl): TEnumControlsResult
begin
Result := TEnumControlsResult.Continue;
if Control is T then
begin
Res := Control as T;
Result := TEnumControlsResult.Stop;
end;
end
);
Result := Res;
end;
function TForm1.ExecuteStrategy(const Symbol: String; const Processor: IMycProcessor<TArray<TDataPoint<TAskBidItem>>>): TState;
var
dataProvider: IMycConverter<TArray<TDataPoint<TAuraAskBidFileItem>>, TArray<TDataPoint<TAskBidItem>>>;
begin
var terminated := TFlag.CreateObserver(FTerminate.Signal).State;
dataProvider :=
TMycGenericConverter<TArray<TDataPoint<TAuraAskBidFileItem>>, TArray<TDataPoint<TAskBidItem>>>.Create(
function(const Values: TArray<TDataPoint<TAuraAskBidFileItem>>): TArray<TDataPoint<TAskBidItem>>
begin
SetLength(Result, Length(Values));
for var i := 0 to High(Result) do
begin
Result[i].Time := Values[i].Time;
Result[i].Data.Ask := Values[i].Data.Ask;
Result[i].Data.Bid := Values[i].Data.Bid;
end;
end
);
dataProvider.Sender.Link(Processor);
Result := FServer.ProcessData(Symbol, terminated, dataProvider);
end;
function TForm1.SelectedSymbol: String;
begin
Result := '';
if RandomBox.IsChecked then
Result := FSymbols.WaitFor[Random(Length(FSymbols.WaitFor))]
else if SymbolsComboBox.ItemIndex >= 0 then
Result := FSymbols.WaitFor[SymbolsComboBox.ItemIndex];
end;
end.