$npx -y skills add kecoma1/MQL5-SKILLS --skill candles-and-seriesUse when working with MqlRates arrays, candles, or time series in MQL5 in this workspace. Follow the local convention for treating index 0 as the most recent candle by explicitly enabling series mode.
| 1 | # Candles And Series |
| 2 | |
| 3 | Use this skill when loading or processing candles in MQL5 with `MqlRates[]`, `CopyRates`, `CopyOpen`, `CopyHigh`, `CopyLow`, `CopyClose`, or similar functions. |
| 4 | |
| 5 | ## Rule |
| 6 | |
| 7 | When the logic depends on candle `0` being the most recent candle, always call: |
| 8 | |
| 9 | ```mq5 |
| 10 | ArraySetAsSeries(array, true); |
| 11 | ``` |
| 12 | |
| 13 | Apply this before reading the array contents. |
| 14 | |
| 15 | In this workspace, the default expectation for candle-processing logic is: |
| 16 | |
| 17 | - index `0`: most recent candle |
| 18 | - index `1`: previous candle |
| 19 | - index `2`: older candle |
| 20 | |
| 21 | ## Example |
| 22 | |
| 23 | ```mq5 |
| 24 | MqlRates rates[]; |
| 25 | ArraySetAsSeries(rates, true); |
| 26 | |
| 27 | int copied = CopyRates(_Symbol, _Period, 0, 3, rates); |
| 28 | if(copied < 3) |
| 29 | return false; |
| 30 | |
| 31 | double current_open = rates[0].open; |
| 32 | double previous_high = rates[1].high; |
| 33 | double older_low = rates[2].low; |
| 34 | ``` |
| 35 | |
| 36 | ## Validation |
| 37 | |
| 38 | Before trusting candle logic, verify these points: |
| 39 | |
| 40 | 1. `ArraySetAsSeries(..., true)` is applied when the code expects candle `0` to be the latest. |
| 41 | 2. `CopyRates(...)` loads only the number of candles actually needed for the pattern. |
| 42 | 3. The code does not mix series-style indexing with chronological indexing by mistake. |
| 43 | 4. Conditions that refer to candle 1, 2, or 3 are mapped explicitly to the intended indices. |
| 44 | |
| 45 | ## Closed Candles |
| 46 | |
| 47 | For patterns that must be built only from closed candles, do not use `CopyRates(..., 0, ...)` if the current forming candle must be excluded. |
| 48 | |
| 49 | In those cases, start from `1`, so `rates[0]` represents the last closed candle. |
| 50 | |
| 51 | ## Recalculation Vs Entry |
| 52 | |
| 53 | Separate these two responsibilities explicitly: |
| 54 | |
| 55 | - when the pattern is recalculated |
| 56 | - when entry conditions are evaluated |
| 57 | |
| 58 | If the pattern depends on closed candles, it can be recalculated on a new bar. |
| 59 | If the entry depends on price crossing a level, that condition may need to be checked on every tick. |
| 60 | |
| 61 | ## Candle Numbering |
| 62 | |
| 63 | When a pattern depends on candle numbering, the convention must be written explicitly. |
| 64 | It is not enough to say `ArraySetAsSeries(..., true)`. |
| 65 | |
| 66 | Also state what each index means in that context, for example: |
| 67 | |
| 68 | - `rates[0]` = last closed candle when using `CopyRates(..., 1, ...)` |
| 69 | - `rates[1]` = previous closed candle |
| 70 | - `rates[2]` = third closed candle back |
| 71 | |
| 72 | ## Pattern Debugging |
| 73 | |
| 74 | When there is doubt about a candle-pattern calculation, create a separate EA test. |
| 75 | |
| 76 | That EA should print times, OHLC values, indices, and pattern results so the calculation can be validated without mixing it with trading logic. |
| 77 | |
| 78 | ## Function Ownership |
| 79 | |
| 80 | If a class or function is responsible for calculating a pattern, it should also load the candles inside that same function. |
| 81 | |
| 82 | Do not split that responsibility between the EA and the class, because that can make each place use a different window, a different shift, or a different array orientation. |