//+------------------------------------------------------------------+ //| ZigZag_Fibo_Structure.mq5 | //| MQL5 Custom Indicator | //+------------------------------------------------------------------+ #property copyright "Custom Indicator" #property link "" #property version "1.02" #property indicator_chart_window #property indicator_buffers 3 #property indicator_plots 3 //--- plot ZigZag #property indicator_label1 "ZigZag Line" #property indicator_type1 DRAW_SECTION #property indicator_color1 clrDodgerBlue #property indicator_style1 STYLE_SOLID #property indicator_width1 2 //--- plot High Markers #property indicator_label2 "Pivot High" #property indicator_type2 DRAW_ARROW #property indicator_color2 clrRed #property indicator_width2 2 //--- plot Low Markers #property indicator_label3 "Pivot Low" #property indicator_type3 DRAW_ARROW #property indicator_color3 clrLimeGreen #property indicator_width3 2 //--- Enums untuk pilihan bentuk marker (Sesuai modifikasi visual Anda) enum ENUM_MARKER_SHAPE { MARKER_TRIANGLE, // Segitiga MARKER_ARROW, // Panah MARKER_CIRCLE, // Titik/Lingkaran MARKER_STAR // Bintang }; //--- Input parameters input string grp1 = "--- Pengaturan ZigZag ---"; input int InpDepth = 12; // Depth input int InpDeviation = 5; // Deviation input int InpBackstep = 3; // Backstep input string grp2 = "--- Pengaturan Marker ---"; input bool InpShowMarkers = true; // Tampilkan/Sembunyikan Marker input ENUM_MARKER_SHAPE InpMarkerShape = MARKER_TRIANGLE; // Bentuk Marker Pengganti input string grp3 = "--- Pengaturan Fibo ---"; input color InpFibo618 = clrGoldenrod; // Warna Fibo 61.8% input color InpFibo500 = clrGray; // Warna Fibo 50.0% input color InpFibo382 = clrDarkOrange;// Warna Fibo 38.2% input int InpFiboHistory = 20; // Jumlah Swing untuk Fibo (Max) //--- Indicator buffers double ZigZagBuffer[]; double HighBuffer[]; double LowBuffer[]; //--- Handle ZigZag bawaan int zigzag_handle; string fibo_prefix = "FiboZG_"; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, ZigZagBuffer, INDICATOR_DATA); SetIndexBuffer(1, HighBuffer, INDICATOR_DATA); SetIndexBuffer(2, LowBuffer, INDICATOR_DATA); //--- Wajib: Deklarasi bahwa nilai 0.0 adalah ruang kosong agar garis terputus terhubung PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0.0); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, 0.0); //--- Setup bentuk marker berdasarkan opsi if(InpShowMarkers) { switch(InpMarkerShape) { case MARKER_TRIANGLE: PlotIndexSetInteger(1, PLOT_ARROW, 234); PlotIndexSetInteger(2, PLOT_ARROW, 233); break; case MARKER_ARROW: PlotIndexSetInteger(1, PLOT_ARROW, 226); PlotIndexSetInteger(2, PLOT_ARROW, 225); break; case MARKER_CIRCLE: PlotIndexSetInteger(1, PLOT_ARROW, 159); PlotIndexSetInteger(2, PLOT_ARROW, 159); break; case MARKER_STAR: PlotIndexSetInteger(1, PLOT_ARROW, 172); PlotIndexSetInteger(2, PLOT_ARROW, 172); break; } } else { PlotIndexSetInteger(1, PLOT_ARROW, 32); PlotIndexSetInteger(2, PLOT_ARROW, 32); } //--- Get handle untuk standard ZigZag beserta fallback lokasinya zigzag_handle = iCustom(Symbol(), Period(), "Examples\\ZigZag", InpDepth, InpDeviation, InpBackstep); if(zigzag_handle == INVALID_HANDLE) { // Fallback jika MQL5 menaruh ZigZag langsung di root folder Indicators zigzag_handle = iCustom(Symbol(), Period(), "ZigZag", InpDepth, InpDeviation, InpBackstep); if(zigzag_handle == INVALID_HANDLE) { Print("Gagal memuat indikator ZigZag. Pastikan file ZigZag.ex5 tersedia."); return(INIT_FAILED); } } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(zigzag_handle); DeleteAllFiboObjects(); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if(rates_total < InpDepth) return(0); int start_pos = (prev_calculated > 0) ? prev_calculated - 1 : 0; int to_copy = rates_total - start_pos; double zig_values[]; if(CopyBuffer(zigzag_handle, 0, 0, to_copy, zig_values) <= 0) return(0); //--- Loop untuk memetakan nilai for(int i = start_pos; i < rates_total; i++) { int copy_index = i - start_pos; double zig_val = zig_values[copy_index]; // PERBAIKAN UTAMA: Blokir EMPTY_VALUE (1.79e308) agar garis tidak melesat ke infinity if(zig_val > 0.0 && zig_val != EMPTY_VALUE) { ZigZagBuffer[i] = zig_val; if(zig_val >= high[i]) { HighBuffer[i] = zig_val; LowBuffer[i] = 0.0; } else if(zig_val <= low[i]) { LowBuffer[i] = zig_val; HighBuffer[i] = 0.0; } else { HighBuffer[i] = zig_val; LowBuffer[i] = 0.0; } } else { // Wajib diset 0.0 agar DRAW_SECTION mengabaikan area ini dan menghubungkan pivot ZigZagBuffer[i] = 0.0; HighBuffer[i] = 0.0; LowBuffer[i] = 0.0; } } //--- Gambar Objek Fibonacci DrawFiboLevels(time, rates_total); return(rates_total); } //+------------------------------------------------------------------+ //| Fungsi untuk menggambar Fibonacci level per swing | //+------------------------------------------------------------------+ void DrawFiboLevels(const datetime &time[], int rates_total) { DeleteAllFiboObjects(); int pivots_found = 0; double p_price[100]; datetime p_time[100]; //--- Scan dari bar terbaru ke belakang untuk mencari pivot for(int i = rates_total - 1; i >= 0 && pivots_found < InpFiboHistory + 1; i--) { if(ZigZagBuffer[i] > 0.0 && ZigZagBuffer[i] != EMPTY_VALUE) { p_price[pivots_found] = ZigZagBuffer[i]; p_time[pivots_found] = time[i]; pivots_found++; } } //--- Buat garis Fibo di antara pivot yang ditemukan for(int i = 0; i < pivots_found - 1; i++) { double price2 = p_price[i]; double price1 = p_price[i+1]; datetime time2 = p_time[i]; datetime time1 = p_time[i+1]; double diff = price2 - price1; double lvl_382 = price2 - (diff * 0.382); double lvl_500 = price2 - (diff * 0.500); double lvl_618 = price2 - (diff * 0.618); string base_name = fibo_prefix + TimeToString(time1) + "_"; DrawTrendLine(base_name + "382", time1, lvl_382, time2, lvl_382, InpFibo382, STYLE_DOT); DrawTrendLine(base_name + "500", time1, lvl_500, time2, lvl_500, InpFibo500, STYLE_SOLID); DrawTrendLine(base_name + "618", time1, lvl_618, time2, lvl_618, InpFibo618, STYLE_DOT); } } //+------------------------------------------------------------------+ //| Fungsi pembantu untuk menggambar garis pendek | //+------------------------------------------------------------------+ void DrawTrendLine(string name, datetime t1, double p1, datetime t2, double p2, color clr, ENUM_LINE_STYLE style) { ObjectCreate(0, name, OBJ_TREND, 0, t1, p1, t2, p2); ObjectSetInteger(0, name, OBJPROP_COLOR, clr); ObjectSetInteger(0, name, OBJPROP_STYLE, style); ObjectSetInteger(0, name, OBJPROP_WIDTH, 1); ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false); ObjectSetInteger(0, name, OBJPROP_RAY_LEFT, false); ObjectSetInteger(0, name, OBJPROP_BACK, true); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); } //+------------------------------------------------------------------+ //| Fungsi untuk membersihkan objek Fibonacci | //+------------------------------------------------------------------+ void DeleteAllFiboObjects() { int total = ObjectsTotal(0, 0, OBJ_TREND); for(int i = total - 1; i >= 0; i--) { string name = ObjectName(0, i, 0, OBJ_TREND); if(StringFind(name, fibo_prefix) == 0) { ObjectDelete(0, name); } } } //+------------------------------------------------------------------+