250 lines
No EOL
23 KiB
MQL5
250 lines
No EOL
23 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| KG Standard Deviation Level V.1.1.mq5 |
|
|
//| Copyright © 2024, Dibuat oleh Asisten AI Gemini |
|
|
//| Modifikasi dari konsep umum |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright © 2024, Asisten AI Gemini"
|
|
#property link ""
|
|
#property version "1.00"
|
|
|
|
#property indicator_chart_window
|
|
#property indicator_buffers 9 // Pivot + 4x2 Level SD
|
|
#property indicator_plots 9
|
|
|
|
//--- Input Parameter
|
|
input ENUM_TIMEFRAMES myPeriod = PERIOD_D1; // Multiplier Deviasi Standar Level 1
|
|
input double SD_Mult1 = 0.5; // Deviasi Standar Level 1
|
|
input double SD_Mult2 = 1.0; // Deviasi Standar Level 2
|
|
input double SD_Mult3 = 1.5; // Deviasi Standar Level 3
|
|
input double SD_Mult4 = 2.0; // Deviasi Standar Level 4
|
|
|
|
//--- Plot Properti untuk Pivot Point
|
|
#property indicator_label1 "Pivot Point"
|
|
#property indicator_type1 DRAW_LINE
|
|
#property indicator_color1 clrLime
|
|
#property indicator_style1 STYLE_SOLID
|
|
#property indicator_width1 2
|
|
|
|
//--- Plot Properti untuk Level Deviasi Atas (Upper)
|
|
#property indicator_label2 "Pivot +SD1"
|
|
#property indicator_type2 DRAW_LINE
|
|
#property indicator_color2 clrGreen
|
|
#property indicator_style2 STYLE_DOT
|
|
#property indicator_width2 1
|
|
|
|
#property indicator_label3 "Pivot -SD1"
|
|
#property indicator_type3 DRAW_LINE
|
|
#property indicator_color3 clrGreen
|
|
#property indicator_style3 STYLE_DOT
|
|
#property indicator_width3 1
|
|
|
|
#property indicator_label4 "Pivot +SD2"
|
|
#property indicator_type4 DRAW_LINE
|
|
#property indicator_color4 clrLimeGreen
|
|
#property indicator_style4 STYLE_DOT
|
|
#property indicator_width4 1
|
|
|
|
#property indicator_label5 "Pivot -SD2"
|
|
#property indicator_type5 DRAW_LINE
|
|
#property indicator_color5 clrLimeGreen
|
|
#property indicator_style5 STYLE_DOT
|
|
#property indicator_width5 1
|
|
|
|
#property indicator_label6 "Pivot +SD3"
|
|
#property indicator_type6 DRAW_LINE
|
|
#property indicator_color6 clrSeaGreen
|
|
#property indicator_style6 STYLE_DOT
|
|
#property indicator_width6 1
|
|
|
|
#property indicator_label7 "Pivot -SD3"
|
|
#property indicator_type7 DRAW_LINE
|
|
#property indicator_color7 clrSeaGreen
|
|
#property indicator_style7 STYLE_DOT
|
|
#property indicator_width7 1
|
|
|
|
#property indicator_label8 "Pivot +SD4"
|
|
#property indicator_type8 DRAW_LINE
|
|
#property indicator_color8 clrDarkGreen
|
|
#property indicator_style8 STYLE_DOT
|
|
#property indicator_width8 1
|
|
|
|
#property indicator_label9 "Pivot -SD4"
|
|
#property indicator_type9 DRAW_LINE
|
|
#property indicator_color9 clrDarkGreen
|
|
#property indicator_style9 STYLE_DOT
|
|
#property indicator_width9 1
|
|
|
|
|
|
//--- Buffers Indikator
|
|
double PivotBuffer[];
|
|
double UpperSD1Buffer[];
|
|
double LowerSD1Buffer[];
|
|
double UpperSD2Buffer[];
|
|
double LowerSD2Buffer[];
|
|
double UpperSD3Buffer[];
|
|
double LowerSD3Buffer[];
|
|
double UpperSD4Buffer[];
|
|
double LowerSD4Buffer[];
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Fungsi inisialisasi indikator kustom |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
SetIndexBuffer(0, PivotBuffer, INDICATOR_DATA); PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(0, PLOT_LABEL, "Pivot Point");
|
|
|
|
SetIndexBuffer(1, UpperSD1Buffer, INDICATOR_DATA); PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(1, PLOT_LABEL, "Pivot +" + DoubleToString(SD_Mult1,1) + " SD");
|
|
SetIndexBuffer(2, LowerSD1Buffer, INDICATOR_DATA); PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(2, PLOT_LABEL, "Pivot -" + DoubleToString(SD_Mult1,1) + " SD");
|
|
|
|
SetIndexBuffer(3, UpperSD2Buffer, INDICATOR_DATA); PlotIndexSetDouble(3, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(3, PLOT_LABEL, "Pivot +" + DoubleToString(SD_Mult2,1) + " SD");
|
|
SetIndexBuffer(4, LowerSD2Buffer, INDICATOR_DATA); PlotIndexSetDouble(4, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(4, PLOT_LABEL, "Pivot -" + DoubleToString(SD_Mult2,1) + " SD");
|
|
|
|
SetIndexBuffer(5, UpperSD3Buffer, INDICATOR_DATA); PlotIndexSetDouble(5, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(5, PLOT_LABEL, "Pivot +" + DoubleToString(SD_Mult3,1) + " SD");
|
|
SetIndexBuffer(6, LowerSD3Buffer, INDICATOR_DATA); PlotIndexSetDouble(6, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(6, PLOT_LABEL, "Pivot -" + DoubleToString(SD_Mult3,1) + " SD");
|
|
|
|
SetIndexBuffer(7, UpperSD4Buffer, INDICATOR_DATA); PlotIndexSetDouble(7, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(7, PLOT_LABEL, "Pivot +" + DoubleToString(SD_Mult4,1) + " SD");
|
|
SetIndexBuffer(8, LowerSD4Buffer, INDICATOR_DATA); PlotIndexSetDouble(8, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
|
PlotIndexSetString(8, PLOT_LABEL, "Pivot -" + DoubleToString(SD_Mult4,1) + " SD");
|
|
|
|
IndicatorSetString(INDICATOR_SHORTNAME, "PivotDev(" + DoubleToString(SD_Mult1,1) + "," + DoubleToString(SD_Mult4,1) + ")");
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fungsi deinisialisasi indikator |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
Comment(""); // Membersihkan komentar saat indikator dihapus
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Fungsi perhitungan indikator kustom |
|
|
//+------------------------------------------------------------------+
|
|
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[])
|
|
{
|
|
int start_idx;
|
|
if(prev_calculated == 0) // Perhitungan pertama
|
|
{
|
|
// Inisialisasi semua buffer dengan EMPTY_VALUE
|
|
ArrayInitialize(PivotBuffer, EMPTY_VALUE); ArrayInitialize(UpperSD1Buffer, EMPTY_VALUE);
|
|
ArrayInitialize(LowerSD1Buffer, EMPTY_VALUE); ArrayInitialize(UpperSD2Buffer, EMPTY_VALUE);
|
|
ArrayInitialize(LowerSD2Buffer, EMPTY_VALUE); ArrayInitialize(UpperSD3Buffer, EMPTY_VALUE);
|
|
ArrayInitialize(LowerSD3Buffer, EMPTY_VALUE); ArrayInitialize(UpperSD4Buffer, EMPTY_VALUE);
|
|
ArrayInitialize(LowerSD4Buffer, EMPTY_VALUE);
|
|
start_idx = 1; // Mulai dari bar kedua karena kita butuh data hari sebelumnya
|
|
// Bar paling awal (indeks 0) tidak akan punya data hari sebelumnya
|
|
}
|
|
else
|
|
{
|
|
start_idx = prev_calculated - 1;
|
|
if(start_idx < 1) start_idx = 1; // Pastikan tidak kurang dari 1
|
|
}
|
|
|
|
// Array untuk menampung data Harian (D1)
|
|
double prev_high_D1[1], prev_low_D1[1], prev_close_D1[1];
|
|
|
|
for(int i = start_idx; i < rates_total; i++)
|
|
{
|
|
// 1. Dapatkan shift bar D1 yang sesuai untuk bar 'time[i]' saat ini
|
|
// Kita ingin data D1 dari HARI SEBELUMNYA relatif terhadap time[i]
|
|
// Jadi, kita cari bar D1 yang time[i] jatuh di dalamnya, lalu ambil data dari bar D1 SEBELUMNYA lagi.
|
|
|
|
datetime current_bar_day_start = time[i] - (time[i] % 86400); // Awal hari dari bar saat ini
|
|
datetime prev_day_for_data = current_bar_day_start - 86400; // Awal hari dari hari sebelumnya yang datanya kita inginkan
|
|
|
|
// Dapatkan shift untuk hari sebelumnya tersebut pada timeframe D1
|
|
int shift_D1_prev = iBarShift(_Symbol, myPeriod, prev_day_for_data, false);
|
|
|
|
bool data_ok = false;
|
|
if(shift_D1_prev != -1) // Pastikan iBarShift berhasil
|
|
{
|
|
// Ambil data HLC dari bar D1 hari sebelumnya
|
|
if(CopyHigh(_Symbol, myPeriod, shift_D1_prev, 1, prev_high_D1) == 1 &&
|
|
CopyLow(_Symbol, myPeriod, shift_D1_prev, 1, prev_low_D1) == 1 &&
|
|
CopyClose(_Symbol, myPeriod, shift_D1_prev, 1, prev_close_D1) == 1)
|
|
{
|
|
data_ok = true;
|
|
}
|
|
}
|
|
|
|
if(data_ok)
|
|
{
|
|
double H_prev = prev_high_D1[0];
|
|
double L_prev = prev_low_D1[0];
|
|
double C_prev = prev_close_D1[0];
|
|
|
|
// Hitung Pivot Point Klasik
|
|
double pivot = (H_prev + L_prev + C_prev + C_prev) / 4.0;
|
|
|
|
/*
|
|
//Hitung "Range" sebagai basis untuk deviasi (bisa diganti dengan StdDev aktual jika diinginkan)
|
|
// Untuk kesederhanaan, kita gunakan Range (H-L) hari sebelumnya sebagai proxy volatilitas
|
|
// StdDev aktual akan melibatkan lebih banyak kalkulasi (rata-rata, lalu sum of squares, etc.)
|
|
double daily_range = H_prev - L_prev;
|
|
|
|
// Jika daily_range terlalu kecil atau tidak valid, hindari pembagian dengan nol atau nilai aneh
|
|
if (daily_range <= _Point * 5) // Jika range sangat kecil, mungkin tidak ada volatilitas
|
|
{
|
|
daily_range = _Point * 5; // Default ke range minimal untuk stabilitas
|
|
}
|
|
*/
|
|
|
|
double PA = pivot; //(C_prev + C_prev + L_prev + H_prev) / 4.0;
|
|
double S_val = 2 * MathPow(C_prev - PA, 2) + MathPow(L_prev - PA, 2) + MathPow(H_prev - PA, 2);
|
|
double StdDev_component = (S_val >= 0) ? MathSqrt(S_val / 3.0) : 0; // Pastikan S_val tidak negatif
|
|
|
|
double P2_dev = SD_Mult1 * StdDev_component;
|
|
double P3_dev = SD_Mult2 * StdDev_component;
|
|
double P4_dev = SD_Mult3 * StdDev_component;
|
|
double P5_dev = SD_Mult4 * StdDev_component;
|
|
|
|
// Simpan nilai pivot ke buffer untuk digambar
|
|
// Nilai pivot dan SD ini valid untuk SELURUH bar pada time[i] yang jatuh pada hari 'current_bar_day_start'
|
|
PivotBuffer[i] = pivot;
|
|
UpperSD1Buffer[i] = pivot + P2_dev;
|
|
LowerSD1Buffer[i] = pivot - P2_dev;
|
|
UpperSD2Buffer[i] = pivot + P3_dev;
|
|
LowerSD2Buffer[i] = pivot - P3_dev;
|
|
UpperSD3Buffer[i] = pivot + P4_dev;
|
|
LowerSD3Buffer[i] = pivot - P4_dev;
|
|
UpperSD4Buffer[i] = pivot + P5_dev;
|
|
LowerSD4Buffer[i] = pivot - P5_dev;
|
|
}
|
|
else // Jika data D1 hari sebelumnya tidak tersedia
|
|
{
|
|
// Jika bar sebelumnya memiliki nilai, teruskan. Jika tidak, biarkan EMPTY_VALUE.
|
|
// Ini membantu garis tetap terlihat jika ada lubang data sementara.
|
|
PivotBuffer[i] = (i > 0 && PivotBuffer[i-1] != EMPTY_VALUE) ? PivotBuffer[i-1] : EMPTY_VALUE;
|
|
UpperSD1Buffer[i] = (i > 0 && UpperSD1Buffer[i-1] != EMPTY_VALUE) ? UpperSD1Buffer[i-1] : EMPTY_VALUE;
|
|
LowerSD1Buffer[i] = (i > 0 && LowerSD1Buffer[i-1] != EMPTY_VALUE) ? LowerSD1Buffer[i-1] : EMPTY_VALUE;
|
|
UpperSD2Buffer[i] = (i > 0 && UpperSD2Buffer[i-1] != EMPTY_VALUE) ? UpperSD2Buffer[i-1] : EMPTY_VALUE;
|
|
LowerSD2Buffer[i] = (i > 0 && LowerSD2Buffer[i-1] != EMPTY_VALUE) ? LowerSD2Buffer[i-1] : EMPTY_VALUE;
|
|
UpperSD3Buffer[i] = (i > 0 && UpperSD3Buffer[i-1] != EMPTY_VALUE) ? UpperSD3Buffer[i-1] : EMPTY_VALUE;
|
|
LowerSD3Buffer[i] = (i > 0 && LowerSD3Buffer[i-1] != EMPTY_VALUE) ? LowerSD3Buffer[i-1] : EMPTY_VALUE;
|
|
UpperSD4Buffer[i] = (i > 0 && UpperSD4Buffer[i-1] != EMPTY_VALUE) ? UpperSD4Buffer[i-1] : EMPTY_VALUE;
|
|
LowerSD4Buffer[i] = (i > 0 && LowerSD4Buffer[i-1] != EMPTY_VALUE) ? LowerSD4Buffer[i-1] : EMPTY_VALUE;
|
|
|
|
if (i == rates_total -1) { // Pesan hanya untuk bar terakhir jika ada masalah
|
|
Comment("PivotDev: Data D1 hari sebelumnya tidak tersedia untuk bar " + TimeToString(time[i]));
|
|
}
|
|
}
|
|
}
|
|
return(rates_total);
|
|
}
|
|
//+------------------------------------------------------------------+ |