4kk4.MQL5/Indicators/Zigzag_Fibo_Structure.mq5
clarissya 2394964283 Scripts
2026-04-27 07:14:01 +07:00

272 行
无行尾
9.5 KiB
MQL5

//+------------------------------------------------------------------+
//| 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);
}
}
}
//+------------------------------------------------------------------+