/* * Multiple Timeframe Breakout Sample */ // a link to the company website #property link "" // the company name #property copyright "" // サブウィンドウ上に指標を表示する. #property indicator_separate_window // 表示する指標の数. #property indicator_buffers 8 // 線の色 #property indicator_color1 Blue #property indicator_color2 Red #property indicator_color3 Blue #property indicator_color4 Red #property indicator_color5 Blue #property indicator_color6 Red #property indicator_color7 Blue #property indicator_color8 Red /* * http://docs.mql4.com/basis/preprosessor/compilation */ #property indicator_minimum 0 #property indicator_maximum 5 #property indicator_level1 1 #property indicator_level2 2 #property indicator_level3 3 #property indicator_level4 4 /* * 外部変数. */ // output file name. extern string OUTPUT_FILE_NAME = "SampleMultipleTimeframeBreakout.log"; // debug extern bool DEBUG = false; // Timeframes. extern int TIMEFRAME_1 = PERIOD_M1; extern int TIMEFRAME_2 = PERIOD_M5; extern int TIMEFRAME_3 = PERIOD_M15; extern int TIMEFRAME_4 = PERIOD_M30; // Period. extern int PERIOD = 21; // 表示用のバッファ. double BUFFER_BREAK_TOP_1[]; double BUFFER_BREAK_BOTTOM_1[]; double BUFFER_BREAK_TOP_2[]; double BUFFER_BREAK_BOTTOM_2[]; double BUFFER_BREAK_TOP_3[]; double BUFFER_BREAK_BOTTOM_3[]; double BUFFER_BREAK_TOP_4[]; double BUFFER_BREAK_BOTTOM_4[]; string SHORT_NAME; string OBJECT_NAME_LABEL_1; string OBJECT_NAME_LABEL_2; string OBJECT_NAME_LABEL_3; string OBJECT_NAME_LABEL_4; /* * 初期化処理. * チャートを表示するときに実行する. */ int init() { outputInfo("start 'init' function"); // break top 1 SetIndexBuffer(0, BUFFER_BREAK_TOP_1); SetIndexStyle(0, DRAW_ARROW); SetIndexArrow(0, SYMBOL_ARROWUP); // break bottom SetIndexBuffer(1, BUFFER_BREAK_BOTTOM_1); SetIndexStyle(1, DRAW_ARROW); SetIndexArrow(1, SYMBOL_ARROWDOWN); // break top 2 SetIndexBuffer(2, BUFFER_BREAK_TOP_2); SetIndexStyle(2, DRAW_ARROW); SetIndexArrow(2, SYMBOL_ARROWUP); // break bottom 2 SetIndexBuffer(3, BUFFER_BREAK_BOTTOM_2); SetIndexStyle(3, DRAW_ARROW); SetIndexArrow(3, SYMBOL_ARROWDOWN); // break top 3 SetIndexBuffer(4, BUFFER_BREAK_TOP_3); SetIndexStyle(4, DRAW_ARROW); SetIndexArrow(4, SYMBOL_ARROWUP); // break bottom 3 SetIndexBuffer(5, BUFFER_BREAK_BOTTOM_3); SetIndexStyle(5, DRAW_ARROW); SetIndexArrow(5, SYMBOL_ARROWDOWN); // break top 4 SetIndexBuffer(6, BUFFER_BREAK_TOP_4); SetIndexStyle(6, DRAW_ARROW); SetIndexArrow(6, SYMBOL_ARROWUP); // break bottom 4 SetIndexBuffer(7, BUFFER_BREAK_BOTTOM_4); SetIndexStyle(7, DRAW_ARROW); SetIndexArrow(7, SYMBOL_ARROWDOWN); string key = TimeToStr(TimeLocal(), TIME_DATE|TIME_SECONDS); // http://docs.mql4.com/windows/WindowExpertName SHORT_NAME = WindowExpertName() + "_" + key; // http://docs.mql4.com/customind/IndicatorShortName IndicatorShortName(SHORT_NAME); OBJECT_NAME_LABEL_1 = "TIMEFRAME_1_" + key; OBJECT_NAME_LABEL_2 = "TIMEFRAME_2_" + key; OBJECT_NAME_LABEL_3 = "TIMEFRAME_3_" + key; OBJECT_NAME_LABEL_4 = "TIMEFRAME_4_" + key; outputInfo("finish 'init' function"); return(0); } /* * 後処理. * チャートから削除するときに実行する. */ int deinit() { outputInfo("start 'deinit' function"); ObjectDelete(OBJECT_NAME_LABEL_1); ObjectDelete(OBJECT_NAME_LABEL_2); ObjectDelete(OBJECT_NAME_LABEL_3); ObjectDelete(OBJECT_NAME_LABEL_4); outputInfo("finish 'deinit' function"); return(0); } /* * 基本処理. * 次の tick が決まるたびに実行する. */ int start() { outputInfo("start 'start' function"); showLabels(); int countingBars = getCountingBars(); string message; datetime currentPeriodTime; int specifiedPeriodIndex; // 過去から現在に向かってバーのインデックスを移動する. for (int i = countingBars - 1; i >= 0; i--) { // 一定期間過去の値を取得して指標バッファに設定する. BUFFER_BREAK_TOP_1[i] = getBreakTop(i, TIMEFRAME_1, 1); BUFFER_BREAK_BOTTOM_1[i] = getBreakBottom(i, TIMEFRAME_1, 1); BUFFER_BREAK_TOP_2[i] = getBreakTop(i, TIMEFRAME_2, 2); BUFFER_BREAK_BOTTOM_2[i] = getBreakBottom(i, TIMEFRAME_2, 2); BUFFER_BREAK_TOP_3[i] = getBreakTop(i, TIMEFRAME_3, 3); BUFFER_BREAK_BOTTOM_3[i] = getBreakBottom(i, TIMEFRAME_3, 3); BUFFER_BREAK_TOP_4[i] = getBreakTop(i, TIMEFRAME_4, 4); BUFFER_BREAK_BOTTOM_4[i] = getBreakBottom(i, TIMEFRAME_4, 4); } outputInfo("finish 'start' function"); return(0); } int getSelfWindowIndex() { // http://docs.mql4.com/windows/WindowFind int windowIndex = WindowFind(SHORT_NAME); return(windowIndex); } void showLabels() { int windowIndex = getSelfWindowIndex(); datetime positionDatetime = iTime(NULL, 0, 0); double positionPrice = 1; showLabel(OBJECT_NAME_LABEL_1, windowIndex, positionDatetime, 1, createLabelText(TIMEFRAME_1)); showLabel(OBJECT_NAME_LABEL_2, windowIndex, positionDatetime, 2, createLabelText(TIMEFRAME_2)); showLabel(OBJECT_NAME_LABEL_3, windowIndex, positionDatetime, 3, createLabelText(TIMEFRAME_3)); showLabel(OBJECT_NAME_LABEL_4, windowIndex, positionDatetime, 4, createLabelText(TIMEFRAME_4)); } string createLabelText(int targetTimeframe) { if (targetTimeframe == PERIOD_M1) { return("M1"); } else if (targetTimeframe == PERIOD_M5) { return("M5"); } else if (targetTimeframe == PERIOD_M15) { return("M15"); } else if (targetTimeframe == PERIOD_M30) { return("M30"); } else if (targetTimeframe == PERIOD_H1) { return("H1"); } else if (targetTimeframe == PERIOD_H4) { return("H4"); } else if (targetTimeframe == PERIOD_D1) { return("D1"); } else if (targetTimeframe == PERIOD_W1) { return("W1"); } else if (targetTimeframe == PERIOD_MN1) { return("MN1"); } else { return("Undefined"); } } void showLabel(string objectName, int windowIndex, datetime positionDatetime, double positionPrice, string label) { if (ObjectFind(objectName) == -1) { if (!ObjectCreate(objectName, OBJ_TEXT, windowIndex, positionDatetime, positionPrice)) { outputError(StringConcatenate("Cannot create object. [name:", objectName, "][error", GetLastError(), "]")); return; } } if (!ObjectSetText(objectName, label, 12, "Arial", Lime)) { outputError(StringConcatenate("Cannot set text. [name:", objectName, "][error", GetLastError(), "]")); } } double getCloseValue(int index) { double value = iClose(Symbol(), 0, index); return(value); } double getBreakTop(int index, int timeframe, double returnValue) { double currentValue = getCloseValue(index + 1); datetime currentPeriodTime = currentPeriodIndex2Time(index + 1); int specifiedPeriodIndex = time2SpecifiedPeriodIndex(currentPeriodTime, timeframe); double highestValue = getHighest(specifiedPeriodIndex + 1, timeframe); outputInfo(createMessage(index, currentValue)); outputInfo(createMessage(index, highestValue)); if (currentValue > highestValue) { return(returnValue); } else { return(EMPTY_VALUE); } } double getBreakBottom(int index, int timeframe, double returnValue) { double currentValue = getCloseValue(index + 1); datetime currentPeriodTime = currentPeriodIndex2Time(index + 1); int specifiedPeriodIndex = time2SpecifiedPeriodIndex(currentPeriodTime, timeframe); double lowestValue = getLowest(specifiedPeriodIndex + 1, timeframe); outputInfo(createMessage(index, currentValue)); outputInfo(createMessage(index, lowestValue)); if (currentValue < lowestValue) { return(returnValue); } else { return(EMPTY_VALUE); } } /* * 指定したインデックスを含む一定期間の中の最大値(終値の中で)を返す. */ double getHighest(int index, int timeframe) { int startIndex = index; int highestIndex = iHighest( Symbol(), // 通貨ペア名 timeframe, // 時間枠 MODE_CLOSE, // Series array identifier. PERIOD, // Number of periods startIndex); double highest = iClose(Symbol(), timeframe, highestIndex); return(highest); } /* * 指定したインデックスを含む一定期間の中の最小値(終値の中で)を返す. */ double getLowest(int index, int timeframe) { int startIndex = index; int lowestIndex = iLowest( Symbol(), // 通貨ペア名 timeframe, // 時間枠 MODE_CLOSE, // Series array identifier. PERIOD, // Number of periods startIndex); double lowest = iClose(Symbol(), timeframe, lowestIndex); return(lowest); } /* * 指定した時刻、時間枠からインデックスを返す. */ int time2SpecifiedPeriodIndex(datetime time, int timeframe) { int index = iBarShift( Symbol(), // Symbol the data of which should be used to calculate indicator. NULL means the current symbol. timeframe, // Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe. time, // value to find (bar's open time). false); // Return mode when bar not found. false - iBarShift returns nearest. true - iBarShift returns -1. datetime specifiedPeriodTime = iTime(Symbol(), timeframe, index); string message = StringConcatenate( "specified period time:", datetime2String(specifiedPeriodTime)); outputInfo(message); return(index); } /* * 現在の時間枠でのインデックスから対応する時刻を返す. */ datetime currentPeriodIndex2Time(int index) { datetime currentTime = iTime(Symbol(), 0, index); string currentTimeString = datetime2String(currentTime); string message = StringConcatenate( "current period time:", currentTimeString); outputInfo(message); return(currentTime); } /* * メッセージを作る. * format * symbol, datetime, price */ string createMessage(int index, double price) { string symbolString = Symbol(); string datetimeString = datetime2String( iTime(symbolString, 0, index)); string priceString = DoubleToStr( price, Digits); string message = StringConcatenate( symbolString, ",", datetimeString, ",", priceString); return(message); } /* * 日時から文字列に変換する */ string datetime2String(datetime dt) { string value = TimeToStr(dt, TIME_DATE | TIME_SECONDS); return(value); } /* * ファイルに出力する. */ void outputInfo(string message) { output("info", message); } void outputError(string message) { output("error", message); } void output(string level, string message) { if (!DEBUG) { return; } int handle = openFile(); if (handle == -1) { return; } writeFile(handle, level, message); closeFile(handle); } /* * 今回計算するバーの数を返す. */ int getCountingBars() { // チャート上のバーの数. int bars = Bars; // 変化のなかったバーの数. int countedBars = IndicatorCounted(); if (countedBars < 0) { return(0); } // 今回計算するバーの数. int countingBars = bars - countedBars - 1; return(countingBars); } /* * ファイルを開く. * return file handle. * not -1 : opened file * -1 : fail */ int openFile() { int handle = FileOpen(OUTPUT_FILE_NAME, FILE_CSV|FILE_READ|FILE_WRITE, ","); if (handle != -1) { FileSeek(handle, 0, SEEK_END); } else { int errorCode = GetLastError(); Print("Cannot open file. [name:", OUTPUT_FILE_NAME, "][errorCode:", errorCode, "]"); } return(handle); } /* * ファイルを閉じる. */ void closeFile(int handle) { FileClose(handle); } /* * ファイルに文字列を書く. */ void writeFile(int handle, string typeName, string message) { datetime current = TimeCurrent(); int result = FileWrite( handle, datetime2String(current), typeName, message); if (result >= 0) { FileFlush(handle); return; } int errorCode = GetLastError(); Print("Cannot write file. [name:", OUTPUT_FILE_NAME, "][errorCode:", errorCode, "]"); return; }