English Deutsch
preview
カスタム市場センチメント指標の開発

カスタム市場センチメント指標の開発

MetaTrader 5 |
74 0
Hlomohang John Borotho
Hlomohang John Borotho

はじめに

市場の真の方向性を見極めることは、特に時間足ごとに異なるシグナルが示される場合には容易ではありません。たとえば、30分足では力強い上昇トレンドが見えていても、4時間足では依然として下落圧力が優勢といったケースでは、トレーダーは判断に迷いやすく、上位足に逆行するエントリーや一貫性のない取引をしてしまいがちです。上位足と下位足のシグナルを体系的に整合させる手段がなければ、不十分な情報に基づく衝動的な判断を避けることは難しく、これは収益性の低下やパフォーマンスの不安定化につながります。

こうした問題を解決するために開発されたのが、Market Sentimentカスタムインジケーターです。このインジケーターは、複数の時間足から得られるシグナルを分かりやすい1つのパネルに統合し、上位時間足のトレンドと下位時間足の構造を組み合わせて分析します。そのうえで、市場を強気、弱気、リスクオン、リスクオフ、中立の5種類のセンチメントに分類します。この多層的な分析手法により、トレーダーは大局を踏まえつつ短期的な変化も的確に捉えられるようになり、結果として判断がより明確になり、不確実性が軽減され、市場環境に合致した整合性の高い取引を行いやすくなります。



開発とロジック

強気センチメント

強気センチメントは、トレーダーや投資家が価格の上昇を期待する局面で発生します。買い圧力が売り圧力を上回る状態が特徴です。典型的な兆候には、上昇トレンド(高値更新や安値切り上げ)、上昇局面での出来高増加、ポジティブな経済指標やニュースなどがあります。極端な場合、強気センチメントはユーフォニア(高揚感)となり、上昇相場の終盤で過剰な楽観主義が見られることがあります。

弱気センチメント

弱気センチメントは、価格の下落が予想され、売り圧力が買い圧力を上回る局面で発生します。典型的な兆候としては、下降トレンド(高値切り下げや安値更新)、下落局面での出来高増加、ネガティブな経済指標やニュースなどが挙げられます。極端な場合、弱気センチメントはパニック売りとして表れ、市場の底付近で激しい売りを引き起こすことがあります。

中立センチメント

中立センチメントは、買い手と売り手の力関係が拮抗し、方向性が定まらない局面で発生します。この環境では、明確な上昇や下降トレンドが形成されず、レンジ相場が続くことが多いです。特徴として、価格の保ち合い、低ボラティリティ、トレーダーがエントリーの確証を待つ状況などが挙げられます。

リスクオンセンチメント

リスクオン環境では、投資家はより高いリターンを求めてリスク資産に資金を移動します。株式、商品、ハイイールド資産への資金流入が増えます。一般的な兆候としては、株価指数の上昇、安全資産(例:金、国債)への需要低下などがあります。

リスクオフセンチメント

リスクオフ環境では、投資家は不安や不確実性により安全資産に資金を退避させます。金、米ドル、スイスフラン、国債などの伝統的な安全資産に資金が流入します。特徴として、株価指数の下落、安全資産への需要増加が挙げられます。

時間足の関係性

アーキテクチャ図



導入手順

//+------------------------------------------------------------------+
//|                                                  Market_Sent.mq5 |
//|                        GIT under Copyright 2025, MetaQuotes Ltd. |
//|                     https://www.mql5.com/ja/users/johnhlomohang/ |
//+------------------------------------------------------------------+
#property copyright "GIT under Copyright 2025, MetaQuotes Ltd."
#property link      "https://www.mql5.com/ja/users/johnhlomohang/"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0


//+------------------------------------------------------------------+
//| Input parameters                                                 |
//+------------------------------------------------------------------+
input group "Timeframe Settings"
input ENUM_TIMEFRAMES HigherTF = PERIOD_H4;     
input ENUM_TIMEFRAMES LowerTF1 = PERIOD_H1;     
input ENUM_TIMEFRAMES LowerTF2 = PERIOD_M30;    

input group "Indicator Settings"
input int MAPeriod = 200;                       
input int SwingLookback = 5;                    
input double ATRThreshold = 0.002;              

input group "Visual Settings"
// force top-left dark theme
input int PanelCorner = 0;                      
input int PanelX = 10;                          
input int PanelY = 10;                          
input string FontFace = "Arial";                
input int FontSize = 10;                        
input color BullishColor = clrLimeGreen;        
input color BearishColor = clrRed;              
input color RiskOnColor = clrDodgerBlue;        
input color RiskOffColor = clrOrangeRed;        
input color NeutralColor = clrGold;      

まず、MQL5でMarket Sentimentカスタムインジケーターのフレームワークを設定します。冒頭部分には、著作権、バージョン、リンクなどのメタデータに加え、インジケーターのプロパティを定義するディレクティブが含まれます。「indicator_buffers 0」および「indicator_plots 0」は、標準のバッファやプロットを使用しないことを意味します。このインジケーターは線やヒストグラムを描画するのではなく、パネル形式のビジュアルツールとして設計されているためです。これらの初期設定により、カスタムセンチメント分析ロジックが実行される環境が整えられます。

入力パラメータは、トレーダーがインジケーターを柔軟に設定できるようにします。「Timeframe Settings」グループでは、上位時間足(デフォルトH4)と下位時間足2種(H1およびM30)を選択してセンチメント分析をおこなうことができます。「Indicator Settings」では、移動平均期間、スイングの過去参照範囲、ATR閾値など、価格の動きやボラティリティを解釈するための技術的パラメーターを調整できます。最後に、「Visual Settings」グループでは、センチメントパネルのチャート上の位置、フォントスタイルやサイズ、強気、弱気、リスクオン、リスクオフ、中立の各状態を表す色を設定できます。これらの入力を組み合わせることで、複数時間足にわたる市場センチメントを検出し、可視化する柔軟な基盤が構築されます。

//+------------------------------------------------------------------+
//| Global variables                                                 |
//+------------------------------------------------------------------+
int higherTFHandle, lowerTF1Handle, lowerTF2Handle;
double higherTFMA[], lowerTF1MA[], lowerTF2MA[];
datetime lastUpdateTime = 0;
string indicatorName = "MarketSentiment";

//--- helper: convert timeframe to string
string TFtoString(int tf)
{
   switch(tf)
   {
      case PERIOD_M1:  return "M1";
      case PERIOD_M5:  return "M5";
      case PERIOD_M15: return "M15";
      case PERIOD_M30: return "M30";
      case PERIOD_H1:  return "H1";
      case PERIOD_H4:  return "H4";
      case PERIOD_D1:  return "D1";
      case PERIOD_W1:  return "W1";
      case PERIOD_MN1: return "MN";
      default: return "TF?";
   }
}

このセクションでは、Market Sentimentインジケーターに必要なグローバル変数とヘルパー関数を定義します。3つのハンドル変数(higherTFHandle、lowerTF1Handle、lowerTF2Handle)は、異なる時間足での移動平均計算の参照を保持するために使用されます。一方、配列(higherTFMA[]、lowerTF1MA[]、lowerTF2MA[])にはそれぞれ対応するデータ値が格納されます。lastUpdateTime変数はインジケーターの最終更新時刻を追跡するために初期化され、効率的な更新を可能にします。また、indicatorNameはチャート上に描画されるオブジェクトの一貫したラベルを提供します。加えて、ヘルパー関数TFtoString()は数値で定義された時間足定数を読みやすい文字列に変換します(例:PERIOD_H1 →「H1」)。この機能は、インジケーターパネル上でのラベル付けや情報表示に役立ちます。

//+------------------------------------------------------------------+
//| OnInit                                                           |
//+------------------------------------------------------------------+
int OnInit()
{
    indicatorName = "MarketSentiment_" + IntegerToString(ChartID());
    
    higherTFHandle = iMA(_Symbol, HigherTF, MAPeriod, 0, MODE_EMA, PRICE_CLOSE);
    lowerTF1Handle = iMA(_Symbol, LowerTF1, MAPeriod, 0, MODE_EMA, PRICE_CLOSE);
    lowerTF2Handle = iMA(_Symbol, LowerTF2, MAPeriod, 0, MODE_EMA, PRICE_CLOSE);
    
    ArraySetAsSeries(higherTFMA, true);
    ArraySetAsSeries(lowerTF1MA, true);
    ArraySetAsSeries(lowerTF2MA, true);
    
    CreatePanel();
    return(INIT_SUCCEEDED);
}

OnInit()関数はMarket Sentimentインジケーターを初期化します。まず、チャートオブジェクトに対してチャートIDを用いた一意の名前を設定し、指定された期間とEMA方式で上位時間足および下位時間足の移動平均ハンドルを作成します。また、移動平均配列を時系列向けに設定することで、最新値にアクセスする際のインデックス操作を容易にします。最後にCreatePanel()関数を呼び出して、チャート上にセンチメント表示パネルを描画し、INIT_SUCCEEDEDを返すことで初期化の成功を確認します。

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    ObjectsDeleteAll(0, indicatorName);
    IndicatorRelease(higherTFHandle);
    IndicatorRelease(lowerTF1Handle);
    IndicatorRelease(lowerTF2Handle);
}

OnDeinit()関数は、インジケーターが削除される際に適切にクリーンアップをおこないます。まず、一意のindicatorNameに関連付けられたチャート上のすべてのオブジェクトを削除し、次に上位時間足および下位時間足の移動平均ハンドルを解放します。これにより、メモリリークを防ぎ、チャート環境を清潔に保つことができます。

//+------------------------------------------------------------------+
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[])
{
    if (TimeCurrent() - lastUpdateTime < 10 && prev_calculated > 0)
        return(rates_total);
    
    lastUpdateTime = TimeCurrent();
    
    CopyBuffer(higherTFHandle, 0, 0, 3, higherTFMA);
    CopyBuffer(lowerTF1Handle, 0, 0, 3, lowerTF1MA);
    CopyBuffer(lowerTF2Handle, 0, 0, 3, lowerTF2MA);
    
    double higherTFPrice = iClose(_Symbol, HigherTF, 0);
    double lowerTF1Price = iClose(_Symbol, LowerTF1, 0);
    double lowerTF2Price = iClose(_Symbol, LowerTF2, 0);
    
    int higherTFBias = GetHigherTFBias(higherTFPrice, higherTFMA[0]);
    
    bool lowerTF1Bullish = IsBullishStructure(LowerTF1, SwingLookback);
    bool lowerTF1Bearish = IsBearishStructure(LowerTF1, SwingLookback);
    bool lowerTF2Bullish = IsBullishStructure(LowerTF2, SwingLookback);
    bool lowerTF2Bearish = IsBearishStructure(LowerTF2, SwingLookback);
    
    bool lowerTF1Breakout = HasBreakout(LowerTF1, SwingLookback, higherTFBias);
    bool lowerTF2Breakout = HasBreakout(LowerTF2, SwingLookback, higherTFBias);
    
    int sentiment = DetermineSentiment(
        higherTFBias, 
        lowerTF1Bullish, lowerTF1Bearish, lowerTF1Breakout,
        lowerTF2Bullish, lowerTF2Bearish, lowerTF2Breakout
    );
    
    UpdatePanel(higherTFBias,
                lowerTF1Bullish, lowerTF1Bearish,
                lowerTF2Bullish, lowerTF2Bearish,
                sentiment);
    
    return(rates_total);
}

OnCalculate()関数は、インジケーターの主要な処理ループとして機能し、新しい価格データやティックが到着するたびに実行されます。まず更新スロットルを設け、前回の更新から少なくとも10秒経過している場合にのみ計算をおこなうようにし、効率性を向上させます。その後、上位および下位時間足の移動平均値をバッファからコピーし、各時間足の最新終値を取得します。これらのデータがセンチメント評価の基礎となります。

価格および移動平均データを取得した後、関数は上位時間足での方向性バイアスを判定し、下位時間足では構造的条件(強気または弱気のパターン)を確認します。また、上位時間足のバイアスに沿った潜在的なブレイクアウトの妥当性も検証します。これらの条件はDetermineSentiment()関数で統合され、市場を強気、弱気、リスクオン、リスクオフ、中立のいずれかに分類します。最後に、結果はUpdatePanel()を通じてチャート上に視覚的に反映され、トレーダーは複数時間足にわたるリアルタイムのセンチメントダッシュボードを確認できるようになります。

//+------------------------------------------------------------------+
//| Determine higher timeframe bias                                  |
//+------------------------------------------------------------------+
int GetHigherTFBias(double price, double maValue)
{
    double deviation = MathAbs(price - maValue) / maValue;
    if (price > maValue && deviation > ATRThreshold) return 1;
    else if (price < maValue && deviation > ATRThreshold) return -1;
    else return 0;
}

この関数は、上位時間足のトレンド方向を評価します。現在の価格と移動平均値を比較し、価格が移動平均を上回り、かつ偏差が定義されたATR閾値を超える場合は1(強気バイアス)を返します。一方、価格が移動平均を下回り、十分な偏差がある場合は-1(弱気バイアス)を返します。どちらの条件も満たさない場合は0を返し、上位時間足のバイアスが中立または判断が定まらないことを示します。

//+------------------------------------------------------------------+
//| Bullish structure                                                |
//+------------------------------------------------------------------+
bool IsBullishStructure(ENUM_TIMEFRAMES tf, int lookback)
{
    int swingHighIndex = iHighest(_Symbol, tf, MODE_HIGH, lookback * 2, 1);
    int swingLowIndex  = iLowest (_Symbol, tf, MODE_LOW,  lookback * 2, 1);
    int prevHigh = iHighest(_Symbol, tf, MODE_HIGH, lookback, lookback+1);
    int prevLow  = iLowest (_Symbol, tf, MODE_LOW,  lookback, lookback+1);
    if (swingHighIndex==-1 || swingLowIndex==-1 || prevHigh==-1 || prevLow==-1) return false;
    return (iHigh(_Symbol, tf, swingHighIndex) > iHigh(_Symbol, tf, prevHigh) &&
            iLow(_Symbol, tf, swingLowIndex)   > iLow (_Symbol, tf, prevLow));
}
//+------------------------------------------------------------------+
//| Bearish structure                                                |
//+------------------------------------------------------------------+
bool IsBearishStructure(ENUM_TIMEFRAMES tf, int lookback)
{
    int swingHighIndex = iHighest(_Symbol, tf, MODE_HIGH, lookback * 2, 1);
    int swingLowIndex  = iLowest (_Symbol, tf, MODE_LOW,  lookback * 2, 1);
    int prevHigh = iHighest(_Symbol, tf, MODE_HIGH, lookback, lookback+1);
    int prevLow  = iLowest (_Symbol, tf, MODE_LOW,  lookback, lookback+1);
    if (swingHighIndex==-1 || swingLowIndex==-1 || prevHigh==-1 || prevLow==-1) return false;
    return (iHigh(_Symbol, tf, swingHighIndex) < iHigh(_Symbol, tf, prevHigh) &&
            iLow(_Symbol, tf, swingLowIndex)   < iLow (_Symbol, tf, prevLow));
}

IsBullishStructure()関数は、指定された時間足における強気の価格パターンを判定します。直近のスイングハイとスイングローを前回のスイングポイントと比較することで識別します。まず、iHighestおよびiLowest関数を用いて、現在および前回のスイングハイとスイングローを取得します。現在のスイングハイが前回のスイングハイより高く、かつ現在のスイングローが前回のスイングローより高い場合、関数はtrueを返し、強気の構造であることを示します。それ以外の場合はfalseを返します。

同様に、IsBearishStructure()関数は弱気のパターンを検出します。直近のスイングハイとスイングローを前回のスイングハイとスイングローと比較し、現在のスイングハイが前回のスイングハイより低く、かつ現在のスイングローが前回のスイングローより低い場合にtrueを返し、弱気の構造であることを示します。どちらの関数も指定された参照期間に基づくスイング分析をおこない、直近の価格動向を過去の動きと比較して評価する手法をインジケーターに提供します。

//+------------------------------------------------------------------+
bool HasBreakout(ENUM_TIMEFRAMES tf, int lookback, int higherTFBias)
{
    int swingHighIndex = iHighest(_Symbol, tf, MODE_HIGH, lookback, 1);
    int swingLowIndex  = iLowest (_Symbol, tf, MODE_LOW,  lookback, 1);
    if (swingHighIndex==-1 || swingLowIndex==-1) return false;
    double swingHigh = iHigh(_Symbol, tf, swingHighIndex);
    double swingLow  = iLow (_Symbol, tf, swingLowIndex);
    double price = iClose(_Symbol, tf, 0);
    if (higherTFBias==1) return (price > swingHigh);
    if (higherTFBias==-1) return (price < swingLow);
    return false;
}

この関数は、指定された時間足において直近のスイングハイまたはスイングローを価格が突破したかどうかを確認します。上位時間足のバイアスも考慮されます。まず、直近のスイングハイとスイングローを特定し、どちらかが取得できない場合はfalseを返します。上位時間足のバイアスが強気の場合、現在の価格がスイングハイを上回ったときにtrueを返します。一方、上位時間足のバイアスが弱気の場合は、現在の価格がスイングローを下回ったときにtrueを返します。上位時間足のバイアスが中立の場合はブレイクアウトを考慮せず、常にfalseを返します。

//+------------------------------------------------------------------+
int DetermineSentiment(int higherTFBias, 
                      bool tf1Bullish, bool tf1Bearish, bool tf1Breakout,
                      bool tf2Bullish, bool tf2Bearish, bool tf2Breakout)
{
    if (higherTFBias==1 && tf1Bullish && tf2Bullish) return 1;
    if (higherTFBias==-1 && tf1Bearish && tf2Bearish) return -1;
    if (higherTFBias==1 && (tf1Breakout||tf2Breakout)) return 2;
    if (higherTFBias==-1 && (tf1Breakout||tf2Breakout)) return -2;
    return 0;
}

DetermineSentiment()関数は、複数の時間足における市場状況を総合的に評価し、全体の市場センチメントを分類します。上位時間足が強気で、かつ下位時間足の両方が強気構造を示す場合は1(強気センチメント)を返します。逆に、上位時間足が弱気で下位時間足の両方が弱気構造の場合は-1(弱気センチメント)を返します。上位時間足が強気で下位時間足にブレイクアウトが発生した場合は2(リスクオン)、上位時間足が弱気で下位時間足に同様のブレイクアウトが発生した場合は-2(リスクオフ)を返します。これらの条件のいずれにも該当しない場合は0を返し、市場が中立または不安定な状態であることを示します。

//+------------------------------------------------------------------+
//| Panel Creation (dark theme, top-left)                            |
//+------------------------------------------------------------------+
void CreatePanel()
{
   string bg = indicatorName + "_BG";
   ObjectCreate(0, bg, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0, bg, OBJPROP_XDISTANCE, PanelX);
   ObjectSetInteger(0, bg, OBJPROP_YDISTANCE, PanelY);
   ObjectSetInteger(0, bg, OBJPROP_XSIZE, 200);
   ObjectSetInteger(0, bg, OBJPROP_YSIZE, 120);
   ObjectSetInteger(0, bg, OBJPROP_CORNER, 0);
   ObjectSetInteger(0, bg, OBJPROP_BGCOLOR, clrBlack);
   ObjectSetInteger(0, bg, OBJPROP_BORDER_COLOR, clrGray);
   ObjectSetInteger(0, bg, OBJPROP_BACK, true);
   ObjectSetInteger(0, bg, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, bg, OBJPROP_HIDDEN, true);

   string title = indicatorName + "_Title";
   ObjectCreate(0, title, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, title, OBJPROP_XDISTANCE, PanelX+10);
   ObjectSetInteger(0, title, OBJPROP_YDISTANCE, PanelY+10);
   ObjectSetInteger(0, title, OBJPROP_CORNER, 0);
   ObjectSetString (0, title, OBJPROP_TEXT, "Market Sentiment");
   ObjectSetInteger(0, title, OBJPROP_COLOR, clrWhite);
   ObjectSetString (0, title, OBJPROP_FONT, FontFace);
   ObjectSetInteger(0, title, OBJPROP_FONTSIZE, FontSize);

   string tfs[3] = { TFtoString(HigherTF), TFtoString(LowerTF1), TFtoString(LowerTF2) };
   for(int i=0;i<3;i++)
   {
      string tfLabel = indicatorName+"_TF"+(string)i;
      ObjectCreate(0, tfLabel, OBJ_LABEL, 0,0,0);
      ObjectSetInteger(0, tfLabel, OBJPROP_XDISTANCE, PanelX+10);
      ObjectSetInteger(0, tfLabel, OBJPROP_YDISTANCE, PanelY+30+i*20);
      ObjectSetInteger(0, tfLabel, OBJPROP_CORNER, 0);
      ObjectSetString (0, tfLabel, OBJPROP_TEXT, tfs[i]+":");
      ObjectSetInteger(0, tfLabel, OBJPROP_COLOR, clrLightGray);
      ObjectSetString (0, tfLabel, OBJPROP_FONT, FontFace);
      ObjectSetInteger(0, tfLabel, OBJPROP_FONTSIZE, FontSize);

      string sentLabel = indicatorName+"_Sentiment"+(string)i;
      ObjectCreate(0, sentLabel, OBJ_LABEL, 0,0,0);
      ObjectSetInteger(0, sentLabel, OBJPROP_XDISTANCE, PanelX+100);
      ObjectSetInteger(0, sentLabel, OBJPROP_YDISTANCE, PanelY+30+i*20);
      ObjectSetInteger(0, sentLabel, OBJPROP_CORNER, 0);
      ObjectSetString (0, sentLabel, OBJPROP_TEXT, "N/A");
      ObjectSetInteger(0, sentLabel, OBJPROP_COLOR, NeutralColor);
      ObjectSetString (0, sentLabel, OBJPROP_FONT, FontFace);
      ObjectSetInteger(0, sentLabel, OBJPROP_FONTSIZE, FontSize);
   }

   string fnl = indicatorName+"_Final";
   ObjectCreate(0, fnl, OBJ_LABEL, 0,0,0);
   ObjectSetInteger(0, fnl, OBJPROP_XDISTANCE, PanelX+10);
   ObjectSetInteger(0, fnl, OBJPROP_YDISTANCE, PanelY+100);
   ObjectSetInteger(0, fnl, OBJPROP_CORNER, 0);
   ObjectSetString (0, fnl, OBJPROP_TEXT, "Final: Neutral");
   ObjectSetInteger(0, fnl, OBJPROP_COLOR, NeutralColor);
   ObjectSetString (0, fnl, OBJPROP_FONT, FontFace);
   ObjectSetInteger(0, fnl, OBJPROP_FONTSIZE, FontSize+2);
}

CreatePanel()関数は、チャート左上に視覚的に整えられたパネルを初期化します。背景が白のチャートでも見やすいダークテーマが使用されます。まず、黒の塗りつぶしと灰色の枠線を持つ背景矩形を作成し、他のチャートオブジェクトの背面に配置し、選択できないように設定します。その上にタイトルラベルを追加し、Market Sentimentインジケーターであることを明確に表示します。文字色は白に設定され、暗い背景でも視認性が高まります。

タイトルの下には、上位および下位の3つの監視対象時間足ごとのラベルを作成します。ラベルには時間足の名前と、初期値として中立色で「N/A」と表示されたセンチメント値のプレースホルダーが設定されます。最後にパネル下部には大きなラベルを配置し、最終的な市場センチメントを要約して表示します。初期値は「Neutral」となっています。この設定により、複数時間足にわたる市場バイアスを一目で把握できるコンパクトなパネルが提供されます。

//+------------------------------------------------------------------+
//| Panel Update                                                     |
//+------------------------------------------------------------------+
void UpdatePanel(int higherTFBias,
                 bool tf1Bullish, bool tf1Bearish,
                 bool tf2Bullish, bool tf2Bearish,
                 int sentiment)
{
    // Higher TF
    string txt="Neutral"; color col=NeutralColor;
    if(higherTFBias==1){txt="Bullish"; col=BullishColor;}
    else if(higherTFBias==-1){txt="Bearish"; col=BearishColor;}
    ObjectSetString(0, indicatorName+"_Sentiment0", OBJPROP_TEXT, txt);
    ObjectSetInteger(0, indicatorName+"_Sentiment0", OBJPROP_COLOR, col);

    // Lower TF1
    txt="Neutral"; col=NeutralColor;
    if(tf1Bullish){txt="Bullish"; col=BullishColor;}
    else if(tf1Bearish){txt="Bearish"; col=BearishColor;}
    ObjectSetString(0, indicatorName+"_Sentiment1", OBJPROP_TEXT, txt);
    ObjectSetInteger(0, indicatorName+"_Sentiment1", OBJPROP_COLOR, col);

    // Lower TF2
    txt="Neutral"; col=NeutralColor;
    if(tf2Bullish){txt="Bullish"; col=BullishColor;}
    else if(tf2Bearish){txt="Bearish"; col=BearishColor;}
    ObjectSetString(0, indicatorName+"_Sentiment2", OBJPROP_TEXT, txt);
    ObjectSetInteger(0, indicatorName+"_Sentiment2", OBJPROP_COLOR, col);

    // Final
    string finalSent="Neutral"; color finalCol=NeutralColor;
    switch(sentiment){
        case 1: finalSent="Bullish"; finalCol=BullishColor; break;
        case -1: finalSent="Bearish"; finalCol=BearishColor; break;
        case 2: finalSent="Risk-On"; finalCol=RiskOnColor; break;
        case -2: finalSent="Risk-Off"; finalCol=RiskOffColor; break;
    }
    ObjectSetString(0, indicatorName+"_Final", OBJPROP_TEXT, "Final: "+finalSent);
    ObjectSetInteger(0, indicatorName+"_Final", OBJPROP_COLOR, finalCol);
}

UpdatePanel()関数は、最新の分析に基づき市場センチメントパネルを動的に更新します。まず、上位時間足のバイアスを評価し、対応するラベルを「Bullish」「Bearish」「Neutral」のいずれかに更新し、適切な色で表示します。次に、2つの下位時間足についても同様に評価をおこない、強気または弱気の構造を確認し、それぞれのラベルに正しい色を反映します。

最後に、全時間足におけるバイアスとブレイクアウトを総合的に評価して、市場全体のセンチメントを判定します。最終的なセンチメントラベルは「Bullish」「Bearish」「Risk-On」「Risk-Off」「Neutral」のいずれかに更新され、対応する色が付けられることで、現在の市場状況を迅速かつ視覚的に把握できます。これにより、トレーダーは複数時間足にわたる市場の方向性を一目で確認することが可能となります。



結論

複数の時間足を統合して市場状況を明確に視覚化するMarket Sentimentカスタムインジケーターを開発しました。インジケーターは、上位および下位時間足の移動平均を計算し、スイングハイとスイングローを用いて強気または弱気の構造を判定し、潜在的なブレイクアウトを検出して、全体のセンチメントを決定します。左上に配置されたダークテーマのパネルには、各時間足のセンチメントと統合された最終センチメントが表示され、色分けにより強気、弱気、リスクオン、リスクオフ、中立の状況を迅速に識別できます。

このインジケーターは複雑な市場データを読みやすく視覚的に整理することで、トレーダーがより情報に基づいた判断をおこなえるよう支援します。リアルタイムで複数時間足のセンチメント分析を提供することで、市場のトレンドを素早く把握し、潜在的な取引機会を特定し、戦略を現行の市場状況に沿わせることが可能になります。これにより不確実性が低減され、意思決定の効率が向上します。

MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/19422

添付されたファイル |
Market_Sent.mq5 (13.68 KB)
MQL5で自己最適化エキスパートアドバイザーを構築する(第14回):フィードバックコントローラーにおけるデータ変換を調整パラメータとして捉える MQL5で自己最適化エキスパートアドバイザーを構築する(第14回):フィードバックコントローラーにおけるデータ変換を調整パラメータとして捉える
前処理は非常に強力でありながら、しばしば軽視されがちな調整パラメータです。その存在は、より注目されるオプティマイザーや華やかなモデル構造の影に隠れています。しかし、前処理のわずかな改善は、利益やリスクに対して予想以上に大きな複利効果をもたらすことがあります。あまりにも多くの場合、このほとんど未踏の領域は単なるルーチン作業として扱われ、手段としてしか意識されません。しかし実際には、前処理は信号を直接増幅することもあれば、容易に破壊してしまうこともあるのです。
MQL5での取引戦略の自動化(第30回):視覚的フィードバックによるプライスアクションAB-CDハーモニックパターンの作成 MQL5での取引戦略の自動化(第30回):視覚的フィードバックによるプライスアクションAB-CDハーモニックパターンの作成
本記事では、MQL5で弱気、強気双方のAB=CDハーモニックパターンを、ピボットポイントとフィボナッチ比率に基づいて識別し、正確なエントリー、ストップロス、テイクプロフィットレベルを用いて取引を自動化するAB=CDパターンエキスパートアドバイザー(EA)を開発します。さらに、チャートオブジェクトによる視覚的フィードバックによって、トレーダーの洞察を強化します。
共和分株式による統計的裁定取引(第4回):リアルタイムモデル更新 共和分株式による統計的裁定取引(第4回):リアルタイムモデル更新
本記事では、共和分関係にある株式バスケットを対象とした、シンプルでありながら包括的な統計的アービトラージのパイプラインについて解説します。データのダウンロードと保存を行うPythonスクリプト、相関検定、共和分検定、定常性検定、さらにデータベース更新用のMetatrader 5サービスの実装およびそれに対応するエキスパートアドバイザー(EA)も含まれています。また、いくつかの設計上の判断については、参考情報および実験の再現性向上のために本記事に記録しています。
SMC (Smart Money Concepts)で取引のレベルアップを実現する:OB、BOS、FVG SMC (Smart Money Concepts)で取引のレベルアップを実現する:OB、BOS、FVG
SMC(Smart Money Concepts、スマートマネーコンセプト)のOB(Order Blocks、注文ブロック)、BOS(Break of Structure、ブレイクオブストラクチャ)、FVG(Fair Value Gaps、公正価格ギャップ)を1つの強力なEAに統合することで、取引をさらに進化させることができます。自動モードで戦略を実行することも、特定のSMCコンセプトだけを使用することも可能で、柔軟かつ精度の高い取引が実現します。