Indicators: Fibonacci Structure Engine

 

Fibonacci Structure Engine:

A Market Structure indicator featuring Fibonacci Intelligence to provide accurate Buy/Sell signals.

Fibonacci Structure Engine

Author: Hammad Dilber

 
indikator tidak muncul di chart
 
mantaffff
 
This is a technical review of the `FibStructureEngine.mq5` indicator, specifically addressing the reported symptom where the indicator fails to render on the chart upon attachment but becomes visible after removal. The review is based on a static analysis of the provided source code, the MQL5 documentation, and community reports.

---

1. Primary Symptom Analysis: "Does Not Appear When Attached, Appears When Removed"

The reported behavior is a classic manifestation of a **deferred rendering** issue in MQL5. When an indicator is attached, `OnCalculate()` is called, but the chart is not always redrawn immediately. The terminal queues drawing commands, and a redraw is only triggered by specific events (e.g., a new tick, a chart property change, or an explicit `ChartRedraw()` call). If `ChartRedraw()` is ineffective or not called at the right moment, newly created graphical objects (lines, labels, boxes) may exist in memory but remain invisible until the next full chart refresh—often triggered when the indicator is removed or the chart is scrolled.

The code calls `ChartRedraw()` at the end of `OnCalculate()`, but this is not guaranteed to force an immediate redraw. MQL5's `ChartRedraw()` is asynchronous; it only queues a command. If the terminal is busy or the chart is not in focus, the redraw may be delayed. The fact that objects become visible after removal suggests that the removal process (which triggers `OnDeinit()`) forces a full chart refresh, at which point the already-created objects finally become visible. However, `OnDeinit()` calls `DeleteAllObjects()`, which should delete those objects. This paradox implies that the objects are either **not being deleted** (due to a failure in `DeleteAllObjects()`) or that the objects the user sees after removal are actually **re-created** by a second `OnInit()` call (if the user re-attaches the indicator). A more plausible explanation is that the indicator's objects are created but **not properly anchored** (due to a critical bug in `DrawLabel()`), causing them to be placed at invalid coordinates. When the chart is redrawn (e.g., upon removal), the objects are re-evaluated and may snap to a visible location.

---

2. Critical Bug: Incorrect `ObjectSetInteger` and `ObjectSetDouble` Calls in `DrawLabel()`

The most severe defect in the code is found in the `DrawLabel()` function. The following lines are syntactically and semantically incorrect for MQL5:

ObjectSetInteger(g_chartID, name, OBJPROP_TIME,      t);
ObjectSetDouble (g_chartID, name, OBJPROP_PRICE,     labelPrice);
```

**Why this is wrong:**  
In MQL5, `OBJPROP_TIME` and `OBJPROP_PRICE` require a **modifier** (0 for the first anchor point, 1 for the second). The correct signatures are:


ObjectSetInteger(chart_id, name, OBJPROP_TIME,  0, t);
ObjectSetDouble (chart_id, name, OBJPROP_PRICE, 0, labelPrice);
```

The overloads without a modifier are only valid for properties like `OBJPROP_COLOR`, `OBJPROP_WIDTH`, `OBJPROP_STYLE`, etc. Using the wrong overload will either cause a **compilation error** or, if the compiler allows it (e.g., via implicit conversions), it will set the property to an incorrect value (e.g., using the time value as a property ID). The result is that labels are either not created, not positioned correctly, or placed at coordinates that are outside the visible chart area.

**Impact:**  
All text labels—including swing labels (HH/HL/LH/LL), BOS/CHoCH labels, engulfing markers, and Fibonacci level labels—are affected. Since these labels are a core visual component of the indicator, their absence makes the indicator appear "empty" on the chart.

**Fix:**  
Replace the two lines with the correct modifier-based calls.

---

3. Secondary Issue: Buffer Initialization and Arrow Rendering

The indicator uses two buffers (`BuyBuffer` and `SellBuffer`) for drawing arrows. The buffer setup in `OnInit()` is mostly correct, but there is a subtle problem:


PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0);
```

This tells the terminal that a buffer value of `0.0` means "no plot." In `OnCalculate()`, the buffers are assigned:


BuyBuffer[i]  = confirmedBuy  && ShowSignals ? low[i]  - atr * 0.3 : 0.0;
SellBuffer[i] = confirmedSell && ShowSignals ? high[i] + atr * 0.3 : 0.0;
```

This is correct. However, if no signals are generated (which is common on a fresh chart with limited history), the buffers remain `0.0` and no arrows appear. This is expected behavior, but users often misinterpret "no signals" as "indicator not working."

**Additional Buffer Bug:**  
The code sets `ArraySetAsSeries(BuyBuffer, true)` and `ArraySetAsSeries(SellBuffer, true)`. While this is allowed, the buffers are already managed by the terminal, and setting them as series can cause indexing issues if not handled carefully. In this code, the buffers are indexed with `i` (which is a bar shift, consistent with series arrays), so this works. However, it is an unnecessary risk.

---

4. Pivot Detection and Warm‑Up Logic

The pivot detection functions (`IsPivotHigh`, `IsPivotLow`) are correctly implemented for series arrays. However, the warm‑up condition is too strict:


if(rates_total < g_warmupBars + SwingLength * 2 + 5) return 0;
```

With `SwingLength = 10` and `g_warmupBars = 50`, the indicator requires at least `75` bars before it begins drawing. On a chart with limited history (e.g., a newly opened chart or a symbol with low liquidity), the indicator will simply do nothing. This is a common complaint among users who attach the indicator to a chart with insufficient bars.

**Recommendation:**  
Lower the minimum bar requirement to `SwingLength * 2 + 10` or make it configurable.

---

5. Object Deletion and Chart Refresh

`DeleteAllObjects()` iterates through `ObjectsTotal(g_chartID)` and deletes objects with the prefix `"FSE_"`. This is correct. However, the function is called in `OnInit()` and `OnDeinit()`. On re‑initialization (e.g., when changing timeframe), `OnDeinit()` is called first, deleting all objects, and then `OnInit()` is called, creating new ones. This is standard.

The problem is that `ChartRedraw()` is called at the end of `OnCalculate()`, but not in `OnInit()` or `OnDeinit()`. After `OnInit()`, the chart is not immediately redrawn, so the objects created in the first `OnCalculate()` call may not appear until the next tick. This is a contributing factor to the "does not appear on attach" symptom.

**Fix:**  
Call `ChartRedraw()` at the end of `OnInit()` and after `DeleteAllObjects()` in `OnDeinit()`.

---

6. Missing Dashboard

The code contains a comment:


// ── Dashboard removed ──


This suggests that a dashboard (likely showing signal confidence, structure bias, etc.) was removed from the indicator. The MQL5 code description mentions "Dashboard" in the description, but the actual implementation lacks it. This is a significant discrepancy between the advertised features and the delivered product.

---

7. Community Reports

On the MQL5 forum for this indicator, there is a direct complaint: *"indikator tidak muncul di chart"* (indicator does not appear on chart). This confirms that the issue is not isolated to the user's environment. The bug in `DrawLabel()` is the most likely cause of this widespread problem.

---

8. Summary of Complaints and Recommended Fixes

| Issue | Severity | Impact | Fix |
|-------|----------|--------|-----|
| Incorrect `ObjectSetInteger`/`ObjectSetDouble` in `DrawLabel()` | **Critical** | Labels not drawn or placed at invalid coordinates | Use modifier `0` for `OBJPROP_TIME` and `OBJPROP_PRICE` |
| Delayed chart redraw | High | Objects not visible until next tick or chart refresh | Call `ChartRedraw()` in `OnInit()` and after object creation |
| Strict warm‑up bars | Medium | Indicator does nothing on charts with <75 bars | Lower `g_warmupBars` or make it configurable |
| No dashboard despite description | Medium | Missing advertised feature | Implement dashboard or remove claim |
| Buffer arrows only appear when signals exist | Low | User may think indicator is broken | Add a "waiting for signals" message or show current structure bias |

---

9. Conclusion

The `FibStructureEngine.mq5` indicator suffers from a **critical rendering bug** in the `DrawLabel()` function that prevents labels from being placed correctly. Combined with asynchronous chart redraw issues, this causes the indicator to appear "empty" when first attached. The fact that objects become visible after removal is a side effect of the chart being forced to refresh, at which point the incorrectly positioned labels may become visible or the user may be seeing objects from a previous instance that were not properly deleted.

To resolve the "does not appear on chart" complaint, the developer must:

1. Fix the `ObjectSetInteger` and `ObjectSetDouble` calls in `DrawLabel()`.
2. Add explicit `ChartRedraw()` calls after object creation in `OnInit()` and after `DeleteAllObjects()` in `OnDeinit()`.
3. Reduce the minimum bar requirement to allow the indicator to function on charts with limited history.
4. Verify that the buffer arrows are displayed when signals occur and that the buffer empty value is handled correctly.

Without these fixes, the indicator will continue to exhibit the reported behavior, and users will be unable to rely on it for live trading.