528 lines
21 KiB
MQL5
528 lines
21 KiB
MQL5
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| np_graphics.mqh |
|
||
|
|
//| Copyright 2025, MetaQuotes Ltd. |
|
||
|
|
//| https://www.mql5.com |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||
|
|
#property link "https://www.mql5.com"
|
||
|
|
#include<Graphics\Graphic.mqh>
|
||
|
|
#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<typename T>
|
||
|
|
CGraphic* plotMatrix(matrix<T>&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<rows; ++i)
|
||
|
|
x[i] = T(i+1);
|
||
|
|
|
||
|
|
CColorGenerator generator;
|
||
|
|
|
||
|
|
// Iterate over each column of the matrix to plot it as a separate curve
|
||
|
|
for(int i=0; i<cols; ++i)
|
||
|
|
{
|
||
|
|
// Extract the column data into a standard MQL array
|
||
|
|
if(!np::vecAsArray(in.Col(i), y))
|
||
|
|
{
|
||
|
|
Print(__FUNCTION__, " error ", GetLastError());
|
||
|
|
ObjectDelete(chart_id, plot_name);
|
||
|
|
delete graph;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Determine the label name for the current curve and add it to the graph
|
||
|
|
CCurve* newcurve = graph.CurveAdd(x, y, generator.Next(), curve_type, split<cols ? legend+string(i+1) : colnames[i]);
|
||
|
|
newcurve.PointsFill(points_fill);
|
||
|
|
newcurve.LinesWidth(linewidth);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Configure Axis labels, fonts, and render the complete plot
|
||
|
|
graph.XAxis().Name(x_axis_label);
|
||
|
|
graph.XAxis().NameSize(13);
|
||
|
|
graph.YAxis().Name(y_axis_label);
|
||
|
|
graph.YAxis().NameSize(13);
|
||
|
|
graph.FontSet("Lucida Console", 13);
|
||
|
|
graph.CurvePlotAll();
|
||
|
|
graph.Update();
|
||
|
|
|
||
|
|
return graph;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Plot matching dimensions from two matrices (X and Y coordinates) |
|
||
|
|
//| Allows plotting either by columns or by rows |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
template<typename T>
|
||
|
|
CGraphic* plotMatrices(matrix<T>&x, matrix<T>&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<cols) || (!by_column && split<rows))
|
||
|
|
Print(__FUNCTION__, " WARNING: Invalid legend labels ");
|
||
|
|
|
||
|
|
T xx[], yy[];
|
||
|
|
CColorGenerator generator;
|
||
|
|
int ncurves = (by_column) ? cols : rows;
|
||
|
|
|
||
|
|
// Loop through curves extraction from rows or columns
|
||
|
|
for(int i=0; i<ncurves; ++i)
|
||
|
|
{
|
||
|
|
// Dynamically extract data depending on tracking configuration
|
||
|
|
if((by_column && (!np::vecAsArray(y.Col(i), yy) || !np::vecAsArray(x.Col(i), xx))) ||
|
||
|
|
(!by_column && (!np::vecAsArray(y.Row(i), yy) || !np::vecAsArray(x.Row(i), xx))))
|
||
|
|
{
|
||
|
|
Print(__FUNCTION__, " error ", GetLastError());
|
||
|
|
ObjectDelete(chart_id, plot_name);
|
||
|
|
delete graph;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add curve data with custom properties
|
||
|
|
CCurve* newcurve = graph.CurveAdd(xx, yy, generator.Next(), curve_type, ((by_column && split<cols) || (!by_column && split<rows)) ? legend+string(i+1) : colnames[i]);
|
||
|
|
newcurve.LinesWidth(line_width);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Complete plot design rules
|
||
|
|
graph.XAxis().Name(x_axis_label);
|
||
|
|
graph.XAxis().NameSize(13);
|
||
|
|
graph.YAxis().Name(y_axis_label);
|
||
|
|
graph.YAxis().NameSize(13);
|
||
|
|
graph.FontSet("Lucida Console", 13);
|
||
|
|
graph.CurvePlotAll();
|
||
|
|
graph.Update();
|
||
|
|
|
||
|
|
return graph;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Renders line matrices then automatically removes them after |
|
||
|
|
//| a specified duration (timed display) |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
template<typename T>
|
||
|
|
void plotmatrices(matrix<T>&x, matrix<T>&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<typename T>
|
||
|
|
CGraphic* plotMatrices(matrix<T>&x, matrix<T>&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<cols) || (!by_column && split<rows))
|
||
|
|
Print(__FUNCTION__, " WARNING: Invalid legend labels ");
|
||
|
|
|
||
|
|
T xx[], yy[];
|
||
|
|
CColorGenerator generator;
|
||
|
|
int ncurves = (by_column) ? cols : rows;
|
||
|
|
for(int i=0; i<ncurves; ++i)
|
||
|
|
{
|
||
|
|
if((by_column && (!np::vecAsArray(y.Col(i), yy) || !np::vecAsArray(x.Col(i), xx))) ||
|
||
|
|
(!by_column && (!np::vecAsArray(y.Row(i), yy) || !np::vecAsArray(x.Row(i), xx))))
|
||
|
|
{
|
||
|
|
Print(__FUNCTION__, " error ", GetLastError());
|
||
|
|
ObjectDelete(chart_id, plot_name);
|
||
|
|
delete graph;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Plots using point markers combined with structured path lines
|
||
|
|
CCurve* newcurve = graph.CurveAdd(xx, yy, generator.Next(), CURVE_POINTS_AND_LINES, ((by_column && split<cols) || (!by_column && split<rows)) ? legend+string(i+1) : colnames[i]);
|
||
|
|
newcurve.PointsFill(fill_points);
|
||
|
|
newcurve.LinesWidth(ncurves-i); // Dynamic calculation: Earlier lines appear bolder than subsequent tracks
|
||
|
|
}
|
||
|
|
|
||
|
|
graph.XAxis().Name(x_axis_label);
|
||
|
|
graph.XAxis().NameSize(13);
|
||
|
|
graph.YAxis().Name(y_axis_label);
|
||
|
|
graph.YAxis().NameSize(13);
|
||
|
|
graph.FontSet("Lucida Console", 13);
|
||
|
|
graph.CurvePlotAll();
|
||
|
|
graph.Update();
|
||
|
|
|
||
|
|
return graph;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Temporary mixed point/line plot displaying matrices for a time |
|
||
|
|
//| window before automated internal deletion |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
template<typename T>
|
||
|
|
void plotmatrices(matrix<T>&x, matrix<T>&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<y.Size(); ++i)
|
||
|
|
{
|
||
|
|
if(!np::vecAsArray(y[i], ya))
|
||
|
|
{
|
||
|
|
delete graph;
|
||
|
|
Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError());
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Map the base X vector to array format up to the boundary depth matching current Y slice size
|
||
|
|
if(!np::vecAsArray(x, xa, 0, (int)ya.Size()))
|
||
|
|
{
|
||
|
|
delete graph;
|
||
|
|
Print(__FUNCTION__, " Failed to Create graphical object on the Main chart Err ", GetLastError());
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
CCurve* newcurve = graph.CurveAdd(xa, ya, generator.Next(), curve_type, curve_names[i]);
|
||
|
|
newcurve.LinesWidth(line_width);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Format typography and layout spaces for enhanced legend identification details
|
||
|
|
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", 18);
|
||
|
|
graph.CurvePlotAll();
|
||
|
|
graph.Update();
|
||
|
|
|
||
|
|
return graph;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Temporary visualization tracking a single X against an array |
|
||
|
|
//| of Y vectors over a predefined execution delay timeframe |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void 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 = false, 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 = 3, ENUM_CURVE_TYPE curve_type=CURVE_LINES, int duration = 20)
|
||
|
|
{
|
||
|
|
CGraphic *plot = plotXYs(x, y, curve_names, 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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Standard XY plot matching single X vector against a single Y vector|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
template<typename T>
|
||
|
|
CGraphic* plotXY(vector<T>&x, vector<T>&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<typename T>
|
||
|
|
void plotxy(vector<T>&x, vector<T>&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<typename T>
|
||
|
|
CGraphic* scatterplot(vector<T>&x, vector<T>&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<typename T>
|
||
|
|
void scatter_plot(vector<T>&x, vector<T>&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<typename T>
|
||
|
|
CGraphic* histogram_plot(vector<T>&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; ++i)
|
||
|
|
{
|
||
|
|
xa[i] = x.Min() + (i + 0.5) * width;
|
||
|
|
ya[i] = 0.0;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Sort data instances into corresponding frequency distribution slots
|
||
|
|
for(ulong i=0; i<x.Size(); ++i)
|
||
|
|
{
|
||
|
|
ulong ind = ulong((x[i] - x.Min()) / width);
|
||
|
|
if(ind >= 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;
|
||
|
|
}
|
||
|
|
}
|