//+------------------------------------------------------------------+ //| ONNX Model Viewer Part 1.mq5 | //| Copyright 2026, Allan Munene Mutiiria. | //| https://t.me/Forex_Algo_Trader | //+------------------------------------------------------------------+ #property copyright "Copyright 2026, Allan Munene Mutiiria." #property link "https://t.me/Forex_Algo_Trader" #property version "1.00" #property strict #property description "Read an ONNX model file and report its structure" #include "OMV Model.mqh" //+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ input group "Model" input string ModelFile = "ONNX Model Viewer Part 1\\model.onnx"; // Model File Path Inside MQL5 Files input bool ShowWeights = true; // List Every Weight Tensor //+------------------------------------------------------------------+ //| Global Variables | //+------------------------------------------------------------------+ COmvModel model; // Parsed model held for the life of the chart //+------------------------------------------------------------------+ //| Report one exposed port | //+------------------------------------------------------------------+ void ReportPort(const OmvPort &port, const string role) { //--- Print the role, name, element type and shape on one line PrintFormat(" %-6s %-10s %-7s %s", role, port.name, model.TypeName(port.elemType), model.DimsText(port.dim, port.dims)); } //+------------------------------------------------------------------+ //| Report every exposed port | //+------------------------------------------------------------------+ void ReportPorts(void) { //--- Print how many ports sit on each side PrintFormat(" ports: %d in, %d out", model.Inputs(), model.Outputs()); //--- Print every graph input for(int i = 0; i < model.Inputs(); i++) { //--- Fetch this input OmvPort port; model.InputAt(i, port); //--- Print it ReportPort(port, "in"); } //--- Print every graph output for(int i = 0; i < model.Outputs(); i++) { //--- Fetch this output OmvPort port; model.OutputAt(i, port); //--- Print it ReportPort(port, "out"); } } //+------------------------------------------------------------------+ //| Report every layer | //+------------------------------------------------------------------+ void ReportNodes(void) { //--- Print how many layers the graph holds PrintFormat(" nodes: %d", model.Nodes()); //--- Print every layer in file order for(int i = 0; i < model.Nodes(); i++) { //--- Fetch this layer OmvNode node; model.NodeAt(i, node); //--- Join the names feeding it string feeds = ""; for(int j = 0; j < node.feedCount; j++) feeds += (j > 0 ? ", " : "") + node.feeds[j]; //--- Join the names it produces string emits = ""; for(int j = 0; j < node.emitCount; j++) emits += (j > 0 ? ", " : "") + node.emits[j]; //--- Print the layer with both name lists PrintFormat(" %2d %-10s %-14s in(%s) out(%s)", i, node.op, node.name, feeds, emits); } } //+------------------------------------------------------------------+ //| Report every weight tensor | //+------------------------------------------------------------------+ void ReportTensors(void) { //--- Print how many tensors and weights the file carries PrintFormat(" tensors: %d holding %d parameters", model.Tensors(), model.Parameters()); //--- Stop when the user asked for the summary only if(!ShowWeights) return; //--- Print every tensor with its shape and range for(int i = 0; i < model.Tensors(); i++) { //--- Fetch this tensor OmvTensor tensor; model.TensorAt(i, tensor); //--- Print the name, shape and size every tensor has PrintFormat(" %-6s %-10s %-8s %-7s %6d values%s", "", tensor.name, model.TypeName(tensor.dataType), model.DimsText(tensor.dim, tensor.dims), tensor.values, //--- A tensor of text has no range to report (tensor.dataType == 8) ? " text" : StringFormat(" min %+.4f max %+.4f mean %+.4f", tensor.minValue, tensor.maxValue, tensor.meanValue)); } } //+------------------------------------------------------------------+ //| Report the whole model | //+------------------------------------------------------------------+ void ReportModel(void) { //--- Print which file was read Print("ONNX Model Viewer -> ", model.Path()); //--- Print what the file says about itself PrintFormat(" ir_version %d opset %d producer %s graph %s", model.IrVersion(), model.Opset(), model.Producer(), model.GraphName()); //--- Print the shapes the model expects and returns ReportPorts(); //--- Print the layers ReportNodes(); //--- Print the weights ReportTensors(); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Read the whole file before reporting anything if(!model.Load(ModelFile)) { Print("ONNX Model Viewer: ", model.Error()); return(INIT_FAILED); } //--- Report what was read ReportModel(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Release the parsed structures model.Clear(); } //+------------------------------------------------------------------+