仕様

日本時間の高値安値の半値を表示させるインジケータを作ってみた。

感想

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);
}
トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2024-11-01 (金) 01:19:26 (178d)