Files
MycLib/AuraTrader/MainForm.pas
T
Michael Schimmel e1159e883b Writeables revised
Read-ahead for DataStream Processing
2025-06-25 10:07:00 +02:00

290 lines
8.4 KiB
ObjectPascal

unit MainForm;
interface
uses
System.SysUtils,
System.Types,
System.UITypes,
System.Classes,
System.Variants,
System.DateUtils,
System.Generics.Collections,
FMX.Types,
FMX.Controls,
FMX.Forms,
FMX.Graphics,
FMX.Dialogs,
FMX.Controls.Presentation,
FMX.StdCtrls,
FMX.ListView.Types,
FMX.ListView.Appearances,
FMX.ListView.Adapters.Base,
FMX.ListView,
FMX.Memo.Types,
FMX.ScrollBox,
FMX.Memo,
FMX.Objects,
Myc.Futures,
Myc.Trade.DataStream,
Myc.Trade.DataPoint,
Myc.Trade.DataProvider,
Myc.Signals,
Myc.Lazy,
Myc.Signals.FMX,
Myc.TaskManager,
FMX.ListBox,
FMX.Layouts;
type
TForm1 = class(TForm)
LogMemo: TMemo;
Panel1: TPanel;
RandomButton: TButton;
Path1: TPath;
SymbolsComboBox: TComboBox;
LoadButton: TButton;
FlowLayout: TFlowLayout;
ChartButton: TButton;
StopButton: TButton;
procedure RandomButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure LoadButtonClick(Sender: TObject);
procedure ChartButtonClick(Sender: TObject);
procedure StopButtonClick(Sender: TObject);
private
const
cnt = 20;
type
TRndItem = record
Stream: IDataStream<TAskBidItem>;
Data: TMutable<TDataSeries<TAskBidItem>>;
Labl: TLabel;
end;
private
FOnEvent: TNotifyEvent;
{ Private declarations }
FServer: IDataServer<TAskBidItem>;
FSymbols: TFuture<TArray<String>>;
FRandom: TList<TRndItem>;
FTerminate: TEvent;
FLoadDone: TState;
public
{ Public declarations }
published
property OnEvent: TNotifyEvent read FOnEvent write FOnEvent;
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.StopButtonClick(Sender: TObject);
begin
FTerminate.Notify;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
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.AddIdleHandler(
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
);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FSymbols.WaitFor;
FTerminate.Notify;
TaskManager.WaitFor(FLoadDone);
Application.OnIdle := nil;
FRandom.Free;
end;
procedure TForm1.LoadButtonClick(Sender: TObject);
begin
if SymbolsComboBox.ItemIndex < 0 then
exit;
var Stream := FServer.CreateStream(FSymbols.WaitFor[SymbolsComboBox.ItemIndex]);
var Data := TDataStreamProvider.Create<TAskBidItem>(30000, 10000, Stream);
Path1.AddIdleHandler(
Data.Changed,
procedure
begin
var Prices := Data.Value;
if Prices.Count > 0 then
begin
Path1.BeginUpdate;
try
Path1.Data.Clear;
Path1.Data.MoveTo(PointF(Path1.Width - 1, Prices[0].Data.Ask));
for var i := 1 to Prices.Count - 1 do
Path1.Data.LineTo(PointF(Path1.Width - i - 1, Prices[i].Data.Ask));
finally
Path1.EndUpdate;
end;
end;
end
);
end;
procedure TForm1.RandomButtonClick(Sender: TObject);
begin
var rnd: TRndItem;
var ass := FSymbols.WaitFor;
rnd.Stream := FServer.CreateStream(ass[Random(Length(FSymbols.WaitFor))]);
rnd.Data := TDataStreamProvider.Create<TAskBidItem>(3000, 1000, rnd.Stream);
rnd.Labl := TLabel.Create(Self);
rnd.Labl.Parent := FlowLayout;
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
.AddIdleHandler(
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.ChartButtonClick(Sender: TObject);
begin
if SymbolsComboBox.ItemIndex < 0 then
exit;
var Symbol := FSymbols.WaitFor[SymbolsComboBox.ItemIndex];
var currPathData := TMutable<IObjectRef<TPathData>>.CreateProtected;
var currLog := TMutable<String>.CreateProtected;
const width = 1000;
const incsize = 100;
begin
var arr := TDataSeries<TAskBidItem>.CreateWriteable(width);
var done :=
FServer.ProcessData(
Symbol,
FTerminate.Signal,
procedure(const Values: TArray<TDataPoint<TAskBidItem>>; const Terminated: TState)
begin
arr.Add(Values);
currLog.Value := arr.TotalCount.ToString;
var PathData := TPathData.Create;
var Prices := arr;
if Prices.Count > 0 then
begin
PathData.MoveTo(PointF(Prices.Count - 1, Prices[0].Data.Ask));
for var i := 1 to Prices.Count - 1 do
PathData.LineTo(PointF(Prices.Count - i - 1, Prices[i].Data.Ask));
end;
currPathData.Value := TObjectRef<TPathData>.Create(PathData);
end
);
FLoadDone := TState.All([FLoadDone, done]);
end;
LogMemo.AddIdleHandler(currLog.Changed, procedure begin LogMemo.Lines.Add(Symbol + ': ' + currLog.Value); end);
Path1.AddIdleHandler(
currPathData.Changed,
procedure
begin
if currPathData.Value<>nil then
begin
Path1.Data.Assign( currPathData.Value.Obj );
end;
end );
(*
FLoadDone := TState.All([FLoadDone, done]);
Path1.AddIdleHandler(
curr.Changed,
procedure
begin
var Prices := curr.Value;
if Prices.Count > 0 then
begin
Path1.BeginUpdate;
try
Path1.Data.Clear;
Path1.Data.MoveTo(PointF(Path1.Width - 1, Prices[0].Data.Ask));
for var i := 1 to Prices.Count - 1 do
begin
Path1.Data.LineTo(PointF(Path1.Width - i - 1, Prices[i].Data.Ask));
end;
finally
Path1.EndUpdate;
end;
end;
end
);
*)
end;
end.