日本時間の高値安値の半値を表示させるインジケータを作ってみた。
3つ前までの半値インジケータの線が効いている
半値をローソク足が離れたら、そっちの方向が優勢ってことでついていくのが基本だ。 しかし、途中で半値を下回ったら、何か異変ありということで、逆方向にヘッジを入れて、そのまま逆方向に行ってしまったら最初のポジションを外して、逆方向のポジションを増やそう。稀に、さらにもとに戻ることがあるが、その時も、ヘッジを入れて、様子見していくが、あまりそういうことは起きないと思う。
//+------------------------------------------------------------------+ //| TimeHorizontalLine.mq5 | //| Copyright 2024, Hayashi Kuniyuki | //| https://java.boy.jp/pukiwiki/index.php?%E3%80%90MQL5%E3%80%91Ku | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Hayashi Kuniyuki" #property link "https://java.boy.jp/pukiwiki/index.php?%E3%80%90MQL5%E3%80%91Ku" #property version "1.00" #property indicator_chart_window #property indicator_plots 1 #property indicator_buffers 1 //--- 入力パラメータ // input double LineLevel = 153.05; // ライン位置 input color LineColor = clrRed; // ライン色 input int LineStyle = STYLE_SOLID; // ラインスタイル input int LineWidth = 1; // ライン幅 input int targetCount = 6000; // 何個前のデータを対象とするか //--- グローバル変数 string lineName; //+------------------------------------------------------------------+ //| TimeSpan クラス - HH:MM形式の時間を扱う | //+------------------------------------------------------------------+ class TimeSpan { private: int m_hours; // 時間 int m_minutes; // 分 bool m_isValid; // 有効な時間かどうか public: // コンストラクタ TimeSpan(string timeStr) { m_hours = 0; m_minutes = 0; m_isValid = false; // "HH:MM" 形式から時間と分を抽出 string parts[]; StringSplit(timeStr, ':', parts); if(ArraySize(parts) == 2) { m_hours = (int)StringToInteger(parts[0]); m_minutes = (int)StringToInteger(parts[1]); m_isValid = m_hours >= 0 && m_minutes >= 0 && m_minutes < 60; } if(!m_isValid) { Print("Invalid time format: ", timeStr, ". Expected format: HH:MM"); } } bool isEqual(datetime checkTime) { MqlDateTime timeStruct; TimeToStruct(checkTime, timeStruct); return(timeStruct.hour == m_hours && timeStruct.min == m_minutes); } // 秒数に変換 int ToSeconds() const { return (m_hours * 3600) + (m_minutes * 60); } // 有効な時間かどうかを確認 bool IsValid() const { return m_isValid; } // 文字列表現を取得 string ToString() const { return StringFormat("%02d:%02d", m_hours, m_minutes); } }; //+------------------------------------------------------------------+ //| 時間計算用のヘルパーメソッド | //+------------------------------------------------------------------+ datetime minus(datetime baseTime, string timeStr) { TimeSpan span(timeStr); if(!span.IsValid()) return baseTime; return baseTime - span.ToSeconds(); } datetime plus(datetime baseTime, string timeStr) { TimeSpan span(timeStr); if(!span.IsValid()) return baseTime; return baseTime + span.ToSeconds(); } //+------------------------------------------------------------------+ //| 指定期間の高値と安値を取得する | //+------------------------------------------------------------------+ void GetHighLowPrices(datetime startTime, datetime endTime, double &highPrice, double &lowPrice) { highPrice = 0; lowPrice = DBL_MAX; int startBar = iBarShift(_Symbol, PERIOD_CURRENT, startTime); int endBar = iBarShift(_Symbol, PERIOD_CURRENT, endTime); // バー数の大きい方を開始位置、小さい方を終了位置とする int fromBar = MathMax(startBar, endBar); int toBar = MathMin(startBar, endBar); // 指定期間の高値と安値を計算 for(int i = fromBar; i >= toBar; i--) { double high = iHigh(_Symbol, PERIOD_CURRENT, i); double low = iLow(_Symbol, PERIOD_CURRENT, i); if(high > highPrice) highPrice = high; if(low < lowPrice) lowPrice = low; } } //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| トレンドラインを描画する | //+------------------------------------------------------------------+ void DrawTrendLine(string name, datetime startTime, datetime endTime, double level) { // 既存のラインを削除 ObjectDelete(0, name); // トレンドラインを作成 ObjectCreate(0, name, OBJ_TREND, 0, startTime, level, endTime, level); // ラインのプロパティを設定 ObjectSetInteger(0, name, OBJPROP_COLOR, LineColor); ObjectSetInteger(0, name, OBJPROP_STYLE, LineStyle); ObjectSetInteger(0, name, OBJPROP_WIDTH, LineWidth); ObjectSetInteger(0, name, OBJPROP_BACK, true); ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); // 選択不可 ObjectSetInteger(0, name, OBJPROP_SELECTED, false); // 選択状態解除 ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false); // 右側に延長しない ObjectSetInteger(0, name, OBJPROP_RAY_LEFT, false); // 左側に延長しない } //+------------------------------------------------------------------+ //| 指定された時刻が目標時刻と一致するかチェックする | //+------------------------------------------------------------------+ bool isEqualTime(datetime checkTime, string targetTimeStr) { // チェックする時刻を文字列に変換(年.月.日 時:分 の形式) string checkTimeStr = TimeToString(checkTime, TIME_DATE|TIME_MINUTES); return(StringCompare(checkTimeStr, targetTimeStr, false) == 0); // false は大文字小文字を区別する } //+------------------------------------------------------------------+ //| 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[]) { int startIdx = MathMax(rates_total - targetCount, 0); // 配列の境界チェック int endIdx = rates_total - 1; // 最新のIndex // デバッグ用:処理範囲の時間を出力 Print("Checking time range from ", TimeToString(time[startIdx]), " to ", TimeToString(time[endIdx])); // n本前から最新までループ(古い方から新しい方へ) TimeSpan *timeSpan = new TimeSpan("09:00"); for(int i = startIdx; i <= endIdx; i++) { if (timeSpan.isEqual(time[i])) { // 高値と安値を格納する変数 double highPrice, lowPrice; // 高値と安値を取得 datetime analyzeStartTime = minus(time[i], "09:00"); datetime analyzeEndTime = minus(time[i], "01:00"); GetHighLowPrices(analyzeStartTime, analyzeEndTime, highPrice, lowPrice); double LineLevel = (highPrice + lowPrice) / 2.0; // トレンドラインを描画 datetime StartTime = minus(time[i], "01:00"); datetime EndTime = plus(time[i], "15:00"); // ラインの一意の名前を生成 lineName = "TLine_" + i; DrawTrendLine(lineName, StartTime, EndTime, LineLevel); } } return(rates_total); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // インジケータ終了時にラインを削除 ObjectDelete(0, lineName); }