* 仕様 [#s8e0c733]
日本時間の高値安値の半値を表示させるインジケータを作ってみた。

* 感想 [#m3e1ac67]
3つ前までの半値インジケータの線が効いている

半値をローソク足が離れたら、そっちの方向が優勢ってことでついていくのが基本だ。
しかし、途中で半値を下回ったら、何か異変ありということで、逆方向にヘッジを入れて、そのまま逆方向に行ってしまったら最初のポジションを外して、逆方向のポジションを増やそう。稀に、さらにもとに戻ることがあるが、その時も、ヘッジを入れて、様子見していくが、あまりそういうことは起きないと思う。


* コード [#ba5b996c]
 //+------------------------------------------------------------------+
 //|                                           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      n = 32; // 何個前のデータを対象とするか
 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 - 6000, 0);  // 配列の境界チェック
     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_" + IntegerToString(GetTickCount());          
           lineName = "TLine_" + i;          
           DrawTrendLine(lineName, StartTime, EndTime, LineLevel);
    
        }
     }
     
     return(rates_total);
 }
 
 //+------------------------------------------------------------------+
 //| Custom indicator deinitialization function                         |
 //+------------------------------------------------------------------+
 void OnDeinit(const int reason)
 {
     // インジケータ終了時にラインを削除
     ObjectDelete(0, lineName);
 }

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS