//+------------------------------------------------------------------+ //| SuperTrend.mq5 | //| eATR + Offset ver | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, FxGeek" #property link "http://www.mql5.com" #property version "1.04" #property indicator_chart_window // プロット: // 0 = Filling // 1 = SuperTrend // 2 = TrendFlag (データウィンドウ用) // 3 = SuperTrend Offset #property indicator_plots 4 // バッファ数 // Filling×2 + SuperTrend×2 + TrendFlag×1 + Offset×1 + 計算用5 = 11 #property indicator_buffers 11 // Plot0: Filling #property indicator_label1 "Filling" #property indicator_type1 DRAW_FILLING #property indicator_color1 clrGray, clrGray // Plot1: SuperTrend (カラーライン) #property indicator_label2 "SuperTrend" #property indicator_type2 DRAW_COLOR_LINE #property indicator_color2 clrGreen, clrRed, clrNONE #property indicator_width2 2 // Plot2: TrendFlag(描画なし・データウィンドウ表示のみ) #property indicator_label3 "TrendFlag (Up=1,Down=0)" #property indicator_type3 DRAW_NONE #property indicator_color3 clrWhite #property indicator_width3 1 // Plot3: OffsetLine(固定色ライン) #property indicator_label4 "SuperTrend Offset" #property indicator_type4 DRAW_LINE #property indicator_style4 STYLE_DOT #property indicator_color4 clrDimGray #property indicator_width4 1 // 中央値の計算方法 enum ENUM_MIDDLE_TYPE { MIDDLE_OPEN, // 始値 MIDDLE_HIGH, // 高値 MIDDLE_LOW, // 安値 MIDDLE_CLOSE, // 終値 MIDDLE_HL, // 高値+安値の平均 MIDDLE_HLC, // 高値+安値+終値の平均 MIDDLE_OHLC, // 始値+高値+安値+終値の平均 MIDDLE_HLCC // 高値+安値+終値x2の平均 }; input int Periode = 10; input double Multiplier = 1.5; input bool Show_Filling = false; // DRAW_FILLINGのON/OFF input ENUM_MIDDLE_TYPE MiddleType = MIDDLE_HLCC; // 中央値の計算方法 // 追加: オフセット設定 input double offsetpips = 80.0; // オフセット(pips). 0以下なら OffsetLine 非表示 input bool offset_reverse = true; // true: 方向を逆にする(買い=上, 売り=下 など) //--- バッファ(プロット順に並べる) double Filled_a[]; // Plot0 buf#0 double Filled_b[]; // Plot0 buf#1 double SuperTrend[]; // Plot1 buf#2 (data) double ColorBuffer[]; // Plot1 buf#3 (color index) double TrendFlag[]; // Plot2 buf#4 (Up=1/Down=0) double OffsetLine[]; // Plot3 buf#5 (data) // 計算用(データウィンドウ非表示) double Atr[]; // buf#6 ← eATR(EMA ATR)を格納 double Up[]; // buf#7 double Down[]; // buf#8 double Middle[]; // buf#9 double trend[]; // buf#10 int changeOfTrend; int flag; int flagh; //+------------------------------------------------------------------+ //| 1pip の価格差を返すヘルパ | //+------------------------------------------------------------------+ double PipPoint(string Currency) { // GOLD(XAUUSDなど)の場合は特別な計算を適用 if (Currency == "XAUUSD" || Currency == "GOLD") { // GOLDの場合の特別な計算(必要に応じて調整) return (0.1); } int SymbolDigits = (int)SymbolInfoInteger(Currency, SYMBOL_DIGITS); switch (SymbolDigits) { case 2: return (0.01); case 3: return (0.01); case 4: return (0.0001); case 5: return (0.0001); } return (0.0); // 不明な場合 } //+------------------------------------------------------------------+ //| OnInit | //+------------------------------------------------------------------+ int OnInit() { // プロット用バッファ SetIndexBuffer(0, Filled_a, INDICATOR_DATA); // Plot0 SetIndexBuffer(1, Filled_b, INDICATOR_DATA); // Plot0 SetIndexBuffer(2, SuperTrend, INDICATOR_DATA); // Plot1 data SetIndexBuffer(3, ColorBuffer, INDICATOR_COLOR_INDEX); // Plot1 color SetIndexBuffer(4, TrendFlag, INDICATOR_DATA); // Plot2 SetIndexBuffer(5, OffsetLine, INDICATOR_DATA); // Plot3 // 計算用バッファ SetIndexBuffer(6, Atr, INDICATOR_CALCULATIONS); SetIndexBuffer(7, Up, INDICATOR_CALCULATIONS); SetIndexBuffer(8, Down, INDICATOR_CALCULATIONS); SetIndexBuffer(9, Middle, INDICATOR_CALCULATIONS); SetIndexBuffer(10, trend, INDICATOR_CALCULATIONS); return (INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| OnCalculate | //+------------------------------------------------------------------+ 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 <= Periode + 2) return (prev_calculated); // バッファ不足時は何もしない //================================================================= // (1) eATR を内部計算(True Range → EMA) //================================================================= double alpha = 2.0 / (Periode + 1.0); // EMA係数 // MQLの price 配列は series (0=最新, rates_total-1=最古) // 最古バーから走査して、Atr[i] = alpha*TR + (1-alpha)*Atr[i+1] とする for (int i = rates_total - 1; i >= 0; i--) { double tr; if (i == rates_total - 1) { // 一番古いバー: 前日終値がないので High-Low のみ tr = high[i] - low[i]; Atr[i] = tr; // 初期値 } else { double range1 = high[i] - low[i]; double range2 = MathAbs(high[i] - close[i + 1]); double range3 = MathAbs(low[i] - close[i + 1]); tr = MathMax(range1, MathMax(range2, range3)); // EMA で平滑化した eATR Atr[i] = alpha * tr + (1.0 - alpha) * Atr[i + 1]; } } //================================================================= // (2) SuperTrend 本体計算 //================================================================= // 計算開始インデックス int first; if (prev_calculated > rates_total || prev_calculated <= 0) { first = Periode; // 初期区間は未定義表示にしておく for (int k = 0; k < first && k < rates_total; ++k) { Filled_a[k] = EMPTY_VALUE; Filled_b[k] = EMPTY_VALUE; SuperTrend[k] = EMPTY_VALUE; TrendFlag[k] = EMPTY_VALUE; OffsetLine[k] = EMPTY_VALUE; } } else { first = prev_calculated - 1; } const double pip = PipPoint(_Symbol); // 本体ループ for (int i = first; i < rates_total && !IsStopped(); i++) { // --- 中央値 ------------------------------------------------- switch (MiddleType) { case MIDDLE_OPEN: Middle[i] = open[i]; break; case MIDDLE_HIGH: Middle[i] = high[i]; break; case MIDDLE_LOW: Middle[i] = low[i]; break; case MIDDLE_CLOSE: Middle[i] = close[i]; break; case MIDDLE_HL: Middle[i] = (high[i] + low[i]) / 2.0; break; case MIDDLE_HLC: Middle[i] = (high[i] + low[i] + close[i]) / 3.0; break; case MIDDLE_OHLC: Middle[i] = (open[i] + high[i] + low[i] + close[i]) / 4.0; break; case MIDDLE_HLCC: Middle[i] = (high[i] + low[i] + 2.0 * close[i]) / 4.0; break; } // --- eATR を使用した Up/Down バンド ------------------------ Up[i] = Middle[i] + (Multiplier * Atr[i]); Down[i] = Middle[i] - (Multiplier * Atr[i]); // --- トレンド判定 ------------------------------------------ if (close[i] > Up[i - 1]) { trend[i] = 1; if (trend[i - 1] == -1) changeOfTrend = 1; } else if (close[i] < Down[i - 1]) { trend[i] = -1; if (trend[i - 1] == 1) changeOfTrend = 1; } else if (trend[i - 1] == 1) { trend[i] = 1; changeOfTrend = 0; } else if (trend[i - 1] == -1) { trend[i] = -1; changeOfTrend = 0; } // --- 交差フラグ -------------------------------------------- flag = (trend[i] < 0 && trend[i - 1] > 0) ? 1 : 0; flagh = (trend[i] > 0 && trend[i - 1] < 0) ? 1 : 0; // --- バンドの継続補正 -------------------------------------- if (trend[i] > 0 && Down[i] < Down[i - 1]) Down[i] = Down[i - 1]; if (trend[i] < 0 && Up[i] > Up[i - 1]) Up[i] = Up[i - 1]; if (flag == 1) Up[i] = Middle[i] - (-Multiplier * Atr[i]); // = Middle + Multiplier*ATR if (flagh == 1) Down[i] = Middle[i] + (-Multiplier * Atr[i]); // = Middle - Multiplier*ATR // --- SuperTrend と色 ---------------------------------------- if (trend[i] == 1) { SuperTrend[i] = Down[i]; if (changeOfTrend == 1) { SuperTrend[i - 1] = SuperTrend[i - 2]; // OffsetLine も一つ前をつなげてギャップを抑える OffsetLine[i - 1] = OffsetLine[i - 2]; changeOfTrend = 0; ColorBuffer[i] = 2.0; // 無色 ColorBuffer[i - 1] = 2.0; // 無色 } else { ColorBuffer[i] = 0.0; // Green } } else // trend[i] == -1 { SuperTrend[i] = Up[i]; if (changeOfTrend == 1) { SuperTrend[i - 1] = SuperTrend[i - 2]; OffsetLine[i - 1] = OffsetLine[i - 2]; changeOfTrend = 0; ColorBuffer[i] = 2.0; // 無色 ColorBuffer[i - 1] = 2.0; // 無色 } else { ColorBuffer[i] = 1.0; // Red } } // --- TrendFlag: Up=1 / Down=0 ------------------------------ TrendFlag[i] = (trend[i] == 1) ? 1.0 : 0.0; // --- OffsetLine(offsetpips<=0なら非表示) ---------------- if (offsetpips > 0.0) { double dir; if (trend[i] == 1) // 買いトレンド { // 通常: 下側 / 逆方向: 上側 dir = offset_reverse ? 1.0 : -1.0; } else // 売りトレンド { // 通常: 上側 / 逆方向: 下側 dir = offset_reverse ? -1.0 : 1.0; } OffsetLine[i] = SuperTrend[i] + dir * offsetpips * pip; } else { OffsetLine[i] = EMPTY_VALUE; } // --- Filling の可否 ---------------------------------------- if (Show_Filling) { Filled_a[i] = SuperTrend[i]; Filled_b[i] = close[i]; } else { Filled_a[i] = EMPTY_VALUE; Filled_b[i] = EMPTY_VALUE; } } return (rates_total); } //+------------------------------------------------------------------+