272 lines
9.5 KiB
MQL5
272 lines
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|