Files

366 lines
21 KiB
Plaintext
Raw Permalink Normal View History

//+------------------------------------------------------------------+
//| SuperTrend.mq5 |
//| Copyright 2011, FxGeek |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2011, FxGeek"
#property link "http://www.mql5.com"
#property version "1.03"
#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 = 2.0;
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
double Up[]; // buf#7
double Down[]; // buf#8
double Middle[]; // buf#9
double trend[]; // buf#10
int atrHandle;
int changeOfTrend;
int flag;
int flagh;
//+------------------------------------------------------------------+
//| 1pip の価格差を返すヘルパ |
//+------------------------------------------------------------------+
double PipPoint(string Currency)
{
// GOLD(XAUUSDなど)の場合は特別な計算を適用
if (Currency == "XAUUSD" || Currency == "GOLD")
{
// GOLDの場合の特別な計算
return (0.1); // ここでGOLDに適した値に変更
}
// MQL5ではSymbolInfoIntegerを使用して桁数を取得
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); // 桁数が一致しない場合は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);
atrHandle = iATR(_Symbol, _Period, Periode);
if (atrHandle == INVALID_HANDLE)
{
Print(__FUNCTION__, ": iATR handle error. err=", GetLastError());
return (INIT_FAILED);
}
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); // バッファ不足時は何もしない
// ATR コピー本数の算定
int to_copy;
if (prev_calculated > rates_total || prev_calculated < 0)
to_copy = rates_total;
else
{
to_copy = rates_total - prev_calculated;
if (prev_calculated > 0)
to_copy++;
}
if (IsStopped())
return (prev_calculated);
if (CopyBuffer(atrHandle, 0, 0, to_copy, Atr) <= 0)
{
Print("Getting ATR failed. err=", GetLastError());
return (prev_calculated);
}
// 計算開始インデックス
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;
}
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;
// OffsetLineoffsetpips<=0なら非表示)
if (offsetpips > 0.0)
{
// 買い/売りごとに、offset_reverse で方向を切り替え
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);
}
//+------------------------------------------------------------------+