217 行
无行尾
6.9 KiB
Markdown
217 行
无行尾
6.9 KiB
Markdown
<p align="center">
|
|
<img src="./Images/MQLCIByLeo.png" alt="MQLCIByLeo Logo" width="1150" height="175"/>
|
|
</p>
|
|
|
|
<p align="center">
|
|
CI framework for MQL5. Automatically compiles and validates EAs and libraries.
|
|
</p>
|
|
|
|
<p align="center">
|
|
<img src="https://img.shields.io/badge/Language-MQL5-1B6CA8?style=flat-square"/>
|
|
<img src="https://img.shields.io/badge/Platform-MetaTrader%205-0D1B2A?style=flat-square"/>
|
|
<img src="https://img.shields.io/badge/Author-nique__372%20and%20Leo-C9D6DF?style=flat-square"/>
|
|
<a href="./LICENSE.md">
|
|
<img src="https://img.shields.io/badge/License-Source%20Available-blue.svg?style=flat-square"/>
|
|
</a>
|
|
<a href="./LICENSE.md">
|
|
<img src="https://img.shields.io/badge/Non--Commercial-Free-brightgreen.svg?style=flat-square"/>
|
|
</a>
|
|
<a href="./LICENSE.md">
|
|
<img src="https://img.shields.io/badge/AI%20LLm%20Training-Prohibited-critical.svg?style=flat-square"/>
|
|
</a>
|
|
</p>
|
|
|
|
---
|
|
|
|
## How it works
|
|
|
|
1. `repo_update.py`Recursively updates all repository dependencies
|
|
2. `launcher.py` opens MT5 with the orchestrator EA
|
|
3. The orchestrator compiles and runs each test EA sequentially
|
|
4. Each test EA uses `CiTestUtil` to validate and report results via `EventChartCustom`
|
|
5. `reviser.py` reads the result and returns exit code `0` or `1` to Actions
|
|
|
|
---
|
|
|
|
## Features
|
|
|
|
### Orchestrator — run multiple test EAs automatically
|
|
|
|
```cpp
|
|
CMqlCIClassCi g_ci_ea;
|
|
#define FOLDER_CI "TbpCi\\"
|
|
|
|
// Initial config
|
|
MqlCiConfigCompiler config;
|
|
config.max_timeout_ms_compile = (60 * 1000); // 1 minute
|
|
config.max_timeout_esecution_per_test = (60 * 1); // 1 minute per test
|
|
config.file_name_out_json = FOLDER_CI + "result_logs.json";
|
|
config.file_name_read_py = FOLDER_CI + "read_py.bin";
|
|
config.file_name_res = FOLDER_CI + "result.bin";
|
|
config.filename_compiled_log = FOLDER_CI + "last_compile_log.log";
|
|
|
|
// Define test EAs
|
|
TestExpertCi experts[1];
|
|
experts[0].expert_ex5_name = "Experts\\Shared Projects\\TbpWrraper\\Workflows\\Test\\GetAllClients.ex5";
|
|
experts[0].expert_mq5_path = "Shared Projects\\TbpWrraper\\Workflows\\Test\\GetAllClients.mq5";
|
|
experts[0].symbol = "EURUSD";
|
|
experts[0].timeframe = PERIOD_M1;
|
|
experts[0].params[2].type = TYPE_STRING;
|
|
experts[0].params[2].string_value = InpApiKey;
|
|
|
|
// Init and run
|
|
g_ci_ea.AddLogFlags(LOG_ALL);
|
|
if(!g_ci_ea.Init(config, experts))
|
|
return INIT_FAILED;
|
|
|
|
if(!g_ci_ea.First())
|
|
return INIT_FAILED;
|
|
```
|
|
|
|
> **Note:** `params[0]` and `params[1]` are always reserved by the framework (EA name and chart ID). User params start at index `2`.
|
|
|
|
---
|
|
|
|
### Unit test class — validate a single class or module
|
|
|
|
```cpp
|
|
CiTestUtil test_util;
|
|
test_util.TestSize(2);
|
|
test_util.SetTestPtr(0, new CTestCustomer());
|
|
test_util.SetTestPtr(1, new CTestJobs());
|
|
|
|
// (chart_id, min_importance_for_early_exit, label, min_percentage_to_pass)
|
|
test_util.Init(InpCharId, 70, "Test api #1", 80.0);
|
|
test_util.RunAllTestAndSend();
|
|
```
|
|
|
|
Each test implements `ICiTest` and declares its own importance (1–100):
|
|
|
|
```cpp
|
|
class CTestCustomer : public ICiTest
|
|
{
|
|
inline string Name() const override { return "GetCustomers"; }
|
|
inline int Importance() const override { return 90; } // High — early exit if fails
|
|
bool Run(string &msg) override
|
|
{
|
|
if(!m_api.GetCustomersSoftware()) { msg = "HTTP call failed"; return false; }
|
|
return true;
|
|
}
|
|
};
|
|
```
|
|
|
|
| Importance range | Level | Behavior on failure |
|
|
|------------------|--------|-----------------------------------|
|
|
| 70 – 100 | High | Early exit, test suite aborted |
|
|
| 30 – 69 | Medium | Continues, lowers overall score |
|
|
| 0 – 29 | Low | Informational, minimal impact |
|
|
|
|
The final score is calculated as:
|
|
|
|
```
|
|
score = (sum of passed importances / total importances) * 100
|
|
```
|
|
|
|
If `score < min_percentage_to_pass` → test suite fails.
|
|
|
|
### Complete example
|
|
- The repository [TbpWrraper](https://forge.mql5.io/nique_372/TbpWrraper) integrates this repository for testing
|
|
|
|
|
|
---
|
|
|
|
### Python scripts
|
|
|
|
| Script | Purpose |
|
|
|----------------|------------------------------------------------------------------|
|
|
| `repo_update.py` | Recursively updates all repository dependencies |
|
|
| `compiler.py` | Compiles the orchestrator EA |
|
|
| `launcher.py` | Launches MT5 with the orchestrator EA |
|
|
| `reviser.py` | Polls for results and returns exit code `0` (pass) or `1` (fail) |
|
|
|
|
---
|
|
|
|
### Actions integration
|
|
|
|
```yaml
|
|
jobs:
|
|
test:
|
|
runs-on: self-hosted # Windows or linux (preference: windows)
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- name: Run CI
|
|
run: |
|
|
python Src/Py/reviser.py \
|
|
--terminal_path "C:\Users\...\Terminal\XXX" \
|
|
--file_name_res "TbpCi/result.bin" \
|
|
--file_name_out_json "TbpCi/result_logs.json" \
|
|
--filename_compiled_log "TbpCi/last_compile_log.log" \
|
|
--file_name_read_py "TbpCi/read_py.bin"
|
|
```
|
|
|
|
> **Note:** The YAML is not included in this repository — each project integrates its own workflow.
|
|
> `reviser.py` works on both Windows and Linux out of the box. `launcher.py` and `compiler.py`
|
|
> may require adjustments depending on your OS and MT5 installation path.
|
|
> The `--terminal_path` argument varies by OS:
|
|
> - **Windows example:** `C:\Users\USER\AppData\Roaming\MetaQuotes\Terminal\XXX`
|
|
> - **Linux (Wine) example:** `/home/user/.mt5/drive_c/Program Files/MetaTrader 5`
|
|
|
|
|
|
---
|
|
|
|
## Repository structure
|
|
|
|
```
|
|
MqlCIByLeo/
|
|
├── Src/
|
|
│ ├── Tester/ # MQL5 orchestrator (CMqlCIClassCi)
|
|
│ ├── UnitTest/ # ICiTest + CiTestUtil
|
|
│ └── Py/ # Python scripts (compiler, launcher, reviser)
|
|
└── Images/ # Repository banner
|
|
```
|
|
|
|
---
|
|
|
|
## Requirements
|
|
|
|
See [dependencies.json](./dependencies.json).
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
- Clone the repository into your MT5 `Shared Projects` folder via cmd.
|
|
- Contact me privately on MQL5 (user: `nique_372`) to be added as a collaborator — the repository will then appear automatically in your Shared Projects.
|
|
- Or fork the repository.
|
|
|
|
---
|
|
|
|
## Disclaimer
|
|
|
|
**Trading involves substantial risk of loss.**
|
|
|
|
- This software is a technical tool, not financial advice
|
|
- Past performance does not guarantee future results
|
|
- You are solely responsible for your trading decisions
|
|
- Always test thoroughly before deploying with real capital
|
|
- Apply appropriate risk management at all times
|
|
|
|
The authors assume no liability for trading losses, system failures, or any damages arising from the use of this software.
|
|
|
|
---
|
|
|
|
## License
|
|
|
|
**[Read Full License](./LICENSE.md)**
|
|
|
|
---
|
|
|
|
## Contact
|
|
|
|
- **Platform:** [MQL5 Community](https://www.mql5.com/es/users/nique_372)
|
|
- **Profile:** https://www.mql5.com/es/users/nique_372/news
|
|
|
|
---
|
|
|
|
<p align="center">Copyright © 2026 Nique-Leo.</p> |