//+------------------------------------------------------------------+ //| np_graphics.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, MetaQuotes Ltd." #property link "https://www.mql5.com" #include #include "np.mqh" //--- namespace np { //+------------------------------------------------------------------+ //| Plot a single matrix where each column is treated as a curve | //| The X-axis defaults to the 1-based index of the row number | //+------------------------------------------------------------------+ template CGraphic* plotMatrix(matrix&in, string plot_name, string legend="col", string x_axis_label="x_axis", string y_axis_label = "y_axis", bool points_fill = true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true, int linewidth=5, ENUM_CURVE_TYPE curve_type=CURVE_LINES) { // Initialize canvas object dynamically CGraphic* graph = new CGraphic(); // Prepare chart display properties ChartRedraw(chart_id); ChartSetInteger(chart_id, CHART_SHOW, chart_show); // Create the visual container on the designated chart/subwindow if(!graph.Create(chart_id, plot_name, sub_win, x1, y1, x2, y2)) { delete graph; Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } int cols = (int)in.Cols(), rows = (int)in.Rows(); string colnames[]; // Split the comma-separated legend string into individual curve names int split = StringSplit(legend, StringGetCharacter(",", 0), colnames); if(split < cols) Print(__FUNCTION__, " WARNING: Invalid legend labels "); T x[], y[]; ArrayResize(x, rows); // Populate X-axis values sequentially from 1 up to the total number of rows for(int i=0; i CGraphic* plotMatrices(matrix&x, matrix&y, string plot_name, bool by_column = false, string x_axis_label="x_axis", string y_axis_label = "y_axis", string legend="col", ENUM_CURVE_TYPE curve_type = CURVE_LINES, int line_width = 5, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true) { // Verify dimensionality match depending on the tracking direction (row vs column) if((by_column && x.Rows()!=y.Rows()) || (!by_column && x.Cols()!=y.Cols())) { Print(__FUNCTION__, " invalid inputs "); return NULL; } CGraphic* graph = new CGraphic(); ChartRedraw(chart_id); ChartSetInteger(chart_id, CHART_SHOW, chart_show); if(!graph.Create(chart_id, plot_name, sub_win, x1, y1, x2, y2)) { delete graph; Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } int cols = (int)y.Cols(), rows = (int)y.Rows(); string colnames[]; // Split legend string for labels int split = StringSplit(legend, StringGetCharacter(",", 0), colnames); if((by_column && split void plotmatrices(matrix&x, matrix&y, string plot_name, bool by_column = false, string x_axis_label="x_axis", string y_axis_label = "y_axis", string legend="col", ENUM_CURVE_TYPE curve_type = CURVE_LINES, int line_width = 5, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true, int duration = 20) { // Generate the plot using the primary drawing function CGraphic *plot = plotMatrices(x, y, plot_name, by_column, x_axis_label, y_axis_label, legend, curve_type, line_width, chart_id, sub_win, x1, y1, x2, y2, chart_show); if(plot!=NULL) { Sleep(duration*1000); // Keep graphic active for the assigned runtime duration plot.Destroy(); // Clear visual objects from the framework delete plot; // Deallocate memory ChartRedraw(chart_id); // Update user workspace UI return; } } //+------------------------------------------------------------------+ //| Variation of plotMatrices with custom lines width scaling | //| Features CURVE_POINTS_AND_LINES as its default drawing strategy | //+------------------------------------------------------------------+ template CGraphic* plotMatrices(matrix&x, matrix&y, string plot_name, bool by_column = false, string x_axis_label="x_axis", string y_axis_label = "y_axis", string legend="col", bool fill_points = true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true) { if((by_column && x.Rows()!=y.Rows()) || (!by_column && x.Cols()!=y.Cols())) { Print(__FUNCTION__, " invalid inputs "); return NULL; } CGraphic* graph = new CGraphic(); ChartRedraw(chart_id); ChartSetInteger(chart_id, CHART_SHOW, chart_show); if(!graph.Create(chart_id, plot_name, sub_win, x1, y1, x2, y2)) { delete graph; Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } int cols = (int)y.Cols(), rows = (int)y.Rows(); string colnames[]; int split = StringSplit(legend, StringGetCharacter(",", 0), colnames); if((by_column && split void plotmatrices(matrix&x, matrix&y, string plot_name, bool by_column = false, string x_axis_label="x_axis", string y_axis_label = "y_axis", string legend="col", bool fill_points=true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true, int duration = 20) { CGraphic *plot = plotMatrices(x, y, plot_name, by_column, x_axis_label, y_axis_label, legend, fill_points, chart_id, sub_win, x1, y1, x2, y2, chart_show); if(plot!=NULL) { Sleep(duration*1000); plot.Destroy(); delete plot; ChartRedraw(chart_id); return; } } //+------------------------------------------------------------------+ //| Plots a single shared X vector against an array of Y vectors | //+------------------------------------------------------------------+ CGraphic* plotXYs(vector&x, vector&y[], string& curve_names[], string plot_name, string x_axis_label="x_axis", string y_axis_label = "y_axis", bool points_fill = true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=750, int y2=500, bool chart_show=true, int line_width = 1, ENUM_CURVE_TYPE curve_type=CURVE_POINTS_AND_LINES) { double xa[]; double ya[]; CGraphic* graph = new CGraphic(); ChartRedraw(chart_id); ChartSetInteger(chart_id, CHART_SHOW, chart_show); // Enforce mapping condition: Every vector element array slice must map directly to a layout string if(y.Size() != curve_names.Size() || !graph.Create(chart_id, plot_name, sub_win, x1, y1, x2, y2)) { delete graph; Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } CColorGenerator generator; for(uint i = 0; i CGraphic* plotXY(vector&x, vector&y, string plot_name, string x_axis_label="x_axis", string y_axis_label = "y_axis", bool points_fill = true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=750, int y2=500, bool chart_show=true, int line_width = 1, ENUM_CURVE_TYPE curve_type=CURVE_POINTS_AND_LINES) { T xa[]; T ya[]; // Verify coordinate structure sizes align symmetrically before processing data arrays if(x.Size()!=y.Size() || !np::vecAsArray(x, xa) || !np::vecAsArray(y, ya)) { Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } CGraphic* graph = new CGraphic(); ChartRedraw(chart_id); ChartSetInteger(chart_id, CHART_SHOW, chart_show); if(!graph.Create(chart_id, plot_name, sub_win, x1, y1, x2, y2)) { delete graph; Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } CColorGenerator generator; CCurve* newcurve = graph.CurveAdd(xa, ya, generator.Next(), curve_type, plot_name); newcurve.PointsFill(points_fill); newcurve.LinesWidth(line_width); graph.HistoryNameWidth(200); graph.HistoryNameSize(15); graph.XAxis().Name(x_axis_label); graph.XAxis().NameSize(15); graph.XAxis().ValuesSize(15); graph.YAxis().Name(y_axis_label); graph.YAxis().NameSize(15); graph.YAxis().ValuesSize(15); graph.FontSet("Lucida Console", 15); graph.CurvePlotAll(); graph.Update(); return graph; } //+------------------------------------------------------------------+ //| Time-limited display function wrapper for a basic XY line plot | //+------------------------------------------------------------------+ template void plotxy(vector&x, vector&y, string plot_name, string x_axis_label="x_axis", string y_axis_label = "y_axis", bool points_fill = true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=750, int y2=500, bool chart_show=true, int line_width = 1, ENUM_CURVE_TYPE curve_type=CURVE_POINTS_AND_LINES, int duration = 20) { CGraphic *plot = plotXY(x, y, plot_name, x_axis_label, y_axis_label, points_fill, chart_id, sub_win, x1, y1, x2, y2, chart_show, line_width, curve_type); if(plot!=NULL) { Sleep(duration*1000); plot.Destroy(); delete plot; ChartRedraw(chart_id); return; } } //+------------------------------------------------------------------+ //| Generates a scatterplot (only rendering independent point markers)| //+------------------------------------------------------------------+ template CGraphic* scatterplot(vector&x, vector&y, string plot_name, string x_axis_label="x_axis", string y_axis_label = "y_axis", bool points_fill = true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true) { T xa[]; T ya[]; if(x.Size()!=y.Size() || !np::vecAsArray(x, xa) || !np::vecAsArray(y, ya)) { Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } CGraphic* graph = new CGraphic(); ChartRedraw(chart_id); ChartSetInteger(chart_id, CHART_SHOW, chart_show); if(!graph.Create(chart_id, plot_name, sub_win, x1, y1, x2, y2)) { delete graph; Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } CColorGenerator generator; // Explicitly uses CURVE_POINTS to exclude connecting lines completely CCurve* newcurve = graph.CurveAdd(xa, ya, generator.Next(), CURVE_POINTS, plot_name); newcurve.PointsFill(points_fill); graph.XAxis().Name(x_axis_label); graph.XAxis().NameSize(15); graph.XAxis().ValuesSize(15); graph.YAxis().Name(y_axis_label); graph.YAxis().NameSize(15); graph.YAxis().ValuesSize(15); graph.FontSet("Lucida Console", 18); graph.CurvePlotAll(); graph.Update(); return graph; } //+------------------------------------------------------------------+ //| Time-limited display function wrapper for a scatter plot canvas | //+------------------------------------------------------------------+ template void scatter_plot(vector&x, vector&y, string plot_name, string x_axis_label="x_axis", string y_axis_label = "y_axis", bool points_fill = true, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true, int duration=20) { CGraphic *plot = scatterplot(x, y, plot_name, x_axis_label, y_axis_label, points_fill, chart_id, sub_win, x1, y1, x2, y2, chart_show); if(plot!=NULL) { Sleep(duration*1000); plot.Destroy(); delete plot; ChartRedraw(chart_id); return; } } //+------------------------------------------------------------------+ //| Processes a vector dataset to generate a structured Histogram plot| //+------------------------------------------------------------------+ template CGraphic* histogram_plot(vector&x, ulong num_bins, string plot_name, string x_axis_label="x_axis", string y_axis_label = "y_axis", int histogram_width = 6, long chart_id=0, int sub_win=0, int x1=30, int y1=40, int x2=550, int y2=310, bool chart_show=true) { T xa[]; T ya[]; // Ensure statistical variance is valid; checking that dataset size has sufficient volume per bin if(x.Size() < num_bins * 10) { Print(__FUNCTION__, " invalid parameter: num_bins. Invalid relative to size of dataset"); return NULL; } // Calculate step metrics for assigning data points to bins double range = x.Max() - x.Min(); double width = range / double(num_bins); if(width == 0) { Print(__FUNCTION__, " width is zero "); return NULL; } ArrayResize(xa, (int)num_bins); ArrayResize(ya, (int)num_bins); // Calculate and establish the center position coordinate for each bin interval for(ulong i=0; i= num_bins) ind = num_bins - 1; // Safeguard boundary overflow anomalies ++ya[ind]; } CGraphic* graph = new CGraphic(); ChartRedraw(chart_id); ChartSetInteger(chart_id, CHART_SHOW, chart_show); if(!graph.Create(chart_id, plot_name, sub_win, x1, y1, x2, y2)) { delete graph; Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError()); return NULL; } CColorGenerator generator; // Render values specifically formatted using CURVE_HISTOGRAM visual blocks CCurve* newcurve = graph.CurveAdd(xa, ya, generator.Next(), CURVE_HISTOGRAM, plot_name); newcurve.HistogramWidth(histogram_width); graph.XAxis().Name(x_axis_label); graph.XAxis().NameSize(15); graph.XAxis().ValuesSize(15); graph.YAxis().Name(y_axis_label); graph.YAxis().NameSize(15); graph.YAxis().ValuesSize(15); graph.FontSet("Lucida Console", 18); graph.CurvePlotAll(); graph.Update(); return graph; } }