Unisciti alla nostra fan page

A powerful and feature-rich JSON library for MQL5, designed to bring a modern development experience similar to Python/JS - libreria per MetaTrader 5
- Visualizzazioni:
- 259
- Valutazioni:
- Pubblicato:
-
Hai bisogno di un robot o indicatore basato su questo codice? Ordinalo su Freelance Vai a Freelance
//+------------------------------------------------------------------+//+------------------------------------------------------------------+ //| JsonLib.mqh | //| Version 10.0 | //| Copyright 2025, ding9736 | //+------------------------------------------------------------------+ #property strict #property copyright "Copyright 2025, ding9736" #property link "https://www.mql5.com/en/users/ding9736" #property link "https://github.com/ding9736/Mql5-JsonLib" #property version "10.0" #ifndef MQL5_JSON_LIBRARY_V10_H #define MQL5_JSON_LIBRARY_V10_H /* //+------------------------------------------------------------------+ //| MQL5 JSON Library - Developer's Manual | //| Author: ding9736 | //| Version: 10.0 | //+------------------------------------------------------------------+ //============================================================================== // 1. Overview //============================================================================== // // The MQL5 JSON Library is a powerful, feature-rich library designed specifically // for parsing, manipulating, and serializing JSON data within the MQL5 // environment. It provides a simple and intuitive Document Object Model (DOM) API, // aiming to make the JSON handling experience in MQL5 comparable to modern // programming languages like JavaScript and Python. // // This library is capable of handling a wide range of tasks, from reading simple // EA configurations to complex real-time data exchange between systems. // Its main functions and features include: // // --- Parsing and Creation --- // // - **Load from String or File**: Reliably parses JSON text into manipulable // in-memory objects (`JsonParse`, `JsonFromFile`). // - **Build from Scratch**: Easily create new JSON objects and arrays // programmatically using concise APIs like `JsonNewObject` and `JsonNewArray`. // - **Flexible Parser**: Optionally supports some non-standard features of JSON5, // such as code comments and trailing commas, to enhance compatibility with // various data sources. // // --- Manipulation and Access --- // // - **Intuitive DOM Traversal**: Access data using intuitive syntax with keys // (`node["key"]`) and indices (`node[0]`), just like using a Python dictionary // or a JavaScript object. // - **Safe Type Conversion**: Provides a series of methods with default values, // such as `AsInt(defaultValue)` and `AsString(defaultValue)`, allowing you // to safely extract data of the desired type from a node without worrying // about program crashes due to type mismatches or non-existent paths. // - **Dynamic Modification**: Freely add, update, or delete key-value pairs // in JSON objects and elements in arrays (`Set`, `Add`, `Remove`). // // --- Advanced Querying and Processing --- // // - **Powerful Query Engine**: Built-in support for **JSON Pointer** (RFC 6901, // for direct path access) and **JSONPath** (for complex and fuzzy queries), // enabling efficient extraction of one or more data nodes from deeply // nested, complex structures, either in bulk or with precision. // - **Low-Memory Stream Parsing**: Provides `JsonStreamParser` for processing // gigabyte-scale, huge JSON files. It reads the file token by token in an // event stream manner without loading the entire file into memory, thus // achieving ultimate memory efficiency. // - **Utility Functions**: Offers advanced features like document cloning (`.Clone()`) // and deep merging (`JsonMerge`), which greatly simplify common complex tasks // such as merging "default configuration" with "user configuration". // // --- Robustness and Safety --- // // - **Automatic Memory Management**: Adopts the RAII (Resource Acquisition Is // Initialization) design pattern. `JsonDocument` is responsible for managing // the lifecycle of all its nodes. Developers do not need to manually `new`/`delete` // any JSON elements, fundamentally eliminating the risk of memory leaks. // - **Cross-Document Operation Safety**: When assigning a node between different // `JsonDocument` instances, the library automatically performs a safe deep // copy (Clone), preventing dangling pointers and accidental data corruption. // - **Detailed Error Reporting**: When parsing fails, the `JsonError` object // provides detailed information including the error line number, column number, // and context, facilitating rapid problem diagnosis. // //============================================================================== // 2. Core Concepts & Memory Management //============================================================================== // // [!!] 2.1 Namespace - The Key to Integrating Your Project [!!] // **Most Important Tip**: All classes in this library (e.g., `JsonDocument`, // `JsonNode`) and global functions (e.g., `JsonParse`) are encapsulated // within a namespace called `MQL5_Json`. // // **How to Use It Correctly:** // // - **In Header Files (.mqh)**: MQL5 does not allow `using namespace` in the // global scope of header files. **Therefore, you must use fully qualified names**. // This is the only reliable way in multi-file projects. // Incorrect: `JsonDocument doc;` // Correct: `MQL5_Json::JsonDocument doc;` // // - **Inside Functions in Main Program Files (.mq5)**: For convenience, you can use // `using namespace MQL5_Json;` inside functions, but to ensure the // generality of the examples, all code in this manual will use the fully // qualified name approach. // // **If you encounter the `'JsonNode' - declaration without type` compilation error,** // **it is almost always because you forgot to add the `MQL5_Json::` prefix** // **to the types and functions.** // // [!!] 2.2 Memory Management Model // `JsonDocument` **owns** the data; `JsonNode` is just a **view**. // // [!!] 2.3 Object Passing in MQL5 // MQL5 requires that all class objects (including `JsonNode`) passed as function // arguments **must be passed by reference (using &)**. // Incorrect: `void myFunction(MQL5_Json::JsonNode node)` // Correct: `void myFunction(MQL5_Json::JsonNode &node)` // //============================================================================== // 3. API Usage & Examples //============================================================================== //--- 3.1. Quick Start ----------------------------------------------- // // void OnStart() // { // string jsonText = "{ \"name\": \"John Doe\", \"age\": 30, \"isStudent\": false, \"courses\": [\"MQL5\", \"C++\"] }"; // // // 1. Parse JSON string (using fully qualified names) // MQL5_Json::JsonError error; // MQL5_Json::JsonParseOptions options; // MQL5_Json::JsonDocument doc = MQL5_Json::JsonParse(jsonText, error, options); // // // Always check if the document is valid after parsing // if (!doc.IsValid()) // { // Print("Failed to parse JSON: ", error.ToString()); // return; // } // // // 2. Access data // MQL5_Json::JsonNode root = doc.GetRoot(); // string name = root.Get("name").AsString("Unknown"); // long age = root.Get("age").AsInt(0); // bool isStudent = root["isStudent"].AsBool(true); // Using the [] operator // // PrintFormat("Name: %s, Age: %d, Is Student: %s", name, age, isStudent ? "Yes" : "No"); // // // 3. Create a new JSON document // MQL5_Json::JsonDocument newDoc = MQL5_Json::JsonNewObject(); // newDoc.GetRoot().Set("status", "OK"); // newDoc.GetRoot().Set("code", 200); // // // 4. Serialize the new JSON (pretty format) // Print("Newly created JSON:\n", newDoc.ToString(true)); // } // //--- 3.2. Parsing JSON ---------------------------------------------- // // void ParseFromStringAndFile() // { // string json_with_comments = "{ \"key\": \"value\", / * comment * / \"key2\": 123, } // trailing comma"; // // MQL5_Json::JsonError error; // MQL5_Json::JsonParseOptions options; // options.allow_trailing_commas = true; // options.allow_comments = true; // // MQL5_Json::JsonDocument doc = MQL5_Json::JsonParse(json_with_comments, error, options); // if (doc.IsValid()) { Print("Flexible parsing successful! Result: ", doc.ToString()); } // // MQL5_Json::JsonDocument docFromFile = MQL5_Json::JsonFromFile("config.json", error, options); // if (docFromFile.IsValid()) { Print("Successfully loaded configuration from file."); } // } // //--- 3.3. Creating JSON ----------------------------------------------- // // void CreateJson() // { // MQL5_Json::JsonDocument doc = MQL5_Json::JsonNewObject(); // MQL5_Json::JsonNode root = doc.GetRoot(); // // root.Set("product_id", 12345); // root.Set("available", true); // // MQL5_Json::JsonNode specs = doc.CreateObjectNode(); // specs.Set("color", "black"); // root.Set("specifications", specs); // // MQL5_Json::JsonNode tags = doc.CreateArrayNode(); // tags.Add("electronics"); // root.Set("tags", tags); // // Print("Created JSON:\n", doc.ToString(true)); // } // //--- 3.4. Accessing & Querying Data -------------------------- // // void AccessData() // { // string jsonText = "{ \"data\": { \"user_id\": 101, \"tags\": [\"active\"] } }"; // MQL5_Json::JsonDocument doc = MQL5_Json::JsonParse(jsonText, {}, {}); // if(!doc.IsValid()) return; // // MQL5_Json::JsonNode root = doc.GetRoot(); // // long user_id = root["data"]["user_id"].AsInt(-1); // string first_tag = root.Get("data").Get("tags").At(0).AsString("default"); // // PrintFormat("User ID: %d, First Tag: %s", user_id, first_tag); // } // // void QueryWithJsonPathAndPointer() // { // string text = "{ \"store\": { \"book\": [ { \"title\": \"MQL5 Basics\" } ] } }"; // MQL5_Json::JsonDocument doc = MQL5_Json::JsonParse(text, {}, {}); // if(!doc.IsValid()) return; // // string title = doc.GetRoot().Query("/store/book/0/title").AsString(); // Print("JSON Pointer Result: ", title); // // MQL5_Json::JsonNode nodes[]; // MQL5_Json::JsonError error; // int count = doc.GetRoot().SelectNodes(nodes, "$.store.book[*].title", error); // if(count > 0) { Print("JSONPath Result: ", nodes[0].AsString()); } // } // //--- 3.5. Modifying Data ---------------------------------------------- // // void ModifyJson() // { // MQL5_Json::JsonDocument doc = MQL5_Json::JsonParse("{ \"a\": 1, \"b\": 2 }", {}, {}); // MQL5_Json::JsonNode root = doc.GetRoot(); // root.Set("a", 100); // root.Remove("b"); // Print("Modified JSON:\n", doc.ToString(true)); // } // //--- 3.6. Serialization ------------------------------------------------ // // void SerializeJson() // { // MQL5_Json::JsonDocument doc = MQL5_Json::JsonNewObject(); // doc.GetRoot().Set("message", "hello world"); // // string pretty_str = doc.ToString(true); // Print("Pretty Format:\n", pretty_str); // // doc.SaveToFile("output.json", true); // } // //============================================================================== // 4. Advanced Features //============================================================================== //--- 4.1. Stream Parsing Large Files (Low Memory Usage) --- // // class CTradeCounter : public MQL5_Json::IJsonStreamHandler // { // private: // int m_count; // public: // int GetCount() const { return m_count; } // bool OnStartDocument() override { m_count=0; return true; } // bool OnString(const string &value) override // { // if(value == "EURUSD") m_count++; // return true; // } // // (Other empty methods omitted for brevity) // }; // // void TestStreamParser() // { // string big_json = "[{\"s\":\"EURUSD\"},{\"s\":\"EURUSD\"}]"; // MQL5_Json::JsonStreamParser parser; // CTradeCounter *handler = new CTradeCounter(); // MQL5_Json::JsonError error; // // if(parser.Parse(big_json, handler, error, {})) // Print("Stream parser found count: ", handler.GetCount()); // delete handler; // } // //--- 4.2. Merging Documents (JsonMerge) --- // // void TestJsonMerge() // { // MQL5_Json::JsonDocument target = MQL5_Json::JsonParse("{ \"a\": 1 }", {}, {}); // MQL5_Json::JsonDocument patch = MQL5_Json::JsonParse("{ \"b\": 2 }", {}, {}); // MQL5_Json::JsonDocument result = MQL5_Json::JsonMerge(target, patch); // Print("Merge result:\n", result.ToString(true)); // } // //--- 4.3. Cloning Documents (Clone) --- // // void TestClone() // { // MQL5_Json::JsonDocument base = MQL5_Json::JsonNewObject(); // base.GetRoot().Set("magic", 12345); // // MQL5_Json::JsonDocument backtest = base.Clone(); // backtest.GetRoot().Set("magic", 67890); // // Print("Cloned and modified config:\n", backtest.ToString(true)); // } // //--- 4.4. Iteration using the Visitor Pattern (ForEach) --- // // class CSumVisitor : public MQL5_Json::IJsonArrayVisitor // { // public: // double sum; // void Visit(int index, const MQL5_Json::JsonNode &item) override // { // if(item.IsNumber()) sum += item.AsDouble(); // } // }; // // void TestForEach() // { // MQL5_Json::JsonDocument doc = MQL5_Json::JsonParse("[10, 20.5, 30]", {}, {}); // CSumVisitor visitor; // doc.GetRoot().ForEach(GetPointer(visitor)); // Print("Array sum: ", visitor.sum); // } // //--- 4.5. JSONPath - Selecting a Single Node (SelectSingleNode) --- // // void TestSelectSingleNode() // { // string text = "{ \"store\": { \"bicycle\": { \"color\": \"red\"} } }"; // MQL5_Json::JsonDocument doc = MQL5_Json::JsonParse(text, {}, {}); // MQL5_Json::JsonError error; // MQL5_Json::JsonNode bike = doc.GetRoot().SelectSingleNode("$.store.bicycle", error); // if(bike.IsValid()) { Print("Found bicycle color: ", bike["color"].AsString()); } // } // //============================================================================== // 5. Design Philosophy & FAQ //============================================================================== // // --- Q: I have correctly #included JsonLib.mqh, so why am I still getting tons of // --- `'JsonNode' - declaration without type` compilation errors? // // **A: This is the most common integration issue and is 100% caused by improper namespace handling.** // // - **Diagnosis**: The compiler doesn't recognize `JsonNode` because it doesn't know to look inside the `MQL5_Json` namespace. // - **Solution**: In your code, modify all calls to `JsonLib` types and functions to their fully qualified form with the `MQL5_Json::` prefix. // // - **Example**: // // Incorrect code (will not compile in an .mqh file) // JsonDocument doc = JsonNewObject(); // // // Correct code (guaranteed to compile) // MQL5_Json::JsonDocument doc = MQL5_Json::JsonNewObject(); // // - **Root Cause**: MQL5 does not allow `using namespace` in the global scope of `.mqh` files. // // // --- Q: Why does the function parameter `JsonNode node` cause an `'objects are passed by reference only'` error? // // **A: This is a mandatory rule of the MQL5 language.** // // - **The Rule**: MQL5 requires all class objects (including `JsonNode`) to be passed by reference (`&`). // - **Solution**: Always use `&` in your function signatures. // - **Example**: // // Incorrect // void ProcessNode(MQL5_Json::JsonNode node); // // // Correct // void ProcessNode(MQL5_Json::JsonNode &node); // //============================================================================== // 6. Best Practices & Important Notes //============================================================================== // // To ensure your project integrates smoothly and runs stably, please adhere to the following rules. // // 1. **Always Use Fully Qualified Names in `.mqh` Files (Crucial!)** // - This is the **number one rule** for successfully integrating `JsonLib` in multi-file projects. // - Always use `MQL5_Json::JsonDocument`, `MQL5_Json::JsonNode`, `MQL5_Json::JsonParse`, etc. // // 2. **Class Object Parameters Must Be Passed by Reference** // - When you write a function that needs to accept a `JsonNode` as a parameter, you must declare it as a reference (`&`). // - `void myFunction(MQL5_Json::JsonNode &node);` // Correct // - This is to comply with MQL5's language rules and will prevent the `'objects are passed by reference only'` compilation error. // // 3. **Memory and Object Lifecycle** // - `JsonDocument` **owns** the data; `JsonNode` is just a **view**. // - If a `JsonDocument` is destroyed, all of its `JsonNode`s become **invalid**. // // 4. **Robust Coding and Error Handling** // - After calling `JsonParse`, **always check `doc.IsValid()`**. // */ //+------------------------------------------------------------------+ #include "Core/JsonCore.mqh" #include "Core/JsonNode.mqh" #include "Core/JsonDocument.mqh" #include "Core/JsonStreamParser.mqh" #include "Core/JsonApiImpl.mqh" #endif // MQL5_JSON_LIBRARY_V10_H //+------------------------------------------------------------------+

The EA identifies trade setups by waiting for a user-defined number of indicators (e.g., 2 out of 3) to show divergence simultaneously. This multi-layer confirmation approach filters out market noise. Key Features: Triple Confirmation Engine: Analyzes RSI, MACD, & Stochastic divergence. Advanced Filters: Optional Trend Filter (MA) and Volume Filter for superior signal quality. Full Customization: Control all indicator settings, divergence sensitivity, and trade logic. Professional Risk Management: Use fixed lots or percentage-based money management with SL/TP.

It is an indicator that determines target levels according to the average of price movements.

The Acceleration/Deceleration Indicator (AC) measures acceleration and deceleration of the current driving force.

Indicator edition for new platform.