private void btnStart_Click(object sender, EventArgs e) { if (cmbStaff.SelectedIndex > -1 && lstItems.SelectedIndex > -1) { StockSession ss = new StockSession(Convert.ToInt32(lstItems.SelectedValue), Convert.ToInt32(cmbStaff.SelectedValue)); fillData(); } else { MessageBox.Show("Please select a staff member and a stock part to continue", "Missing information", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
public DataChart(Dictionary <string, List <StockDataInterface> > dataSets, StockSession session) { this.DataSets = session.Data; this.Session = session; this.Start = session.SinkFile.Start; this.End = session.SinkFile.End; // Create the surface used to draw the plot Plot = new NPlot.Swf.InteractivePlotSurface2D(); Plot.SurfacePadding = 0; Plot.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; Plot.ShowCoordinates = false; Plot.XAxis1 = new Axis(); Plot.YAxis1 = new Axis(); Plot.XAxis1.HideTickText = true; //stockPricePlot.XAxis1.NumberFormat = " h"; Plot.XAxis1.AxisColor = System.Drawing.Color.Transparent; Plot.YAxis1.HideTickText = true; Plot.YAxis1.Color = System.Drawing.Color.Transparent; Plot.PlotBackColor = GuiStyle.DARK_GREY; Plot.Canvas.HandleCreated += (sender, e) => { Plot.Canvas.BackColor = Plot.Canvas.Parent.BackColor; //SetChartData(Source); }; // Set the time axis as default this.XAxis = "Time"; this.XAxisGetValue = getExpressionEvaluator(this.XAxis); this.TimeAxis = new TradingDateTimeAxis(Plot.XAxis1); TimeAxis.StartTradingTime = new TimeSpan(9, 30, 0); TimeAxis.EndTradingTime = new TimeSpan(16, 0, 0); TimeAxis.WorldMin = (double)(Start).Ticks; TimeAxis.WorldMax = (double)(End).Ticks; Plot.XAxis1 = TimeAxis; InitPlotColors(); Plot.Refresh(); }
/// <summary> /// Pulls the processed stock data, and puts it into a format that can be fed into the ML model /// </summary> /// <param name="session">The session this processing is part of</param> /// <param name="sources">The sources to load the data from</param> /// <param name="features">The array the features should be placed in</param> /// <param name="labels">The array the expected outputs should be placed in</param> public static void PopulateData <T, U>(StockSession session, List <List <SourceList <T, U> > > sources, ref float[,] features, ref U[,] labels, MemoryScheme keep = MemoryScheme.MEM_KEEP_NONE) where T : struct, StockData where U : struct { List <DateTime> pointTimes = new List <DateTime>(); List <int> skips = new List <int>(); int numDataPoints = 0; int numFeatures = 0; int numLabels = 0; bool autoDetectFeaturesLabels = false; if (features == null) { features = new float[1, 1024]; autoDetectFeaturesLabels = true; } if (labels == null) { labels = new U[1, 1024]; autoDetectFeaturesLabels = true; } // Determine the size of the features and labels for (int srcIdx = 0; srcIdx < sources.Count; srcIdx++) { int maxPoints = 0; for (int mergeIdx = 0; mergeIdx < sources[srcIdx].Count; mergeIdx++) { int points = 0; int timeIdx = 0; foreach (var s in sources[srcIdx][mergeIdx].Source) { // Ensure the desired interval is set for the source s.Interval = sources[srcIdx][mergeIdx].Interval; // Determine how many data points are in the source int count = s.GetSourceCount(); points += count; // Record the point times for (int pnt = 0; pnt < count; pnt++) { DateTime t = (s.Start.AddSeconds(pnt * s.Interval.TotalSeconds)); if ((timeIdx >= pointTimes.Count) || (t.AddSeconds(s.Interval.TotalSeconds) < pointTimes[timeIdx])) { pointTimes.Insert(timeIdx, t); } while ((timeIdx < pointTimes.Count) && (t >= pointTimes[timeIdx])) { timeIdx++; } } } if (points > maxPoints) { maxPoints = points; } // Also get the number of features and labels that will be loaded if ((srcIdx == 0) && autoDetectFeaturesLabels) { sources[srcIdx][mergeIdx].Source[0].Load(session); sources[srcIdx][mergeIdx].Loader(sources[srcIdx][mergeIdx].Source[0][0], features, labels, 0, ref numFeatures, ref numLabels); } } numDataPoints += maxPoints; } // Create the data arrays to output if (features.GetLength(0) < numDataPoints) { features = new float[numDataPoints, numFeatures]; } if (labels.GetLength(0) < numDataPoints) { labels = new U[numDataPoints, numLabels]; } // Load the data numFeatures = 0; numLabels = 0; for (int srcIdx = 0; srcIdx < sources.Count; srcIdx++) { for (int mergeIdx = 0; mergeIdx < sources[srcIdx].Count; mergeIdx++) { int mergeFeatures = numFeatures; int mergeLabels = numLabels; int timeIdx = 0; // Load all of the data first foreach (var s in sources[srcIdx][mergeIdx].Source) { // Load the source data s.Load(session); } // Add the data to the features/labels foreach (var s in sources[srcIdx][mergeIdx].Source) { for (int pnt = 0; pnt < s.Count; pnt++) { // Add the data multiple times if it has a slower interval for (DateTime t = s.Time(pnt + 1); (timeIdx < pointTimes.Count) && (t > pointTimes[timeIdx]); timeIdx++) { mergeFeatures = numFeatures; mergeLabels = numLabels; sources[srcIdx][mergeIdx].Loader(s[pnt], features, labels, timeIdx, ref mergeFeatures, ref mergeLabels); // Check if any values are invalid for (int i = numFeatures; i < mergeFeatures; i++) { if (float.IsNaN(features[timeIdx, i])) { if (!skips.Contains(timeIdx)) { skips.Add(timeIdx); } break; } } } } } // Clear the data if desired foreach (var s in sources[srcIdx][mergeIdx].Source) { s.Clear(keep); } // Advance to the next merge location in the features/labels arrays numFeatures = mergeFeatures; numLabels = mergeLabels; } } // Remove the invalid data if (skips.Count > 0) { skips.Sort(); int skipped = 0; int src = skips[0]; int dst; var oldFeatures = features; var oldLabels = labels; features = new float[numDataPoints - skips.Count, numFeatures]; labels = new U[numDataPoints - skips.Count, numLabels]; for (dst = skips[0]; src < numDataPoints; dst++, src++) { // Check if the next copy location is skipped while ((src < numDataPoints) && (skipped < skips.Count) && (src == skips[skipped])) { skipped++; src++; } // Copy the source to the destination to remove any skipped entries Array.Copy(oldFeatures, (src * numFeatures), features, (dst * numFeatures), numFeatures); Array.Copy(oldLabels, (src * numLabels), labels, (dst * numLabels), numLabels); } } }
public static List <List <StockMLData.SourceList <T, W> > > GenerateConfig <T, U, V, W>(StockSession session, List <string> symbols, List <Tuple <TimeSpan, StockMLData.SourceList <T, W> .DataLoader> > intervals, StockDataSetDerived <T, U, V> .StockDataCreator creator, StockDataSetDerived <T, U, V> .StockProcessingStateAccessor getState) where T : struct, StockData where U : struct, StockData where W : struct { var dataSets = new List <Dictionary <string, List <StockDataSet <T> > > >(); foreach (var i in intervals) { var set = StockDataSetDerived <T, U, V> .Derive(session.SourceFile.GetSegments <U>(), session.SinkFile, creator, getState); dataSets.Add(StockDataSetDerived <T, U, V> .CastToBase(set)); } var sources = new List <List <StockMLData.SourceList <T, W> > >(); foreach (var s in symbols) { var l = new List <StockMLData.SourceList <T, W> >(); for (int i = 0; i < intervals.Count; i++) { l.Add(new StockMLData.SourceList <T, W>() { Source = dataSets[i][s], Interval = intervals[i].Item1, Loader = intervals[i].Item2 }); } sources.Add(l); } return(sources); }
public DataChartGui(Dictionary <string, List <StockDataSet <T> > > dataSets, StockDataFile file, StockSession session) : base(dataSets, file, session) { GuiPanel = new Panel(); GuiPanel.Size = new System.Drawing.Size(600, 300); GuiPanel.AutoSize = true; GuiPanel.BackColor = GuiStyle.BACKGROUND_COLOR; GuiPanel.BorderStyle = BorderStyle.FixedSingle; EventHandler resizeHandler = (sender, e) => { GuiPanel.Size = new System.Drawing.Size(GuiPanel.Parent.Width - 50, GuiPanel.Height); SymbolTextbox.Location = new System.Drawing.Point((GuiPanel.Width / 2) - (SymbolTextbox.Width / 2), 5); int intervalBtnPos = SymbolTextbox.Right + 5; foreach (var pair in IntervalButtons) { pair.Item1.Location = new Point(intervalBtnPos, SymbolTextbox.Top); intervalBtnPos = pair.Item1.Right + 5; } XAxisTextbox.Location = new System.Drawing.Point((GuiPanel.Width / 2) - (SymbolTextbox.Width / 2), GuiPanel.Height - XAxisTextbox.Height - 10); }; GuiPanel.ParentChanged += (sender, e) => { GuiPanel.Parent.Resize += resizeHandler; resizeHandler(sender, e); }; // Create the symbol search textbox SymbolTextbox = new TextBox(); SymbolTextbox.BackColor = GuiStyle.DARK_GREY; SymbolTextbox.ForeColor = GuiStyle.TEXT_COLOR; SymbolTextbox.AutoCompleteMode = AutoCompleteMode.Suggest; SymbolTextbox.AutoCompleteSource = AutoCompleteSource.CustomSource; SymbolTextbox.TextChanged += (sender, e) => { TextBox t = (TextBox)sender; if (t.Text.Length >= 1) { // Get the available symbols matching the search string AutoCompleteStringCollection collection = new AutoCompleteStringCollection(); collection.AddRange(SuggestSymbols(t.Text)); t.AutoCompleteCustomSource = collection; } }; SymbolTextbox.KeyDown += (s, eventArgs) => { if (eventArgs.KeyCode == Keys.Enter) { SetPlotLineSymbol(SymbolTextbox.Text); SetSymbolInterval(); this.Refresh(); } }; GuiPanel.Controls.Add(SymbolTextbox); XAxisTextbox = SymbolTextbox.Clone(); XAxisTextbox.Text = "Time"; XAxisTextbox.TextChanged += (sender, e) => { TextBox t = (TextBox)sender; if (t.Text.Length >= 1) { // Get the available symbols matching the search string AutoCompleteStringCollection collection = new AutoCompleteStringCollection(); collection.AddRange(SuggestExpressions(t.Text)); t.AutoCompleteCustomSource = collection; } }; XAxisTextbox.KeyDown += (s, eventArgs) => { if (eventArgs.KeyCode == Keys.Enter) { try { SetXAxis(XAxisTextbox.Text); ErrorMessageLabel.Visible = false; } catch (Exception ex) { ErrorMessageLabel.Text = ex.ToString(); ErrorMessageLabel.Visible = true; } } }; GuiPanel.Controls.Add(XAxisTextbox); XAxisValue = new Label(); XAxisValue.Font = GuiStyle.Font; XAxisValue.ForeColor = GuiStyle.TEXT_COLOR; XAxisTextbox.LocationChanged += (sender, e) => { XAxisValue.Location = new System.Drawing.Point(XAxisTextbox.Right + 5, XAxisTextbox.Top); }; XAxisValue.Size = new System.Drawing.Size(250, XAxisValue.Height); XAxisValue.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; GuiPanel.Controls.Add(XAxisValue); AddPlotButton = new PictureBox(); AddPlotButton.Image = System.Drawing.Bitmap.FromFile("Content/GUI/Button_Add.png"); AddPlotButton.Click += (sender, e) => { AddPlotLine(); }; GuiPanel.Controls.Add(AddPlotButton); // Add the interactive chart controls Plot.AddInteraction(new PlotDrag(true, true)); Plot.AddInteraction(new HoverInteraction(this)); var plotCanvas = base.Canvas; GuiPanel.Resize += (sender, e) => { plotCanvas.Size = new System.Drawing.Size(GuiPanel.Width - 250, GuiPanel.Height - 75); plotCanvas.Location = new System.Drawing.Point(GuiPanel.Width - plotCanvas.Width - 5, (GuiPanel.Height - plotCanvas.Height) / 2); }; GuiPanel.Controls.Add(plotCanvas); ErrorMessageLabel = new Label(); ErrorMessageLabel.ForeColor = GuiStyle.PRICE_COLOR_NEGATIVE; ErrorMessageLabel.BackColor = GuiStyle.DARK_GREY; ErrorMessageLabel.AutoSize = false; ErrorMessageLabel.Visible = false; ErrorMessageLabel.Width = plotCanvas.Width - 10; ErrorMessageLabel.Height = plotCanvas.Height - 10; plotCanvas.Resize += (sender, e) => { ErrorMessageLabel.Width = plotCanvas.Width - 10; ErrorMessageLabel.Height = plotCanvas.Height - 10; }; ErrorMessageLabel.Location = new Point(plotCanvas.Left + 5, plotCanvas.Bottom - ErrorMessageLabel.Height - 5); plotCanvas.LocationChanged += (sender, e) => { ErrorMessageLabel.Location = new Point(plotCanvas.Left + 5, plotCanvas.Top + 5); }; GuiPanel.Controls.Add(ErrorMessageLabel); ErrorMessageLabel.BringToFront(); foreach (var pair in IntervalButtons) { pair.Item1.SetImage(GuiButton.ButtonImage.GREEN_TRANSPARENT); pair.Item1.Click += (sender, e) => { // Update the selected button (first) foreach (var p in IntervalButtons) { p.Item1.SetImage(GuiButton.ButtonImage.GREEN_TRANSPARENT); } pair.Item1.SetImage(GuiButton.ButtonImage.GREEN_WHITE); // Set the new interval SetSymbolInterval(); Refresh(); }; GuiPanel.Controls.Add(pair.Item1); } IntervalButtons[0].Item1.SetImage(GuiButton.ButtonImage.GREEN_WHITE); // Start with one line AddPlotLine(); }
public DataChartGui(Dictionary <string, List <StockDataInterface> > dataSets, StockSession session) : base(dataSets, session) { GuiPanel = new Panel(); GuiPanel.Size = new System.Drawing.Size(600, 300); GuiPanel.AutoSize = false; GuiPanel.BackColor = GuiStyle.BACKGROUND_COLOR; GuiPanel.BorderStyle = BorderStyle.FixedSingle; EventHandler resizeHandler = (sender, e) => { GuiPanel.Size = new System.Drawing.Size(GuiPanel.Parent.Width - 50, GuiPanel.Parent.Height - GuiPanel.Top - 50); }; GuiPanel.ParentChanged += (sender, e) => { GuiPanel.Parent.Resize += resizeHandler; resizeHandler(sender, e); }; GuiPanel.Resize += (sender, e) => { SymbolTextbox.Location = new System.Drawing.Point((GuiPanel.Width / 2) - (SymbolTextbox.Width / 2), 5); SymbolNextButton.Location = new Point(SymbolTextbox.Right + 5, SymbolTextbox.Top); SymbolPrevButton.Location = new Point(SymbolTextbox.Left - 5 - SymbolPrevButton.Width, SymbolTextbox.Top); SaveImageButton.Location = new System.Drawing.Point(GuiPanel.Width - (SaveImageButton.Width) - 5, 5); ChartDescriptionTextbox.Location = new Point(SymbolNextButton.Right + 15, SymbolTextbox.Top); ChartDescriptionTextbox.Size = new Size((SaveImageButton.Left - ChartDescriptionTextbox.Left) - 15, ChartDescriptionTextbox.Height); XAxisTextbox.Location = new System.Drawing.Point((GuiPanel.Width / 2) - (SymbolTextbox.Width / 2), GuiPanel.Height - XAxisTextbox.Height - 10); }; // Create the symbol search textbox SymbolTextbox = new TextBox(); SymbolTextbox.BackColor = GuiStyle.DARK_GREY; SymbolTextbox.ForeColor = GuiStyle.TEXT_COLOR; #if false SymbolTextbox.AutoCompleteMode = AutoCompleteMode.Suggest; SymbolTextbox.AutoCompleteSource = AutoCompleteSource.CustomSource; SymbolTextbox.TextChanged += (sender, e) => { TextBox t = (TextBox)sender; if (t.Text.Length >= 1) { // Get the available symbols matching the search string AutoCompleteStringCollection collection = new AutoCompleteStringCollection(); collection.AddRange(SuggestSymbols(t.Text)); t.AutoCompleteCustomSource = collection; } }; #endif SymbolTextbox.KeyDown += (s, eventArgs) => { if (eventArgs.KeyCode == Keys.Enter) { SetPlotLineSymbol(SymbolTextbox.Text); this.Refresh(); } }; GuiPanel.Controls.Add(SymbolTextbox); // Create the next and previous arrows for the symbol list SymbolNextButton = new PictureBox(); SymbolNextButton.Image = System.Drawing.Bitmap.FromFile("Content/GUI/ArrowRight.png"); SymbolNextButton.Size = SymbolNextButton.Image.Size; SymbolNextButton.Click += (sender, e) => { var allSymbols = DataSets.Keys.ToList(); if (allSymbols.Count > 0) { SetPlotLineSymbol(allSymbols[Math.Min(allSymbols.IndexOf(SymbolTextbox.Text) + 1, allSymbols.Count - 1)]); this.Refresh(); } }; GuiPanel.Controls.Add(SymbolNextButton); SymbolPrevButton = new PictureBox(); SymbolPrevButton.Image = System.Drawing.Bitmap.FromFile("Content/GUI/ArrowRight.png"); SymbolPrevButton.Image.RotateFlip(RotateFlipType.RotateNoneFlipX); SymbolPrevButton.Size = SymbolPrevButton.Image.Size; SymbolPrevButton.Click += (sender, e) => { var allSymbols = DataSets.Keys.ToList(); if (allSymbols.Count > 0) { SetPlotLineSymbol(allSymbols[Math.Max(allSymbols.IndexOf(SymbolTextbox.Text) - 1, 0)]); this.Refresh(); } }; GuiPanel.Controls.Add(SymbolPrevButton); ChartDescriptionTextbox = SymbolTextbox.Clone(); GuiPanel.Controls.Add(ChartDescriptionTextbox); XAxisTextbox = SymbolTextbox.Clone(); XAxisTextbox.Text = "Time"; XAxisTextbox.TextChanged += (sender, e) => { TextBox t = (TextBox)sender; if (t.Text.Length >= 1) { // Get the available symbols matching the search string AutoCompleteStringCollection collection = new AutoCompleteStringCollection(); collection.AddRange(SuggestExpressions(t.Text)); t.AutoCompleteCustomSource = collection; } }; XAxisTextbox.KeyDown += (s, eventArgs) => { if (eventArgs.KeyCode == Keys.Enter) { try { SetXAxis(XAxisTextbox.Text); ErrorMessageLabel.Visible = false; } catch (Exception ex) { ErrorMessageLabel.Text = ex.ToString(); ErrorMessageLabel.Visible = true; } } }; GuiPanel.Controls.Add(XAxisTextbox); XAxisValue = new Label(); XAxisValue.Font = GuiStyle.Font; XAxisValue.ForeColor = GuiStyle.TEXT_COLOR; XAxisTextbox.LocationChanged += (sender, e) => { XAxisValue.Location = new System.Drawing.Point(XAxisTextbox.Right + 5, XAxisTextbox.Top); }; XAxisValue.Size = new System.Drawing.Size(250, XAxisValue.Height); XAxisValue.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; GuiPanel.Controls.Add(XAxisValue); AddPlotButton = new PictureBox(); AddPlotButton.Image = System.Drawing.Bitmap.FromFile("Content/GUI/Button_Add.png"); AddPlotButton.Click += (sender, e) => { AddPlotLine(); }; GuiPanel.Controls.Add(AddPlotButton); // Add the interactive chart controls Plot.AddInteraction(new PlotDrag(true, true)); Plot.AddInteraction(Hover = new HoverInteraction(this)); LineDrawer = new LineInteraction(this); Plot.AddInteraction(LineDrawer); var plotCanvas = base.Canvas; GuiPanel.Resize += (sender, e) => { if ((GuiPanel.Width > 250) && (GuiPanel.Height > 75)) { plotCanvas.Size = new System.Drawing.Size(GuiPanel.Width - 250, GuiPanel.Height - 75); plotCanvas.Location = new System.Drawing.Point(GuiPanel.Width - plotCanvas.Width - 5, (GuiPanel.Height - plotCanvas.Height) / 2); } }; GuiPanel.Controls.Add(plotCanvas); ErrorMessageLabel = new Label(); ErrorMessageLabel.ForeColor = GuiStyle.PRICE_COLOR_NEGATIVE; ErrorMessageLabel.BackColor = GuiStyle.DARK_GREY; ErrorMessageLabel.AutoSize = false; ErrorMessageLabel.Visible = false; ErrorMessageLabel.Width = plotCanvas.Width - 10; ErrorMessageLabel.Height = plotCanvas.Height - 10; plotCanvas.Resize += (sender, e) => { ErrorMessageLabel.Width = plotCanvas.Width - 10; ErrorMessageLabel.Height = plotCanvas.Height - 10; }; ErrorMessageLabel.Location = new Point(plotCanvas.Left + 5, plotCanvas.Bottom - ErrorMessageLabel.Height - 5); plotCanvas.LocationChanged += (sender, e) => { ErrorMessageLabel.Location = new Point(plotCanvas.Left + 5, plotCanvas.Top + 5); }; GuiPanel.Controls.Add(ErrorMessageLabel); ErrorMessageLabel.BringToFront(); // Add the button to reload the session SaveImageButton = new GuiButton("Save Img"); SaveImageButton.Location = new System.Drawing.Point(GuiPanel.Width - (SaveImageButton.Width / 2) - 5, 5); SaveImageButton.Click += (sender, e) => { var saveDiag = new System.Windows.Forms.SaveFileDialog(); saveDiag.Title = "Save chart image..."; saveDiag.FileName = SymbolTextbox.Text + "_" + ChartDescriptionTextbox.Text + ".png"; if (saveDiag.ShowDialog() == System.Windows.Forms.DialogResult.OK) { SaveImage(saveDiag.FileName); } }; GuiPanel.Controls.Add(SaveImageButton); ChartChanged += () => { XAxisTextbox.Text = XAxis; foreach (var l in Lines) { if (!l.Locked) { SymbolTextbox.Text = l.Symbol; break; } } }; // Start with one line AddPlotLine("Price"); // Reload the chart when the session is reloaded session.OnReload += ReloadData; }
public DataChart(Dictionary <string, List <StockDataSet <T> > > dataSets, StockDataFile file, StockSession session) { this.DataSets = dataSets; this.File = file; this.Session = session; this.Start = File.Start; this.End = File.End; // Load the dummy data var dummySrc = DataSets.First().Value[0]; dummySrc.Load(session); DataSets.First().Value[1].Load(session); // Work-around so that the processing state is reset if this symbol is loaded again in the future DummyData = new StockDataSet <T>(dummySrc.Symbol, dummySrc.Start, dummySrc.File); DummyData.DataSet.Initialize(dummySrc.DataSet.InternalArray); // Create the surface used to draw the plot Plot = new NPlot.Swf.InteractivePlotSurface2D(); Plot.SurfacePadding = 0; Plot.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; Plot.ShowCoordinates = false; Plot.XAxis1 = new Axis(); Plot.YAxis1 = new Axis(); Plot.XAxis1.HideTickText = true; //stockPricePlot.XAxis1.NumberFormat = " h"; Plot.XAxis1.AxisColor = System.Drawing.Color.Transparent; Plot.YAxis1.HideTickText = true; Plot.YAxis1.Color = System.Drawing.Color.Transparent; Plot.PlotBackColor = GuiStyle.DARK_GREY; Plot.Canvas.HandleCreated += (sender, e) => { Plot.Canvas.BackColor = Plot.Canvas.Parent.BackColor; //SetChartData(Source); }; // Set the time axis as default this.XAxis = "Time"; this.XAxisGetValue = getExpressionEvaluator(this.XAxis); this.TimeAxis = new TradingDateTimeAxis(Plot.XAxis1); TimeAxis.StartTradingTime = new TimeSpan(9, 30, 0); TimeAxis.EndTradingTime = new TimeSpan(16, 0, 0); TimeAxis.WorldMin = (double)(file.Start).Ticks; TimeAxis.WorldMax = (double)(file.End).Ticks; Plot.XAxis1 = TimeAxis; Plot.Refresh(); }