日本時間の高値安値の半値を表示させるインジケータを作ってみた。
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 n = 32; // 何個前のデータを対象とするか
//--- グローバル変数
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 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);
}