457 lines
13 KiB
ObjectPascal
457 lines
13 KiB
ObjectPascal
unit MainForm;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.Types,
|
|
System.UITypes,
|
|
System.Classes,
|
|
System.Variants,
|
|
System.DateUtils,
|
|
System.Generics.Collections,
|
|
System.Rtti,
|
|
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,
|
|
Myc.Aura.Module,
|
|
FMX.ListBox,
|
|
FMX.Layouts,
|
|
FMX.TreeView,
|
|
FMX.TabControl,
|
|
FMX.Menus,
|
|
System.ImageList,
|
|
FMX.ImgList,
|
|
System.Actions,
|
|
FMX.ActnList,
|
|
TestChartControl;
|
|
|
|
type
|
|
TForm1 = class(TForm)
|
|
LogMemo: TMemo;
|
|
MainPanel: TPanel;
|
|
SymbolsComboBox: TComboBox;
|
|
RandomBox: TCheckBox;
|
|
LoadButton: TButton;
|
|
RandomButton: TButton;
|
|
ChartButton: TButton;
|
|
StopButton: TButton;
|
|
Splitter1: TSplitter;
|
|
ActionList: TActionList;
|
|
AddWorkspaceAction: TAction;
|
|
WorkspacePanel: TPanel;
|
|
TabControl: TTabControl;
|
|
ToolBar: TToolBar;
|
|
AddWorkspaceButton: TSpeedButton;
|
|
ObjectsPanel: TPanel;
|
|
ObjectsTabControl: TTabControl;
|
|
ModulesTabItem: TTabItem;
|
|
TreeView: TTreeView;
|
|
TestButton: TSpeedButton;
|
|
TestAction: TAction;
|
|
SpeedButton1: TSpeedButton;
|
|
TestPopup: TPopup;
|
|
FlowLayout1: TFlowLayout;
|
|
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 SpeedButton1Click(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;
|
|
FApplication: IAuraApplication;
|
|
FModulesItem: TTreeViewItem;
|
|
function SelectedSymbol: String;
|
|
|
|
public
|
|
procedure NewWorkspace;
|
|
function CurrLayout: TFlowLayout;
|
|
published
|
|
property OnEvent: TNotifyEvent read FOnEvent write FOnEvent;
|
|
end;
|
|
|
|
var
|
|
Form1: TForm1;
|
|
|
|
implementation
|
|
|
|
uses
|
|
TestModule;
|
|
|
|
{$R *.fmx}
|
|
|
|
procedure TForm1.NewWorkspace;
|
|
begin
|
|
var ws: IAuraWorkspace := TMycAuraWorkspace.Create('New workspace', tmTesting);
|
|
FApplication.Workspaces.Insert(-1, ws);
|
|
|
|
var tab := TabControl.Add;
|
|
tab.Text := ws.Caption;
|
|
tab.Tag := NativeInt(ws);
|
|
|
|
var tabBtn := TSpeedButton.Create(Self);
|
|
tabBtn.Parent := tab;
|
|
tabBtn.Align := TAlignLayout.Right;
|
|
|
|
var scrollbox := TVertScrollBox.Create(Self);
|
|
scrollbox.Parent := tab;
|
|
scrollbox.Align := TAlignLayout.Client;
|
|
|
|
var flow := TFlowLayout.Create(Self);
|
|
flow.Parent := tab;
|
|
flow.Align := TAlignLayout.Client;
|
|
|
|
tab.ProcessSignal(ws.Name.Changed, procedure begin tab.Text := ws.Caption; end);
|
|
end;
|
|
|
|
procedure TForm1.StopButtonClick(Sender: TObject);
|
|
begin
|
|
FTerminate.Notify;
|
|
end;
|
|
|
|
procedure TForm1.TreeViewDblClick(Sender: TObject);
|
|
begin
|
|
var addnew := false;
|
|
|
|
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(FLoadDone);
|
|
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;
|
|
if Layout = nil then
|
|
exit;
|
|
|
|
var Stream := FServer.CreateStream(FSymbols.WaitFor[SymbolsComboBox.ItemIndex]);
|
|
var Data := TDataStreamProvider.Create<TAskBidItem>(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;
|
|
if Layout = nil then
|
|
exit;
|
|
|
|
var rnd: TRndItem;
|
|
|
|
rnd.Stream := FServer.CreateStream(FSymbols.WaitFor[Random(Length(FSymbols.WaitFor))]);
|
|
rnd.Data := TDataStreamProvider.Create<TAskBidItem>(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.ChartButtonClick(Sender: TObject);
|
|
begin
|
|
var Layout := CurrLayout;
|
|
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 done :=
|
|
TaskManager.RunTask(
|
|
nil,
|
|
function: TState
|
|
begin
|
|
var Prices := TDataSeries<TAskBidItem>.CreateWriteable(width);
|
|
Result :=
|
|
FServer.ProcessData(
|
|
Symbol,
|
|
FTerminate.Signal,
|
|
procedure(const Values: TArray<TDataPoint<TAskBidItem>>; const Terminated: TState)
|
|
begin
|
|
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
|
|
);
|
|
|
|
FLoadDone := TState.All([FLoadDone, 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: TFlowLayout;
|
|
begin
|
|
if TabControl.ActiveTab = nil then
|
|
exit(nil);
|
|
|
|
var Res: TFlowLayout := nil;
|
|
TabControl.ActiveTab.EnumControls(
|
|
function(Control: TControl): TEnumControlsResult
|
|
begin
|
|
Result := TEnumControlsResult.Continue;
|
|
if Control is TFlowLayout then
|
|
begin
|
|
Res := Control as TFlowLayout;
|
|
Result := TEnumControlsResult.Stop;
|
|
end;
|
|
end
|
|
);
|
|
|
|
Result := Res;
|
|
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.SpeedButton1Click(Sender: TObject);
|
|
begin
|
|
TestChartForm.Visible := true;
|
|
end;
|
|
|
|
end.
|