English Deutsch
preview
ニュース取引が簡単に(第3回):取引の実施

ニュース取引が簡単に(第3回):取引の実施

MetaTrader 5トレーディング | 21 10月 2024, 11:30
341 0
Kabelo Frans Mampa
Kabelo Frans Mampa

はじめに

前回は、ニュースカレンダーデータベースに経済データを保存するEAを作成しました。また、EAが十分なパフォーマンスを発揮するための基礎を築くために、多くのクラスを開発しました。この記事では、プロジェクトでこれらのクラスを拡張し、最終的に経済データから取引するという目標に到達します。私たちの次の目標は収益性であり、これについては次回の記事で取り上げる予定です。この記事では、データベースに新しいビューを追加して、MQL5の経済指標カレンダーからユニークなイベントをすべて表示し、さまざまなイベントに関する情報を提供します。また、柔軟性を持たせるために、取引時に経済データをフィルタリングするための新たな入力をEAに追加する予定です。本連載の前回の記事には、取引のリスクを管理するためのリスク管理クラスの作成などの役立つ情報があります。まだの方はご覧ください。 



期待できるもの

現在のチャートに対応した簡潔かつ現代的なグラフィックの改善。下の画像は、ライトモードでのこれらのグラフィックの表現です。

    ライトモードでのAUDUSD(イラスト)

    セクション1~9は、EAがチャート上に表示されるたびに自動的に表示されます。

    セクション10、11~15のグループ、16はオプションで、新しい1分ローソク足ごとに更新されます(バックテスト時のパフォーマンスを向上させるため)。

    セクション

    • 10:端末の日時を表示します。チャートがライトモードのときにニュースイベントが発生すると、時刻が赤く表示されます。
    • 11:現在/次のニュースイベントの日時を表示します。日時が端末の時刻と同じ場合、文字は赤で表示されます。
    • 12:ニュースイベントの名前を表示します。文字色はイベントの重要度に応じて変わります。例えば、重要度が高い場合は赤で表示されます。
    • 13:ニュースイベントの国名を表示します。文字色は、イベントの重要度とチャートのカラーモード(ライトモードなど)によって変わります。
    • 14:ニュースイベントの通貨名を表示します。文字色は異なります。
    • 15:ニュースイベントの重要度を表示します。文字色は異なります。
    • 16:現在の銘柄のスプレッドと、2週間分の1分ローソク足のスプレッドデータから計算された評価を表示します。評価は「excellent」、「good」、「normal」、「bad」、「terrible」のグループに分類され、ダークモードとライトモードのバリエーションで、各カテゴリごとに異なる色で表示されます。

    下の画像は、ダークモードがどのように実装されているかを表したものです。

    セクション

    • 17:現在の端末の日に発生する、または発生したすべてのイベントのイベント時刻を表示します。 

    ダークモードでのAUDUSD(イラスト)



    DISPLAY入力

    • CHART COLOUR MODE:ダークモードとライトモードを切り替えます。
    • DISPLAY NEWS INFO:チャート上にセクション11~15を表示するかどうかを切り替えます。
    • DISPLAY EVENT OBJ:チャート上にセクション17を表示するかどうかを切り替えます。
    • DISPLAY SPREAD RATING:チャート上にセクション16を表示するかどうかを切り替えます。
    • DISPLAY DATE:チャート上にセクション10を表示するかどうかを切り替えます。

    表示入力オプション


    DST SCHEDULE入力

    • SELECT DST OPTION:ユーザーやトレーダーがカスタムの夏時間スケジュールを選択したり、EAが推奨する夏時間スケジュールを自動的に選択できるようにし、ストラテジーテスターでバックテストをおこなう際にイベント時間を正しく設定できるようにします
    • SELECT CUSTOM DST:ユーザーやトレーダーがDSTスケジュールを手動で設定できるようにします

    DST SCHEDULE入力オプション


    RISK MANAGEMENT入力

    • SELECT RISK OPTION:ユーザーやトレーダーが、最小ロットサイズ、最大ロットサイズなど、異なるリスク管理プロファイルを選択できるようにします。
    • RISK FLOOR:すべてのリスクプロファイルに対して最低リスクを設定します。例えば、1ロット分の資金がないが、最小ロットサイズである0.01ロット分の資金がある場合、資金が不足しているため取引を開始しないのではなく、0.01ロットを使用して取引を開始します。これは、リスクプロファイルが適切に設定されなかった場合のセーフティネットに過ぎません。
    • MAX-RISK:通常の取引を開始するのに十分な資金がなかった場合に、口座内の余剰証拠金のパーセンテージを使用して取引を開始します。このオプションは、RISK FLOORがMAX-RISKに設定されているときのみ有効です。
    • RISK CEILING:特定の銘柄に対して最大ロットを開くのに十分な口座残高がある場合に、ロットサイズの上限を設定します。上限はMAX LOTSIZEによって異なり、特定の銘柄によって設定された最大ロットサイズが最大値となります。一方、MAX LOTSIZE(x2)は、ボリューム制限が許可されている場合に、最大ロットサイズで2つの取引を開くことができます。
    • PERCENTAGE OF [BALANCE | FREE-MARGIN]:利用可能な残高または余剰証拠金の一定割合をリスクにさらします。
    • AMOUNT PER [BALANCE | FREE-MARGIN]:残高または余剰証拠金の一定の金額をリスクにさらします。例えば、[BALANCE | FREE-MARGIN]が1000に設定され、EACH AMOUNTが10に設定されている場合、残高または余剰証拠金の通貨価値が1000ごとに、各取引に対して10の通貨価値をリスクにさらすことを意味します。つまり、残高/余剰証拠金が1000米ドルなら、取引ごとに10米ドルのリスクを負うことになります。
    • LOTSIZE PER [BALANCE | FREE-MARGIN]:残高または余剰証拠金の価値に対して特定のロットサイズをリスクにさらします。例えば、[BALANCE | FREE-MARGIN]が1000に設定され、EACH LOTS(VOLUME)が0.1に設定されている場合、BALANCEまたはFREE-MARGINの通貨価値が1000の通貨価値ごとに各取引で0.1のロットサイズのリスクを負うことになります。つまり、残高/余剰証拠金が1000米ドルであれば、取引ごとに0.1をリスクにさらすことになります。
    • CUSTOM LOTSIZE:取引を開始するたびに、あらかじめ決められたロットサイズのリスクを負います。
    • PERCENTAGE OF MAX-RISK:口座の利用可能な余剰証拠金を使用して、銘柄の最大リスク量のパーセンテージをリスクにさらします。例えば、口座の余剰証拠金が10,000米ドルでAUDUSDの最大リスクボリュームが100ロットである場合、最大リスクの割合を25%に設定すると、使用されるロットサイズは100ロットの25%である25ロットになります。

    RISK MANAGEMENT入力オプション


    NEWS SETTINGS入力


    NEWS SETTINGSには、さまざまな入力オプションがあります。

    1. CALENDAR IMPORTANCE
    2. EVENT FREQUENCY
    3. EVENT SECTOR
    4. EVENT TYPE
    5. EVENT CURRENCY
    これらのオプションは下の画像に示されています。

    NEWS SETTINGS入力オプション

    • CALENDAR IMPORTANCE:ニュースの重要性に基づいてニュースデータをフィルタリングします。

    CALENDAR IMPORTANCE入力パラメータ

    • EVENT FREQUENCY:出現頻度に基づいてニュースデータをフィルタリングします。

    EVENT FREQUENCY入力パラメータ

    • EVENT SECTOR:セクターに基づいてニュースデータをフィルタリングします。

    EVENT SECTOR入力パラメータ

    • EVENT TYPE:タイプに基づいてニュースデータをフィルタリングします。例えば、EVENTは通常、スピーチや会議に使用され、INDICATORは金利、雇用データなどに使用され、HOLIDAYはニュース年やその他のさまざまな休日に使用されます。

    EVENT TYPE入力パラメータ

    • EVENT CURRENCY:選択可能な通貨オプションに基づいてニュースデータをフィルタリングします。SYMBOL CURRENCIESは、SYMBOL MARGIN、SYMBOL BASE、SYMBOL PROFITのすべての通貨を考慮します。

    EVENT CURRENCY入力パラメータ


    TRADE SETTINGS入力

    • STOPLOSS[0=NONE]:すべての取引に固定ストップロスを設定します。ストップロスがゼロに設定されている場合、すべての取引はストップロス値を持ちません。
    • TAKEPROFIT[0=NONE]:すべての取引に一定のテイクプロフィットを設定します。テイクプロフィットがゼロに設定されている場合、すべての取引はテイクプロフィットの値を持ちません。
    • PRE-ENTRY SEC:ユーザーやトレーダーが、イベント時間前に取引が開かれるまでの秒数を設定できるようにします。つまり、PRE-ENTRY SECが5に設定されている場合、イベントが発生する5秒前が、イベントが発生する前に取引が開始される時間帯であることを意味します。例:イベント時間が15:00pmの場合、14:59:45~14:59:59の5秒前から取引が可能になります。
    • TRADING DAY OF WEEK:月曜日、火曜日などの営業日をフィルタリングします。 

    TRADE SETTINGS入力オプション

    これから、EAを機能させるためのコードに取り組んでいきます。


    銘柄プロパティクラス

    第2回から追加された変更点

    • スプレッド評価の列挙体宣言
    //Enumeration for Spread rating
    enum SpreadRating
      {
       SpreadRating_Terrible,//Terrible
       SpreadRating_Bad,//Bad
       SpreadRating_Normal,//Normal
       SpreadRating_Good,//Good
       SpreadRating_Excellent//Excellent
      };
    • チャートカラーモードを設定するブール変数の宣言
    bool isLightMode;//Variable to configure Chart color mode
    • 浮動スプレッドを取得するブール関数の宣言
    bool              SpreadFloat(string SYMBOL=NULL);//Retrieve Spread Float
    //+------------------------------------------------------------------+
    //|Retrieve Spread Float                                             |
    //+------------------------------------------------------------------+
    bool CSymbolProperties::SpreadFloat(string SYMBOL=NULL)
      {
       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          return CSymbol.SpreadFloat();
         }
       Print("Unable to retrieve Symbol's Spread Float");
       return false;//Retrieve false when failed.
      }
    • スプレッド評価を取得するスプレッド評価関数の宣言
    SpreadRating      SpreadValue(string SYMBOL=NULL);//Retrieve Spread Rating

    この関数は、SpreadRatingから列挙値を返します。

    //+------------------------------------------------------------------+
    //|Retrieve Spread Rating                                            |
    //+------------------------------------------------------------------+
    SpreadRating CSymbolProperties::SpreadValue(string SYMBOL=NULL)
      {
       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          if(SpreadFloat(SYMBOL))//Check if Symbol has a floating Spread
            {
    
             //Declarations
             vector Spreads;
             int SpreadArray[],SpreadAvg=0,SpreadMax=0,SpreadMin=0,
                               SpreadUpper=0,SpreadLower=0,SpreadAvgUpper=0,
                               SpreadAvgLower=0,SpreadMidUpper=0,SpreadMidLower=0;
    
             //Get Spread data from CopySpread built-in function for 2 weeks using M1 timeframe.
             if(CopySpread(GetSymbolName(),PERIOD_M1,iTime(GetSymbolName(),PERIOD_W1,2),
                           iTime(GetSymbolName(),PERIOD_M1,0),SpreadArray)==-1)
               {
                Print("Error trying to retrieve spread values");
                return SpreadRating_Normal;//Retrieve default value when failed.
               }
             else
               {
                Spreads.Assign(SpreadArray);//Assign spread array into Spreads vector variable
    
                SpreadMax = int(Spreads.Max());//Assign max spread
                SpreadMin = int(Spreads.Min());//Assign min spread
                SpreadAvg = int(Spreads.Median());//Assign average spread
    
                //Divide Spread into sectors based of different averages.
                SpreadMidUpper = int((SpreadAvg+SpreadMax)/2);
                SpreadMidLower = int((SpreadAvg+SpreadMin)/2);
                SpreadAvgUpper = int((SpreadAvg+SpreadMidUpper)/2);
                SpreadAvgLower = int((SpreadAvg+SpreadMidLower)/2);
                SpreadUpper = int((SpreadMidUpper+SpreadMax)/2);
                SpreadLower = int((SpreadMidLower+SpreadMin)/2);
    
                int Spread = Spread(SYMBOL);//Assign Symbol's Spread
    
                if(Spread<SpreadLower||Spread==SpreadMin)//Excellent
                  {
                   return SpreadRating_Excellent;
                  }
                else
                   if(Spread>=SpreadLower&&Spread<SpreadAvgLower)//Good
                     {
                      return SpreadRating_Good;
                     }
                   else
                      if(Spread>=SpreadAvgLower&&Spread<=SpreadAvgUpper)//Normal
                        {
                         return SpreadRating_Normal;
                        }
                      else
                         if(Spread>SpreadAvgUpper&&Spread<=SpreadUpper)//Bad
                           {
                            return SpreadRating_Bad;
                           }
                         else//Terrible
                           {
                            return SpreadRating_Terrible;
                           }
               }
            }
          else
            {
             return SpreadRating_Normal;//Retrieve default value when spread is fixed.
            }
         }
       Print("Unable to retrieve Symbol's Spread Rating");
       return SpreadRating_Normal;//Retrieve default value when failed.
      }

    まず銘柄を設定し、次にその銘柄に浮動スプレッドがあるかどうかを確認してから、その平均値に基づいてスプレッドを評価する簡単な計算をおこないます。銘柄の設定に失敗した場合、または銘柄が浮動スプレッドを持っていない場合、デフォルト値としてSpreadRating_Normalを返します。

       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          if(SpreadFloat(SYMBOL))//Check if Symbol has a floating Spread
            {

    銘柄の設定に成功し、その銘柄が浮動スプレッドを持つ場合、Spreadsベクトル変数と、スプレッドの値を格納する int変数を宣言します。変数を宣言した後、CopySpread 関数を使用して、2 週間前の1分ローソク足から現在の1分ローソク足までのスプレッド値をSpreadArray変数に格納します。CopySpread関数が何らかの理由で失敗した場合、デフォルト値としてSpreadRating_Normalを返します。

     //Declarations
             vector Spreads;
             int SpreadArray[],SpreadAvg=0,SpreadMax=0,SpreadMin=0,
                               SpreadUpper=0,SpreadLower=0,SpreadAvgUpper=0,
                               SpreadAvgLower=0,SpreadMidUpper=0,SpreadMidLower=0;
    
             //Get Spread data from CopySpread built-in function for 2 weeks using M1 timeframe.
             if(CopySpread(GetSymbolName(),PERIOD_M1,iTime(GetSymbolName(),PERIOD_W1,2),
                           iTime(GetSymbolName(),PERIOD_M1,0),SpreadArray)==-1)
               {
                Print("Error trying to retrieve spread values");
                return SpreadRating_Normal;//Retrieve default value when failed.
               }

    CopySpreadが成功したら、SpreadsベクトルにSpreadArrayの整数値を代入します。次に、2週間全体での最大スプレッド、最小スプレッド、平均スプレッドなどの基本情報をこれらの配列値から取得し、これらの値をそれぞれSpreadMax、SpreadMin、SpreadAvgに格納します。次に、これら3つの前の値から異なる平均値を求めます。

    SpreadMidUpper変数はSpreadAvgとSpreadMaxの平均、SpreadMidLower変数はSpreadAvgとSpreadMinの平均、SpreadAvgUpper変数はSpreadAvgとSpreadMidUpperの平均、SpreadAvgLower変数はSpreadAvgとSpreadMidLowerの平均、SpreadUpper変数はSpreadMidUpperとSpreadMaxの平均、SpreadLower変数はSpreadMidLowerとSpreadMinの平均を求めます。また、スプレッドを分類するために、現在の銘柄のスプレッドを比較します。

    Spreads.Assign(SpreadArray);//Assign spread array into Spreads vector variable
    
                SpreadMax = int(Spreads.Max());//Assign max spread
                SpreadMin = int(Spreads.Min());//Assign min spread
                SpreadAvg = int(Spreads.Median());//Assign average spread
    
                //Divide Spread into sectors based of different averages.
                SpreadMidUpper = int((SpreadAvg+SpreadMax)/2);
                SpreadMidLower = int((SpreadAvg+SpreadMin)/2);
                SpreadAvgUpper = int((SpreadAvg+SpreadMidUpper)/2);
                SpreadAvgLower = int((SpreadAvg+SpreadMidLower)/2);
                SpreadUpper = int((SpreadMidUpper+SpreadMax)/2);
                SpreadLower = int((SpreadMidLower+SpreadMin)/2);
    
                int Spread = Spread(SYMBOL);//Assign Symbol's Spread

    スプレッド値

    スプレッドを5つのクラスに分けます。

      • Excellent:現在のスプレッドがSpreadLowerより小さいまたはSpreadMinに等しい場合
      • Good:現在のスプレッドがSpreadLower変数以上で、かつSpreadAvgLower変数未満の場合
      • Normal:現在のスプレッドがSpreadAvgLower変数以下で、かつSpreadAvgUpper変数以下の場合
      • Bad:現在のスプレッドがSpreadAvgUpper変数よりも大きく、かつSpreadUpper変数以下の場合
      • Terrible:現在のスプレッドがSpreadUpper変数より大きい場合

                if(Spread<SpreadLower||Spread==SpreadMin)//Excellent
                  {
                   return SpreadRating_Excellent;
                  }
                else
                   if(Spread>=SpreadLower&&Spread<SpreadAvgLower)//Good
                     {
                      return SpreadRating_Good;
                     }
                   else
                      if(Spread>=SpreadAvgLower&&Spread<=SpreadAvgUpper)//Normal
                        {
                         return SpreadRating_Normal;
                        }
                      else
                         if(Spread>SpreadAvgUpper&&Spread<=SpreadUpper)//Bad
                           {
                            return SpreadRating_Bad;
                           }
                         else//Terrible
                           {
                            return SpreadRating_Terrible;
                           }
    • 評価に基づいてスプレッドカラーを取得する関数の宣言
    color             SpreadColor(string SYMBOL=NULL);//Retrieve Spread Color

    各スプレッド列挙値に対するスプレッドの色を取得するために、列挙値が一定であることからswitch文の使用を検討します。各評価の色はご覧の通りです。

      • Excellent:ライトモードではclrBlue

    Excellentライトモード

     ダークモードではclrLightCyan

    Excellent ダークモード

      • Good:ライトモードではclrCornflowerBlue

    Goodライトモード
    ダークモードではclrLightGreen
    Goodダークモード

      • Normal:ライトモードではclrBlack
    Normalライトモード
     ダークモードではclrWheat
    Normal:ダークモード
      • Bad:clrOrange
      • Terrible:clrRed
      • デフォルト:ライトモードではclrBlack、ダークモードではclrWheat

    //+------------------------------------------------------------------+
    //|Retrieve Spread Color                                             |
    //+------------------------------------------------------------------+
    color CSymbolProperties::SpreadColor(string SYMBOL=NULL)
      {
       switch(SpreadValue(SYMBOL))//Get Spread Rating value
         {
          case SpreadRating_Excellent://Excellent Spread
             return (isLightMode)?clrBlue:clrLightCyan;
             break;
          case SpreadRating_Good://Good Spread
             return (isLightMode)?clrCornflowerBlue:clrLightGreen;
             break;
          case SpreadRating_Normal://Normal Spread
             return (isLightMode)?clrBlack:clrWheat;
             break;
          case SpreadRating_Bad://Bad Spread
             return clrOrange;
             break;
          case SpreadRating_Terrible://Terrible Spread
             return clrRed;
             break;
          default://failed to be identified
             return (isLightMode)?clrBlack:clrWheat;//Retrieve default color when failed.
             break;
         }
      }
    • スプレッドの説明を取得する文字列関数の宣言
    string            SpreadDesc(string SYMBOL=NULL);//Retrieve Spread Description
    //+------------------------------------------------------------------+
    //|Retrieve Spread Description                                       |
    //+------------------------------------------------------------------+
    string CSymbolProperties::SpreadDesc(string SYMBOL=NULL)
      {
       switch(SpreadValue(SYMBOL))//Get Spread Rating value
         {
          case SpreadRating_Excellent://Excellent Spread
             return "Excellent";
             break;
          case SpreadRating_Good://Good Spread
             return "Good";
             break;
          case SpreadRating_Normal://Normal Spread
             return "Normal";
             break;
          case SpreadRating_Bad://Bad Spread
             return "Bad";
             break;
          case SpreadRating_Terrible://Terrible Spread
             return "Terrible";
             break;
          default://failed to be identified
             return "Unknown";//Retrieve default value when failed.
             break;
         }
      }
    • 銘柄の説明を取得する文字列関数の宣言
    string            Description(string SYMBOL=NULL);//Retrieve Symbol's Description
    //+------------------------------------------------------------------+
    //|Retrieve Symbol's Description                                     |
    //+------------------------------------------------------------------+
    string CSymbolProperties::Description(string SYMBOL=NULL)
      {
       if(SetSymbolName(SYMBOL))//Set Symbol
         {
          return CSymbol.Description();
         }
       Print("Unable to retrieve Symbol's Description");
       return "";//Retrieve an empty string when failed.
      }

    銘柄の説明


    チャートプロパティクラス

    このクラスは第2回から再編成され、MQL5のインクルードクラスのチャートクラスを継承するようになりました。ChartProp構造体には、変更されるすべてのチャートプロパティが格納されています。Public関数ChartRefreshは、まずChartGet関数を呼び出してチャートプロパティを初期化し、その後、取得したプロパティ値を使ってChartSet関数を呼び出し、チャートを構成します。

    #include "SymbolProperties.mqh"
    #include <Charts/Chart.mqh>
    CSymbolProperties CSymbol;//Symbol Properties object
    //+------------------------------------------------------------------+
    //|ChartProperties class                                             |
    //+------------------------------------------------------------------+
    class CChartProperties : public CChart
      {
    private:
    //Structure for chart properties
       struct ChartProp
         {
          ENUM_CHART_MODE mode;//Chart Mode
          color          clrBackground;//Chart Background Color
          color          clrForeground;//Chart Foreground Color
          color          clrLineLast;//Chart Line Color
          color          clrCandleBear;//Chart Bear Candle Color
          color          clrBarDown;//Chart Down Candle Color
          color          clrCandleBull;//Chart Bull Candle Color
          color          clrBarUp;//Chart Up Candle Color
          color          clrLineAsk;//Chart Ask Color
          color          clrLineBid;//Chart Bid Color
          color          clrChartLine;//Chart Line Color
          color          clrStopLevels;//Chart Stop Level Color
          color          clrVolumes;//Chart Volumes Color
          bool           Foreground;//Chart Foreground Visibility
          bool           ShowLineAsk;//Chart Ask Line Visibility
          bool           ShowLineBid;//Chart Bid Line Visibility
          bool           ShowPeriodSep;//Chart Period Separator Visibility
          bool           ShowOHLC;//Chart Open-High-Low-Close Visibility
          bool           ShowGrid;//Chart Grid Visibility
          ENUM_CHART_VOLUME_MODE ShowVolumes;//Chart Volumes Visibility
          bool           AutoScroll;//Chart Auto Scroll Option
          bool           Shift;//Chart Shift Option
          double         ShiftSize;//Chart Shift Size
          bool           ShowObjectDescr;//Chart Object Descriptions
          ulong          CHART_SHOW_TRADE_LEVELS;//Chart Trade Levels Visibility
          ulong          CHART_SHOW_ONE_CLICK;//Chart One Click Trading Visibility
          ulong          CHART_SHOW_TICKER;//Chart Ticker Visibility
          ulong          CHART_DRAG_TRADE_LEVELS;//Chart Drag Trade levels
          ENUM_CHART_POSITION Navigate;//Chart Navigate
         };
       ChartProp         DefaultChart,MyChart;//Used to store chart properties
       void              ChartSet(ChartProp &Prop);//Apply Chart format
       void              ChartGet();//Assign Chart property values
    public:
                         CChartProperties();//Constructor
                        ~CChartProperties(void);//Destructor
                         //Configure the chart
       void              ChartRefresh() {ChartGet();ChartSet(MyChart);}
       string            GetChartPeriodName();//Retrieve Period name
      };

    コンストラクタでは、継承変数m_chart_idに現在のチャートIDを代入します。

    //+------------------------------------------------------------------+
    //|Constructor                                                       |
    //+------------------------------------------------------------------+
    CChartProperties::CChartProperties()
      {
       m_chart_id=ChartID();//Set chart id
       ChartGet();//Get chart values
       ChartSet(MyChart);//customize chart
      }

    ChartGet関数では、変数DefaultChartとMyChartに値を割り当てます。DefaultChartには、チャートを変更する前の現在のチャートのプロパティが保存され、MyChartにはカスタム値が保存されます。

    //+------------------------------------------------------------------+
    //|Assign Chart property values                                      |
    //+------------------------------------------------------------------+
    void CChartProperties::ChartGet()
      {
       DefaultChart.mode = Mode();//assign chart mode
       MyChart.mode = CHART_CANDLES;//assign custom chart mode
       DefaultChart.clrBackground = ColorBackground();//assign Background color
       MyChart.clrBackground = (isLightMode)?clrWhite:clrBlack;//assign custom Background color
       DefaultChart.clrForeground = ColorForeground();//assign foreground color
       MyChart.clrForeground = (isLightMode)?clrBlack:clrWhite;//assign custom foreground color
       DefaultChart.clrLineLast = ColorLineLast();//assign Chart Line Color
       MyChart.clrLineLast = clrWhite;//assign custom Chart Line Color
       DefaultChart.clrCandleBear = ColorCandleBear();//assign Chart Bear Candle Color
       MyChart.clrCandleBear = clrBlack;//assign custom Chart Bear Candle Color
       DefaultChart.clrBarDown = ColorBarDown();//assign Chart Down Candle Color
       MyChart.clrBarDown = (isLightMode)?clrBlack:CSymbol.Background();//assign custom Chart Down Candle Color
       DefaultChart.clrCandleBull = ColorCandleBull();//assign Chart Bull Candle Color
       MyChart.clrCandleBull = CSymbol.Background();//assign custom Chart Bull Candle Color
       DefaultChart.clrBarUp = ColorBarUp();//assign Chart Up Candle Color
       MyChart.clrBarUp = (isLightMode)?clrBlack:CSymbol.Background();//assign custom Chart Up Candle Color
       DefaultChart.clrLineAsk = ColorLineAsk();//assign Chart Ask Color 
       MyChart.clrLineAsk = (isLightMode)?clrBlack:clrWhite;//assign custom Chart Ask Color
       DefaultChart.clrLineBid = ColorLineBid();//assign Chart Bid Color
       MyChart.clrLineBid = (isLightMode)?clrBlack:CSymbol.Background();//assign custom Chart Bid Color
       DefaultChart.clrChartLine = ColorChartLine();//assign Chart Line Color
       MyChart.clrChartLine = (isLightMode)?clrBlack:clrWhite;//assign custom Chart Line Color
       DefaultChart.clrStopLevels = ColorStopLevels();//assign Chart Stop Level Color
       MyChart.clrStopLevels = clrRed;//assign custom Chart Stop Level Color
       DefaultChart.clrVolumes = ColorVolumes();//assign Chart Volumes Color
       MyChart.clrVolumes = clrGreen;//assign custom Chart Volumes Color
       DefaultChart.Foreground = Foreground();//assign Chart Foreground Visibility
       MyChart.Foreground = false;//assign custom Chart Foreground Visibility
       DefaultChart.ShowLineAsk = ShowLineAsk();//assign Chart Ask Line Visibility
       MyChart.ShowLineAsk = true;//assign custom Chart Ask Line Visibility
       DefaultChart.ShowLineBid = ShowLineBid();//assign Chart Bid Line Visibility
       MyChart.ShowLineBid = true;//assign custom Chart Bid Line Visibility
       DefaultChart.ShowPeriodSep = ShowPeriodSep();//assign Chart Period Separator Visibility
       MyChart.ShowPeriodSep = true;//assign custom Chart Period Separator Visibility
       DefaultChart.ShowOHLC = ShowOHLC();//assign Chart Open-High-Low-Close Visibility
       MyChart.ShowOHLC = false;//assign custom Chart Open-High-Low-Close Visibility
       DefaultChart.ShowGrid = ShowGrid();//assign Chart Grid Visibility
       MyChart.ShowGrid = false;//assign custom Chart Grid Visibility
       DefaultChart.ShowVolumes = ShowVolumes();//assign Chart Volumes Visibility
       MyChart.ShowVolumes = CHART_VOLUME_HIDE;//assign custom Chart Volumes Visibility
       DefaultChart.AutoScroll = AutoScroll();//assign Chart Auto Scroll Option
       MyChart.AutoScroll = true;//assign custom Chart Auto Scroll Option
       DefaultChart.Shift = Shift();//assign Chart Shift Option
       MyChart.Shift = true;//assign custom Chart Shift Option
       DefaultChart.ShiftSize = ShiftSize();//assign Chart Shift Size
       MyChart.ShiftSize = 15;//assign custom Chart Shift Size
       DefaultChart.ShowObjectDescr = ShowObjectDescr();//assign Chart Object Descriptions
       MyChart.ShowObjectDescr = false;//assign custom Chart Object Descriptions
       DefaultChart.Navigate = CHART_END;//assign Chart Navigate
       MyChart.Navigate = CHART_END;//assign custom Chart Navigate
       //---assign Chart Trade Levels Visibility
       DefaultChart.CHART_SHOW_TRADE_LEVELS = ChartGetInteger(ChartId(),CHART_SHOW_TRADE_LEVELS);
       //---assign custom Chart Trade Levels Visibility
       MyChart.CHART_SHOW_TRADE_LEVELS = ulong(true);
       //---assign Chart One Click Trading Visibility
       DefaultChart.CHART_SHOW_ONE_CLICK = ChartGetInteger(ChartId(),CHART_SHOW_ONE_CLICK);
       //---assign custom Chart One Click Trading Visibility
       MyChart.CHART_SHOW_ONE_CLICK = ulong(false);
       //---assign Chart Ticker Visibility
       DefaultChart.CHART_SHOW_TICKER = ChartGetInteger(ChartId(),CHART_SHOW_TICKER);
       //---assign custom Chart Ticker Visibility
       MyChart.CHART_SHOW_TICKER = ulong(false);
       //---assign Chart Drag Trade levels
       DefaultChart.CHART_DRAG_TRADE_LEVELS = ChartGetInteger(ChartId(),CHART_DRAG_TRADE_LEVELS);
       //---assign custom Chart Drag Trade levels
       MyChart.CHART_DRAG_TRADE_LEVELS = ulong(false);
      }

    ChartSet関数はChartProp構造体を引数として取り、現在のチャートを設定します。

    //+------------------------------------------------------------------+
    //|Apply Chart format                                                |
    //+------------------------------------------------------------------+
    void CChartProperties::ChartSet(ChartProp &Prop)
      {
       Mode(Prop.mode);//Set Chart Candle Mode
       ColorBackground(Prop.clrBackground);//Set Chart Background Color
       ColorForeground(Prop.clrForeground);//Set Chart Foreground Color
       ColorLineLast(Prop.clrLineLast);//Set Chart Line Color
       ColorCandleBear(Prop.clrCandleBear);//Set Chart Bear Candle Color
       ColorBarDown(Prop.clrBarDown);//Set Chart Down Candle Color
       ColorCandleBull(Prop.clrCandleBull);//Set Chart Bull Candle Color
       ColorBarUp(Prop.clrBarUp);//Set Chart Up Candle Color
       ColorLineAsk(Prop.clrLineAsk);//Set Chart Ask Color
       ColorLineBid(Prop.clrLineBid);//Set Chart Bid Color
       ColorChartLine(Prop.clrChartLine);//Set Chart Line Color
       ColorStopLevels(Prop.clrStopLevels);//Set Chart Stop Level Color
       ColorVolumes(Prop.clrVolumes);//Set Chart Volumes Color
       Foreground(Prop.Foreground);//Set if Chart is in Foreground Visibility
       ShowLineAsk(Prop.ShowLineAsk);//Set Chart Ask Line Visibility
       ShowLineBid(Prop.ShowLineBid);//Set Chart Bid Line Visibility
       ShowPeriodSep(Prop.ShowPeriodSep);//Set Chart Period Separator Visibility
       ShowOHLC(Prop.ShowOHLC);//Set Chart Open-High-Low-Close Visibility
       ShowGrid(Prop.ShowGrid);//Set Chart Grid Visibility
       ShowVolumes(Prop.ShowVolumes);//Set Chart Volumes Visibility
       AutoScroll(Prop.AutoScroll);//Set Chart Auto Scroll Option
       Shift(Prop.Shift);//Set Chart Shift Option
       ShiftSize(Prop.ShiftSize);//Set Chart Shift Size Value
       ShowObjectDescr(Prop.ShowObjectDescr);//Set Chart Show Object Descriptions
       ChartSetInteger(ChartId(),CHART_SHOW_TRADE_LEVELS,Prop.CHART_SHOW_TRADE_LEVELS);//Set Chart Trade Levels Visibility
       ChartSetInteger(ChartId(),CHART_SHOW_ONE_CLICK,Prop.CHART_SHOW_ONE_CLICK);//Set Chart One Click Trading Visibility
       ChartSetInteger(ChartId(),CHART_SHOW_TICKER,Prop.CHART_SHOW_TICKER);//Set Chart Ticker Visibility
       ChartSetInteger(ChartId(),CHART_DRAG_TRADE_LEVELS,Prop.CHART_DRAG_TRADE_LEVELS);//Set Chart Drag Trade levels
       Navigate(Prop.Navigate);//Set Chart Navigate
      }

    GetChartPeriodName関数は、switch文を使って現在のチャートのチャート期間名を取得します。

    //+------------------------------------------------------------------+
    //|Retrieve Period name                                              |
    //+------------------------------------------------------------------+
    string CChartProperties::GetChartPeriodName()
      {
       switch(ChartPeriod(ChartId()))//Get chart Period with chart id
         {
          case PERIOD_M1:
             return("M1");
          case PERIOD_M2:
             return("M2");
          case PERIOD_M3:
             return("M3");
          case PERIOD_M4:
             return("M4");
          case PERIOD_M5:
             return("M5");
          case PERIOD_M6:
             return("M6");
          case PERIOD_M10:
             return("M10");
          case PERIOD_M12:
             return("M12");
          case PERIOD_M15:
             return("M15");
          case PERIOD_M20:
             return("M20");
          case PERIOD_M30:
             return("M30");
          case PERIOD_H1:
             return("H1");
          case PERIOD_H2:
             return("H2");
          case PERIOD_H3:
             return("H3");
          case PERIOD_H4:
             return("H4");
          case PERIOD_H6:
             return("H6");
          case PERIOD_H8:
             return("H8");
          case PERIOD_H12:
             return("H12");
          case PERIOD_D1:
             return("Daily");
          case PERIOD_W1:
             return("Weekly");
          case PERIOD_MN1:
             return("Monthly");
         }
       return("unknown period");
      }

    デストラクタは、チャートに変更を加える前の、以前のチャート構成を復元します。

    //+------------------------------------------------------------------+
    //|Destructor                                                        |
    //+------------------------------------------------------------------+
    CChartProperties::~CChartProperties()
      {
       ChartSet(DefaultChart);//restore chart default configuration
       m_chart_id=-1;//reset chart id
      }



    オブジェクトプロパティクラス

    このクラスでは、カスタムオブジェクトの文字色にいくつかの変更が加えられました。第2回では、すべてのテキストオブジェクトに対して1つの文字色しか使用できませんでした。この問題を解決するために、TextObj_colorという名前のカラー変数をクラス外で宣言する方法が採用されています。

    #include "ChartProperties.mqh"
    color TextObj_color;
    //+------------------------------------------------------------------+
    //|ObjectProperties class                                            |
    //+------------------------------------------------------------------+
    class CObjectProperties:public CChartProperties
      {
    private:
       //Simple  chart objects structure
       struct ObjStruct
         {
          long           ChartId;
          string         Name;
         } Objects[];//ObjStruct variable array
    
       //-- Add chart object to Objects array
       void              AddObj(long chart_id,string name)
         {
          ArrayResize(Objects,Objects.Size()+1,Objects.Size()+2);
          Objects[Objects.Size()-1].ChartId=chart_id;
          Objects[Objects.Size()-1].Name=name;
         }
    
    protected:
       void              DeleteObj()
         {
          for(uint i=0;i<Objects.Size();i++)
            {
             ObjectDelete(Objects[i].ChartId,Objects[i].Name);
            }
         }
    
    public:
                         CObjectProperties(void) {}//Class constructor
    
       //-- Create Rectangle chart object
       void              Square(long chart_ID,string name,int x_coord,int y_coord,int width,int height,ENUM_ANCHOR_POINT Anchor);
    
       //-- Create text chart object
       void              TextObj(long chartID,string name,string text,int x_coord,int y_coord,
                                 ENUM_BASE_CORNER Corner=CORNER_LEFT_UPPER,int fontsize=10);
    
       //-- Create Event object
       void               EventObj(long chartID,string name,string description,datetime eventdate);
    
       //-- Class destructor removes all chart objects created previously
                        ~CObjectProperties(void)
         {
          DeleteObj();
         }
      };

    下に見るように、Textobj関数のパラメータはたくさんあるので、パラメータが長くなるのを避けるために、テキストオブジェクトの色を変更するためにTextobj_colorを使うことにします。

    //+------------------------------------------------------------------+
    //|Create text chart object                                          |
    //+------------------------------------------------------------------+
    void CObjectProperties::TextObj(long chartID,string name,string text,int x_coord,int y_coord,
                                    ENUM_BASE_CORNER Corner=CORNER_LEFT_UPPER,int fontsize=10)
      {
       ObjectDelete(chartID,name);//Delete previous object with the same name and chart id
       if(ObjectCreate(chartID,name,OBJ_LABEL,0,0,0))//Create object label
         {
          AddObj(chartID,name);//Add object to array
          ObjectSetInteger(chartID,name,OBJPROP_XDISTANCE,x_coord);//Set x Distance/coordinate
          ObjectSetInteger(chartID,name,OBJPROP_YDISTANCE,y_coord);//Set y Distance/coordinate
          ObjectSetInteger(chartID,name,OBJPROP_CORNER,Corner);//Set object's corner anchor
          ObjectSetString(chartID,name,OBJPROP_TEXT,text);//Set object's text
          ObjectSetInteger(chartID,name,OBJPROP_COLOR,TextObj_color);//Set object's color
          ObjectSetInteger(chartID,name,OBJPROP_FONTSIZE,fontsize);//Set object's font-size
         }
       else
         {
          Print("Failed to create object: ",name);
         }
      }

    チャートカラーモードに応じて背景色を変えられるように、Square関数を少し変更しました。

    //+------------------------------------------------------------------+
    //|Create Rectangle chart object                                     |
    //+------------------------------------------------------------------+
    void CObjectProperties::Square(long chart_ID,string name,int x_coord,int y_coord,int width,int height,ENUM_ANCHOR_POINT Anchor)
      {
       const int              sub_window=0;             // subwindow index
       const int              x=x_coord;                // X coordinate
       const int              y=y_coord;                // Y coordinate
       const color            back_clr=(isLightMode)?clrWhite:clrBlack;// background color
       const ENUM_BORDER_TYPE border=BORDER_SUNKEN;     // border type
       const color            clr=clrRed;               // flat border color (Flat)
       const ENUM_LINE_STYLE  style=STYLE_SOLID;        // flat border style
       const int              line_width=0;             // flat border width
       const bool             back=false;               // in the background
       const bool             selection=false;          // highlight to move
       const bool             hidden=true;              // hidden in the object list
    
       ObjectDelete(chart_ID,name);//Delete previous object with the same name and chart id
       if(ObjectCreate(chart_ID,name,OBJ_RECTANGLE_LABEL,sub_window,0,0))//create rectangle object label
         {
          AddObj(chart_ID,name);//Add object to array
          ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);//Set x Distance/coordinate
          ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);//Set y Distance/coordinate
          ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);//Set object's width/x-size
          ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);//Set object's height/y-size
          ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);//Set object's background color
          ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_TYPE,border);//Set object's border type
          ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,Anchor);//Set objects anchor point
          ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);//Set object's color
          ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);//Set object's style
          ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,line_width);//Set object's flat border width
          ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);//Set if object is in foreground or not
          ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);//Set if object is selectable/dragable
          ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);//Set if object is Selected
          ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);//Set if object is hidden in object list
          ChartRedraw(chart_ID);
         }
       else
         {
          Print("Failed to create object: ",name);
         }
      }


    共通変数のヘッダーファイル

    取引の目的で、メモリ内にデータベースを作成することにしました。このデータベースには名前が必要で、その名前にはブローカー名、現在のチャートID、そしてEAがストラテジーテスター内にあるかどうかを考慮した要素が含まれます。  

    #define NEWS_DATABASE_MEMORY           StringFormat("Calendar_%s_%d_%s.sqlite",broker,ChartID(),(MQLInfoInteger(MQL_TESTER)?"TESTER":"REAL"))

    Choice列挙体はパーソナライズ用で、EAの入力に使用され、ブールデータ型に置き換わります。DayOfTheWeek列挙体は、土曜日と日曜日を除いた週の取引日を選択するために使用されます。一方、ブール関数Answerは、Choice列挙体をブールデータ型に変換します。

    enum Choice
      {
       Yes,//YES
       No//NO
      };
    
    enum DayOfTheWeek
      {
       Monday,//MONDAY
       Tuesday,//TUESDAY
       Wednesday,//WEDNESDAY
       Thursday,//THURSDAY
       Friday,//FRIDAY
       AllDays//ALL DAYS
      };
    
    //+------------------------------------------------------------------+
    //|Convert enumeration Choice into a boolean value                   |
    //+------------------------------------------------------------------+
    bool Answer(Choice choose)
      {
       return (choose==Yes)?true:false;
      }


    時間変数クラス

    このクラスの目的は、ローソク足の時間データを保存することです。このデータは、新しいローソク足が形成されたかどうかを確認するために使用されます。

    //+------------------------------------------------------------------+
    //|TimeVariables class                                               |
    //+------------------------------------------------------------------+
    class CTimeVariables
      {
    private:
       //---Array to store candlestick times
       datetime          CandleTime[2000];
    public:
                         CTimeVariables(void);
       //---Set Array index time
       void              SetTime(uint index,datetime time);
       //---Get Array index time
       datetime          GetTime(uint index);
      };

    コンストラクタでは、CandleTime配列内のすべてのインデックスにデフォルトの時刻を設定します。

    //+------------------------------------------------------------------+
    //|Constructor                                                       |
    //+------------------------------------------------------------------+
    CTimeVariables::CTimeVariables()
      {
       for(uint i=0; i<CandleTime.Size(); i++)
         {
          CandleTime[i]=D'1970.01.01';
         }
      }

    関数SetTimeには2つのパラメータがあり、1つは配列のインデックス、もう1つは日時です。もし引数indexが0以上で、CandleTimeのサイズより小さければ、引数timeに配列のインデックスを代入します。 

    //+------------------------------------------------------------------+
    //|Set Array index time                                              |
    //+------------------------------------------------------------------+
    void CTimeVariables::SetTime(uint index,datetime time)
      {
       if(index>=0&&index<CandleTime.Size())
         {
          CandleTime[index] = time;
         }
      }

    関数GetTimeは、正の整数の引数を1つ受け取り、index引数が有効であれば、CandleTimeで配列のindex値からdatetimeを取得します。

    //+------------------------------------------------------------------+
    //|Get Array index time                                              |
    //+------------------------------------------------------------------+
    datetime CTimeVariables::GetTime(uint index)
      {
       return (index>=0&&index<CandleTime.Size())?CandleTime[index]:datetime(0);
      }


    時間管理クラス

    DSTSchedule列挙体を宣言し、ユーザーやトレーダーがEAの入力に対して自動DSTまたはカスタムDSTのいずれかを選択できるようにします。MySchedule変数はカスタムDSTを保存するために使用されます。

    //-- Enumeration for DST schedule
    enum DSTSchedule
      {
       AutoDst_Selection,//AUTO DST
       CustomDst_Selection//CUSTOM DST
      } MyDST;
    
    DST_type MySchedule;//Variable for custom DST schedule

    以下の関数は、特定の日付の時間を整数データ型で返します。 

    int               ReturnHour(datetime time);//Returns the Hour for a specific date
    //+------------------------------------------------------------------+
    //|Returns the Hour for a specific date                              |
    //+------------------------------------------------------------------+
    int CTimeManagement::ReturnHour(datetime time)
      {
       return Time(time).hour;
      }

    以下の関数は、特定の日付の分を整数データ型で返します。 

    int               ReturnMinute(datetime time);//Returns the Minute for a specific date
    //+------------------------------------------------------------------+
    //|Returns the Minute for a specific date                            |
    //+------------------------------------------------------------------+
    int CTimeManagement::ReturnMinute(datetime time)
      {
       return Time(time).min;
      }

    以下の関数は、特定の日付の秒を整数データ型で返します。 

    int               ReturnSecond(datetime time);//Returns the Second for s specific date
    //+------------------------------------------------------------------+
    //|Returns the Second for s specific date                            |
    //+------------------------------------------------------------------+
    int CTimeManagement::ReturnSecond(datetime time)
      {
       return Time(time).sec;
      }

    以下の関数はdatetime型引数に対応するMqlDateTimeを返します。

    //-- Will convert datetime to MqlDateTime
       MqlDateTime       Time(datetime Timetoformat);
    //+------------------------------------------------------------------+
    //|Will convert datetime to MqlDateTime                              |
    //+------------------------------------------------------------------+
    MqlDateTime CTimeManagement::Time(datetime Timetoformat)
      {
       TimeToStruct(Timetoformat,timeFormat);
       return timeFormat;
      }

    以下の関数は、時、分、秒を修正したdatetime型引数timeに対応する値をdatetime型で返します。

    //-- Will return a datetime with changes to the hour,minute and second
       datetime          Time(datetime time,int Hour,int Minute,int Second);
    //+------------------------------------------------------------------+
    //|Will return a datetime with changes to the hour,minute and second |
    //+------------------------------------------------------------------+
    datetime CTimeManagement::Time(datetime time,int Hour,int Minute,int Second)
      {
       timeFormat=Time(time);
       timeFormat.hour=Hour;
       timeFormat.min=Minute;
       timeFormat.sec=Second;
       return StructToTime(timeFormat);
      }

    以下の関数は、時間と分を変更したdatetime型引数の日時をdatetime型で返します。

    //-- Will return a datetime with changes to the hour and minute
       datetime          Time(datetime time,int Hour,int Minute);
    //+------------------------------------------------------------------+
    //|Will return a datetime with changes to the hour and minute        |
    //+------------------------------------------------------------------+
    datetime CTimeManagement::Time(datetime time,int Hour,int Minute)
      {
       timeFormat=Time(time);
       timeFormat.hour=Hour;
       timeFormat.min=Minute;
       return StructToTime(timeFormat);
      }

    以下の関数は、TimeTradeServerの時刻が引数BeginTimeとEndTimeの範囲内であればtrueを返します。

    //-- Check current time is within a time range
       bool              TimeIsInRange(datetime BeginTime,datetime EndTime);
    //+------------------------------------------------------------------+
    //|Check current time is within a time range                         |
    //+------------------------------------------------------------------+
    bool CTimeManagement::TimeIsInRange(datetime BeginTime,datetime EndTime)
      {
       if(BeginTime<=TimeTradeServer()&&EndTime>=TimeTradeServer())
         {
          return true;
         }
       return false;
      }

    以下の関数は、PreEventのdatetimeがTimeTradeServer以下で、EventTimeがTimeTradeServer以上の場合にtrueを返します。

    //-- Check if current time is within preEvent time and Event time
       bool              TimePreEvent(datetime PreEvent,datetime Event);
    //+------------------------------------------------------------------+
    //|Check if current time is within preEvent time and Event time      |
    //+------------------------------------------------------------------+
    bool CTimeManagement::TimePreEvent(datetime PreEventTime,datetime EventTime)
      {
       if(PreEventTime<=TimeTradeServer()&&EventTime>TimeTradeServer())
         {
          return true;
         }
       return false;
      }

    以下の関数は、時、分を修正した現在時刻をMqlDateTime型で返します。

    //-- Return MqlDateTime for current date time with custom hour and minute
       MqlDateTime       Today(int Hour,int Minute);
    //+------------------------------------------------------------------+
    //|Return MqlDateTime for current date time with custom hour and     |
    //|minute                                                            |
    //+------------------------------------------------------------------+
    MqlDateTime CTimeManagement::Today(int Hour,int Minute)
      {
       TimeTradeServer(today);
       today.hour=Hour;
       today.min=Minute;
       return today;
      }

    以下の関数は、時、分、秒を修正した現在時刻をMqlDateTime型で返します。

    //-- Return MqlDateTime for current date time with custom hour, minute and second
       MqlDateTime       Today(int Hour,int Minute,int Second);
    //+------------------------------------------------------------------+
    //|Return MqlDateTime for current date time with custom hour, minute |
    //|and second                                                        |
    //+------------------------------------------------------------------+
    MqlDateTime CTimeManagement::Today(int Hour,int Minute,int Second)
      {
       TimeTradeServer(today);
       today.hour=Hour;
       today.min=Minute;
       today.sec=Second;
       return today;
      }

    以下の関数は、現在の曜日が対応する曜日に等しい場合、または列挙体DayOfTheWeekがAllDaysに等しい場合にtrueを返します。

    //-- Check current day of the week
       bool              isDayOfTheWeek(DayOfTheWeek Day);
    //+------------------------------------------------------------------+
    //|Check current day of the week                                     |
    //+------------------------------------------------------------------+
    bool CTimeManagement::isDayOfTheWeek(DayOfTheWeek Day)
      {
       switch(Day)
         {
          case  Monday://Monday
             if(DayOfWeek(TimeTradeServer())==MONDAY)
               {
                return true;
               }
             break;
          case Tuesday://Tuesday
             if(DayOfWeek(TimeTradeServer())==TUESDAY)
               {
                return true;
               }
             break;
          case Wednesday://Wednesday
             if(DayOfWeek(TimeTradeServer())==WEDNESDAY)
               {
                return true;
               }
             break;
          case Thursday://Thursday
             if(DayOfWeek(TimeTradeServer())==THURSDAY)
               {
                return true;
               }
             break;
          case Friday://Friday
             if(DayOfWeek(TimeTradeServer())==FRIDAY)
               {
                return true;
               }
             break;
          case AllDays://All days
             return true;
             break;
          default://Unknown
             break;
         }
       return false;
      }

    以下の関数は、特定の日付の曜日を返します。

    //-- Return enumeration Day of week for a certain date
       ENUM_DAY_OF_WEEK  DayOfWeek(datetime time);
    //+------------------------------------------------------------------+
    //|Return enumeration Day of week for a certain date                 |
    //+------------------------------------------------------------------+
    ENUM_DAY_OF_WEEK CTimeManagement::DayOfWeek(datetime time)
      {
       return (ENUM_DAY_OF_WEEK)Time(time).day_of_week;
      }


    ローソク足プロパティクラス

    このクラスには新しい関数が追加されました。

    //+------------------------------------------------------------------+
    //|CandleProperties class                                            |
    //+------------------------------------------------------------------+
    class CCandleProperties : public CChartProperties
      {
    private:
       CTimeManagement   Time;//TimeManagement object
       CTimeVariables    CTV;//Timevariables object
    public:
       double            Open(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle Open-Price
       double            Close(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle Close-Price
       double            High(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle High-Price
       double            Low(int CandleIndex,ENUM_TIMEFRAMES Period=PERIOD_CURRENT,string SYMBOL=NULL);//Retrieve Candle Low-Price
       bool              IsLargerThanPreviousAndNext(datetime CandleTime,int Offset,string SYMBOL);//Determine if one candle is larger than two others
       bool              NewCandle(int index,ENUM_TIMEFRAMES period=PERIOD_CURRENT,string SYMBOL=NULL);//Check if a new candle is present
      };

    関数NewCandleは、新しいローソク足が形成されるとtrueを返し、SetTime関数を使って現在のローソク足の開始時間をクラスTimevariablesに保存します。以前に保存された時間と現在のローソク足の開始時間を比較し、時間が異なるかどうかを確認します。もし時間が異なれば、新しいローソク足が形成されたと見なします。

    //+------------------------------------------------------------------+
    //|Check if a new candle is present                                  |
    //+------------------------------------------------------------------+
    bool CCandleProperties::NewCandle(int index,ENUM_TIMEFRAMES period=PERIOD_CURRENT,string SYMBOL=NULL)
      {
       if(CTV.GetTime(index) == iTime(((SYMBOL==NULL)?Symbol():SYMBOL),period,0))
         {
          return false;//Candle time are equal no new candles have formed
         }
       else
         {
         //--- Candle time has changed set the new time
          CTV.SetTime(index,iTime(((SYMBOL==NULL)?Symbol():SYMBOL),period,0));
          return true;
         }
      }


    セッションクラス

    このクラスの目的は、取引セッションの時間を管理することです。この記事では、これらの取引セッションの時間を使用しませんが、後ほどこのクラスを活用する予定です。このクラスは、TimeManagement関数を利用するため、TimeManagementクラスを継承しています。

    セッション時間

    #include "Timemanagement.mqh"
    //+------------------------------------------------------------------+
    //|Sessions Class                                                    |
    //+------------------------------------------------------------------+
    class CSessions:CTimeManagement
      {
    public:
                         CSessions(void) {}
                        ~CSessions(void) {}
       //--- Check if trading Session has began
       bool              isSessionStart(int offsethour=0,int offsetmin=0);
       //--- Check if trading Session has ended
       bool              isSessionEnd(int offsethour=0,int offsetmin=45);
       //--- Get Session End datetime
       datetime          SessionEnd(int offsethour=0,int offsetmin=45);
      };

    以下の関数は、現在の銘柄と曜日に対応するすべての有効な取引セッションを確認します。最も早い取引セッションが見つかると、その時間にオフセットを加えます。例えば、最も早い取引セッションが01:00から05:00の場合、オフセット時間として1時間を追加し、分は0とします。この場合、取引セッションは02:00から05:00に開始します。取引セッションの開始時間を知る目的は、通常取引セッションの開始時に発生する大きなスプレッドを避けることです。取引セッションが現在アクティブであれば、この関数はtrueを返します。 

    //+------------------------------------------------------------------+
    //|Check if trading Session has started                              |
    //+------------------------------------------------------------------+
    bool CSessions::isSessionStart(int offsethour=0,int offsetmin=0)
      {
    //--- Declarations
       datetime datefrom,dateto,DateFrom[],DateTo[];
    
    //--- Find all session times
       for(int i=0; i<10; i++)
         {
          //--- Get the session dates for the current symbol and Day of week
          if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto))
            {
             //--- Check if the end date's hour is at midnight
             if(ReturnHour(dateto)==00||ReturnHour(dateto)==24)
               {
                //--- Adjust the date to one minute before midnight
                dateto = Time(TimeTradeServer(),23,59);
               }
             //--- Re-adjust DateFrom Array size
             ArrayResize(DateFrom,int(ArraySize(DateFrom))+1,int(ArraySize(DateFrom))+2);
             //--- Assign the last array index datefrom value
             DateFrom[int(ArraySize(DateFrom))-1] = datefrom;
             //--- Re-adjust DateTo Array size
             ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2);
             //--- Assign the last array index dateto value
             DateTo[int(ArraySize(DateTo))-1] = dateto;
            }
         }
    
    //--- Check if there are session times
       if(DateFrom.Size()>0)
         {
          /* Adjust DateFrom index zero date as the first index date will be the earliest date
           from the whole array, we add the offset to this date only*/
          DateFrom[0] = TimePlusOffset(DateFrom[0],MinutesS(startoffsetmin));
          DateFrom[0] = TimePlusOffset(DateFrom[0],HoursS(startoffsethour));
          //--- Iterate through the whole array
          for(uint i=0; i<DateFrom.Size(); i++)
            {
             //--- Check if the current time is within the trading session
             if(TimeIsInRange(DateFrom[i],DateTo[i]))
               {
                return true;
               }
            }
         }
       else
         {
          //--- If there are no trading session times
          return true;
         }
       return false;
      }

    以下の関数は、セッションが終了した場合にtrueを返します。ブローカーによっては、取引セッションが終了する1時間前にスプレッドが大きくなる場合があるので、この関数はそのような時間帯の取引を避けるのに役立ちます。

    //+------------------------------------------------------------------+
    //|Check if trading Session has ended                                |
    //+------------------------------------------------------------------+
    bool CSessions::isSessionEnd(int offsethour=0,int offsetmin=45)
      {
    //--- Declarations
       datetime datefrom,dateto,DateTo[],lastdate=0,sessionend;
    
    //--- Find all session times
       for(int i=0; i<10; i++)
         {
          //--- Get the session dates for the current symbol and Day of week
          if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto))
            {
             //--- Check if the end date's hour is at midnight
             if(ReturnHour(dateto)==00||ReturnHour(dateto)==24)
               {
                //--- Adjust the date to one minute before midnight
                dateto = Time(TimeTradeServer(),23,59);
               }
             //--- Re-adjust DateTo Array size
             ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2);
             //--- Assign the last array index dateto value
             DateTo[int(ArraySize(DateTo))-1] = dateto;
            }
         }
    
    //--- Check if there are session times
       if(DateTo.Size()>0)
         {
          //--- Assign lastdate a default value
          lastdate = DateTo[0];
          //--- Iterate through the whole array
          for(uint i=0; i<DateTo.Size(); i++)
            {
             //--- Check for the latest date in the array
             if(DateTo[i]>lastdate)
               {
                lastdate = DateTo[i];
               }
            }
         }
       else
         {
          //--- If there are no trading session times
          return false;
         }
       /* get the current time and modify the hour and minute time to the lastdate variable
       and assign the new datetime to sessionend variable*/
       sessionend = Today(ReturnHour(lastdate),ReturnMinute(lastdate));
    //--- Re-adjust the sessionend dates with the minute and hour offsets
       sessionend = TimeMinusOffset(sessionend,MinutesS(offsetmin));
       sessionend = TimeMinusOffset(sessionend,HoursS(offsethour));
    
    //--- Check if sessionend date is more than the current time
       if(TimeTradeServer()<sessionend)
         {
          return false;
         }
       return true;
      }

    以下の関数は、現在の日の取引セッションの終了日を返します。MQL5の取引セッション時間にはいくつかの制限があり、休日には一部の銘柄が取引セッション時間よりもずっと早く終了する可能性があることに気付きました。これは留意すべき点です。

    //+------------------------------------------------------------------+
    //|Get Session End datetime                                          |
    //+------------------------------------------------------------------+
    datetime CSessions::SessionEnd(int offsethour=0,int offsetmin=45)
      {
    //--- Declarations
       datetime datefrom,dateto,DateTo[],lastdate=0,sessionend;
    
    //--- Find all session times
       for(int i=0; i<10; i++)
         {
          //--- Get the session dates for the current symbol and Day of week
          if(SymbolInfoSessionTrade(Symbol(),DayOfWeek(TimeTradeServer()),i,datefrom,dateto))
            {
             //--- Check if the end date's hour is at midnight
             if(CTV.ReturnHour(dateto)==00||CTV.ReturnHour(dateto)==24)
               {
                //--- Adjust the date to one minute before midnight
                dateto = Time(TimeTradeServer(),23,59);
               }
             //--- Re-adjust DateTo Array size
             ArrayResize(DateTo,int(ArraySize(DateTo))+1,int(ArraySize(DateTo))+2);
             //--- Assign the last array index dateto value
             DateTo[int(ArraySize(DateTo))-1] = dateto;
            }
         }
    
    //--- Check if there are session times
       if(DateTo.Size()>0)
         {
          //--- Assign lastdate a default value
          lastdate = DateTo[0];
          //--- Iterate through the whole array
          for(uint i=0; i<DateTo.Size(); i++)
            {
             //--- Check for the latest date in the array
             if(DateTo[i]>lastdate)
               {
                lastdate = DateTo[i];
               }
            }
         }
       else
         {
          //--- If there are no trading session times
          return 0;
         }
       /* get the current time and modify the hour and minute time to the lastdate variable
       and assign the new datetime to sessionend variable*/
       sessionend = Today(ReturnHour(lastdate),ReturnMinute(lastdate));
    //--- Re-adjust the sessionend dates with the minute and hour offsets
       sessionend = TimeMinusOffset(sessionend,MinutesS(offsetmin));
       sessionend = TimeMinusOffset(sessionend,HoursS(offsethour));
    //--- return sessionend date
       return sessionend;
      }


    ニュースクラス

    このクラスはプロジェクト全体で最も重要で、コードだけでも1000行以上に及ぶ最大のクラスです。第2回以降、このクラスとcommonフォルダ内のカレンダーデータベースとのやり取りに関するコードに大幅な改良を加えました。この記事では、新たにデータベースを作成しますが、今回はそのデータベースをメモリ内に構築します。

    メモリ内DBとストレージDBの比較における利点

    • スピード: メモリ内データベースはデータをRAMに直接保存するため、読み書きの速度が大幅に向上します。リアルタイムのデータ処理や分析が必要なアプリケーションに特に有利です。 RAMはディスクストレージよりも高速であるため、メモリ内データベースへのアクセスは迅速になり、応答時間が短縮され、全体的なパフォーマンスが向上します。
    • パフォーマンス: 待ち時間の短縮とデータアクセスの高速化は、スループットの向上を意味します。これにより、データベースが1秒あたりに処理できるトランザクション数が増加し、 大量のデータを効率的に処理できるため、ビッグデータ分析やその他のコンピューティング負荷が高いタスクに適しています。

    ストレージ上のデータベースは引き続き使用し、そこからデータを収集して、新しいメモリ内データベースに転送します。これにより、バックテスト時にバランスの取れたパフォーマンスを実現します。ストレージのデータベースのみを使用すると、コンピュータのスペックによってはパフォーマンスに大きな影響を与える可能性があるためです。

    まずはEAの入力に使用するために、クラス外の宣言から始めます。DBMemoryConnection整数変数は、メモリ内データベースの整数接続ハンドルを保持します。Calendar_Importance列挙体は、EAの入力パラメータで異なるイベントの重要度を選択するために使用されます。Event_Sector列挙体は、EAの入力パラメータで異なるイベントセクターを選択するために使用されます。Event_Frequency列挙体は、EAの入力パラメータに異なるイベント頻度を選択するために使用されます。Event_Type列挙体は、EAの入力パラメータに異なるイベントタイプを選択するために使用されます。Event_Currency列挙体は、EAの入力パラメータで異なるイベント通貨オプションを選択するために使用されます。UpcomingNews Calendar構造体変数は、他のクラス/ファイルで簡単にアクセスできるように、次の経済イベントの詳細を格納します。

    int       DBMemoryConnection;//In memory database handle
    
    //--- Enumeration for Calendar Importance
    enum Calendar_Importance
      {
       Calendar_Importance_None,//NONE
       Calendar_Importance_Low,//LOW
       Calendar_Importance_Moderate,//MODERATE
       Calendar_Importance_High,//HIGH
       Calendar_Importance_All//ALL
      } myImportance;
    
    //--- Enumeration for Calendar Sector
    enum Event_Sector
      {
       Event_Sector_None,//NONE
       Event_Sector_Market,//MARKET
       Event_Sector_Gdp,//GDP
       Event_Sector_Jobs,//JOBS
       Event_Sector_Prices,//PRICES
       Event_Sector_Money,//MONEY
       Event_Sector_Trade,//TRADE
       Event_Sector_Government,//GOVERNMENT
       Event_Sector_Business,//BUSINESS
       Event_Sector_Consumer,//CONSUMER
       Event_Sector_Housing,//HOUSING
       Event_Sector_Taxes,//TAXES
       Event_Sector_Holidays,//HOLIDAYS
       Event_Sector_ALL//ALL
      } mySector;
    
    //--- Enumeration for Calendar Event Frequency
    enum Event_Frequency
      {
       Event_Frequency_None,//NONE
       Event_Frequency_Week,//WEEK
       Event_Frequency_Month,//MONTH
       Event_Frequency_Quarter,//QUARTER
       Event_Frequency_Year,//YEAR
       Event_Frequency_Day,//DAY
       Event_Frequency_ALL//ALL
      } myFrequency;
    
    //--- Enumeration for Calendar Event type
    enum Event_Type
      {
       Event_Type_Event,//EVENT
       Event_Type_Indicator,//INDICATOR
       Event_Type_Holiday,//HOLIDAY
       Event_Type_All//ALL
      } myType;
    
    //--- Enumeration for Calendar Event Currency
    enum Event_Currency
      {
       Event_Currency_Symbol,//SYMBOL CURRENCIES
       Event_Currency_Margin,//SYMBOL MARGIN
       Event_Currency_Base,//SYMBOL BASE
       Event_Currency_Profit,//SYMBOL PROFIT
       Event_Currency_ALL,//ALL CURRENCIES
       Event_Currency_NZD_NZ,//NZD -> NZ
       Event_Currency_EUR_EU,//EUR -> EU
       Event_Currency_JPY_JP,//JPY -> JP
       Event_Currency_CAD_CA,//CAD -> CA
       Event_Currency_AUD_AU,//AUD -> AU
       Event_Currency_CNY_CN,//CNY -> CN
       Event_Currency_EUR_IT,//EUR -> IT
       Event_Currency_SGD_SG,//SGD -> SG
       Event_Currency_EUR_DE,//EUR -> DE
       Event_Currency_EUR_FR,//EUR -> FR
       Event_Currency_BRL_BR,//BRL -> BR
       Event_Currency_MXN_MX,//MXN -> MX
       Event_Currency_ZAR_ZA,//ZAR -> ZA
       Event_Currency_HKD_HK,//HKD -> HK
       Event_Currency_INR_IN,//INR -> IN
       Event_Currency_NOK_NO,//NOK -> NO
       Event_Currency_USD_US,//USD -> US
       Event_Currency_GBP_GB,//GBP -> GB
       Event_Currency_CHF_CH,//CHF -> CH
       Event_Currency_KRW_KR,//KRW -> KW
       Event_Currency_EUR_ES,//EUR -> ES
       Event_Currency_SEK_SE,//SEK -> SE
       Event_Currency_ALL_WW//ALL -> WW
      } myCurrency;
    
    //--- Structure variable to store Calendar next Event data
    Calendar UpcomingNews;

    ニュースクラスへの追加機能

    • 列挙体CalendarComponentsの拡張: カレンダーストレージデータベースのイベント詳細を表示するためにEventInfo_Viewが追加され、MQL5経済指標カレンダーで利用可能なすべての通貨を表示するためにCurrencies_Viewが追加されました。
    • 構造体配列CalendarContentsは、2つの新しいビューEventInfo_ViewとCurrencies_Viewに対応するため、サイズが10から12に増加しました。
    • DBのプロパティを格納するMQL5CalendarContents構造体型のDBMemory変数の宣言。
    • カレンダーDBの全データを共通フォルダに格納するためのCalendarData構造体と変数の宣言。
    • GetCalendar関数の宣言。この関数は、共通フォルダ内のカレンダーDBからフィルタリングされたすべてのデータをリクエストし、このデータをCalendarData構造配列データに格納します。この配列データは、作成されると、メモリ内の新しいカレンダーDBに挿入されます。
    • commonフォルダのCalendar DBのAutoDSTテーブルから列挙体DST_typeを取得するGetAutoDST関数の宣言。
    • Calendar_Importance列挙体に基づいて、イベントの重要度の文字列リクエストを取得する関数Request_Importanceの宣言。
    • Event_Frequency列挙体に基づくイベント頻度の文字列リクエストを取得する関数Request_Frequencyの宣言。
    • Event_Sector列挙体に基づいてイベントセクターの文字列リクエストを取得する関数Request_Sectorの宣言。
    • Event_Type列挙体に基づいて、イベントタイプの文字列リクエストを取得する関数Request_Typeの宣言。
    • Event_Currency列挙体に基づいてイベント通貨の文字列リクエストを取得する関数Request_Currencyの宣言。
    • NewsTime Calendar構造体の配列に特定の日付のイベントを入力する関数EconomicDetailsMemoryの宣言。
    • メモリ内にカレンダーデータベースを作成する関数CreateEconomicDatabaseMemoryの宣言。
    • UpcomingNews構造体変数を次のイベントデータで更新する関数EconomicNextEventの宣言。
    • 次のイベント影響データを取得する関数GetImpactの宣言。
    • 重要度文字列をカレンダーイベント重要度の列挙体(ENUM_CALENDAR_EVENT_IMPORTANCE)に変換する関数IMPORTANCEの宣言。
    • Calendar_Importance列挙体をカレンダーイベント重要度の列挙体に変換する関数IMPORTANCEの宣言。
    • カレンダーイベント重要度の列挙体を重要度評価文字列に変換する関数GetImportanceの宣言。
    • 各カレンダーイベント重要度の列挙体の色を取得する関数GetImportance_colorの宣言。
    • Event_Sector列挙体をカレンダーイベントセクター列挙体に変換する関数SECTOR のの宣言。
    • Event_Frequency列挙体をカレンダーイベント頻度列挙体に変換する関数FREQUENCYの宣言。
    • Event_Type列挙体をカレンダーイベントタイプ列挙体に変換する関数TYPEの宣言。

    //+------------------------------------------------------------------+
    //|News class                                                        |
    //+------------------------------------------------------------------+
    class CNews : private CCandleProperties
      {
       //Private Declarations Only accessable by this class/header file
    private:
    
       //-- To keep track of what is in our database
       enum CalendarComponents
         {
          AutoDST_Table,//AutoDST Table
          CalendarAU_View,//View for DST_AU
          CalendarNONE_View,//View for DST_NONE
          CalendarUK_View,//View for DST_UK
          CalendarUS_View,//View for DST_US
          EventInfo_View,//View for Event Information
          Currencies_View,//View for Currencies
          Record_Table,// Record Table
          TimeSchedule_Table,//TimeSchedule Table
          MQL5Calendar_Table,//MQL5Calendar Table
          AutoDST_Trigger,//Table Trigger for AutoDST
          Record_Trigger//Table Trigger for Record
         };
    
       //-- structure to retrieve all the objects in the database
       struct SQLiteMaster
         {
          string         type;//will store object's type
          string         name;//will store object's name
          string         tbl_name;//will store table name
          int            rootpage;//will store rootpage
          string         sql;//Will store the sql create statement
         } DBContents[];//Array of type SQLiteMaster
    
       //--  MQL5CalendarContents inherits from SQLiteMaster structure
       struct MQL5CalendarContents:SQLiteMaster
         {
          CalendarComponents  Content;
          string         insert;//Will store the sql insert statement
         } CalendarContents[12],DBMemory;//Array to Store objects in our database
    
       CTimeManagement   CTime;//TimeManagement Object declaration
       CDaylightSavings_UK  Savings_UK;//DaylightSavings Object for the UK and EU
       CDaylightSavings_US  Savings_US;//DaylightSavings Object for the US
       CDaylightSavings_AU  Savings_AU;//DaylightSavings Object for the AU
    
       bool              AutoDetectDST(DST_type &dstType);//Function will determine Broker DST
       DST_type          DSTType;//variable of DST_type enumeration declared in the CommonVariables class/header file
       bool              InsertIntoTables(int db,Calendar &Evalues[]);//Function for inserting Economic Data in to a database's table
       void              CreateAutoDST(int db);//Function for creating and inserting Recommend DST for the Broker into a table
       bool              CreateCalendarTable(int db,bool &tableExists);//Function for creating a table in a database
       bool              CreateTimeTable(int db,bool &tableExists);//Function for creating a table in a database
       void              CreateCalendarViews(int db);//Function for creating views in a database
       void              CreateRecordTable(int db);//Creates a table to store the record of when last the Calendar database was updated/created
       string            DropRequest;//Variable for dropping tables in the database
    
       //-- Function for retrieving the MQL5CalendarContents structure for the enumartion type CalendarComponents
       MQL5CalendarContents CalendarStruct(CalendarComponents Content)
         {
          MQL5CalendarContents Calendar;
          for(uint i=0;i<CalendarContents.Size();i++)
            {
             if(CalendarContents[i].Content==Content)
               {
                return CalendarContents[i];
               }
            }
          return Calendar;
         }
    
       //--- To Store Calendar DB Data
       struct CalendarData
         {
          int            EventId;//Event Id
          string         Country;//Event Country
          string         EventName;//Event Name
          string         EventType;//Event Type
          string         EventImportance;//Event Importance
          string         EventCurrency;//Event Currency
          string         EventCode;//Event Code
          string         EventSector;//Event Sector
          string         EventForecast;//Event Forecast Value
          string         EventPreval;//Event Previous Value
          string         EventImpact;//Event Impact
          string         EventFrequency;//Event Frequency
          string         DST_UK;//DST UK
          string         DST_US;//DST US
          string         DST_AU;//DST AU
          string         DST_NONE;//DST NONE
         } DB_Data[],DB_Cal;//Structure variables
    
       //--- Will Retrieve all relevant Calendar data for DB in Memory from DB in Storage
       void              GetCalendar(CalendarData &Data[])
         {
          //--- Open calendar DB in Storage
          int db=DatabaseOpen(NEWS_DATABASE_FILE, DATABASE_OPEN_READWRITE | DATABASE_OPEN_CREATE| DATABASE_OPEN_COMMON);
          if(db==INVALID_HANDLE)//Checks if the database was able to be opened
            {
             //if opening the database failed
             if(!FileIsExist(NEWS_DATABASE_FILE,FILE_COMMON))//Checks if the database Calendar exists in the common folder
               {
                return;//Returns true when the database was failed to be opened and the file doesn't exist in the common folder
               }
            }
          //--- Get filtered calendar DB data
          string SqlRequest = StringFormat("Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,"
                                           "MQ.EventCode,MQ.EventSector,MQ.EventForecast,MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,"
                                           "TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from %s MQ "
                                           "Inner Join %s TS on TS.ID=MQ.ID "
                                           "Where %s and %s and %s and %s and %s;",
                                           CalendarStruct(MQL5Calendar_Table).name,CalendarStruct(TimeSchedule_Table).name,
                                           Request_Importance(myImportance),Request_Frequency(myFrequency),
                                           Request_Sector(mySector),Request_Type(myType),Request_Currency(myCurrency));
          //--- Process Sql request
          int Request = DatabasePrepare(db,SqlRequest);
          if(Request==INVALID_HANDLE)
            {
             //--- Print details if request failed.
             Print("DB: ",NEWS_DATABASE_FILE, " request failed with code ", GetLastError());
             Print("SQL");
             Print(SqlRequest);
            }
          else
            {
             //--- Clear data from whole array
             ArrayRemove(Data,0,WHOLE_ARRAY);
             //--- create structure variable to get data from request
             CalendarData data;
             //Assigning values from the sql query into Data structure array
             for(int i=0; DatabaseReadBind(Request,data); i++)
               {
                //--- Resize Data Array
                ArrayResize(Data,i+1,i+2);
                Data[i]  = data;
               }
            }
          DatabaseFinalize(Request);//Finalize request
          //--- Close Calendar database
          DatabaseClose(db);
         }
    
       //--- Retrieve the AutoDST enumeration data from calendar DB in storage
       DST_type          GetAutoDST()
         {
          string Sch_Dst;
          //--- open the database 'Calendar' in the common folder
          int db=DatabaseOpen(NEWS_DATABASE_FILE, DATABASE_OPEN_READONLY|DATABASE_OPEN_COMMON);
    
          if(db==INVALID_HANDLE)//Checks if 'Calendar' failed to be opened
            {
             if(!FileIsExist(NEWS_DATABASE_FILE,FILE_COMMON))//Checks if 'Calendar' database exists
               {
                Print("Could not find Database!");
                return DST_NONE;//return default value when failed.
               }
            }
    
          //--- Sql query to get AutoDST value
          string request_text="SELECT DST FROM 'AutoDST'";
          //--- Process sql request
          int request=DatabasePrepare(db,request_text);
          if(request==INVALID_HANDLE)
            {
             Print("DB: ",NEWS_DATABASE_FILE, " request failed with code ", GetLastError());
             DatabaseClose(db);//Close Database
             return DST_NONE;//return default value when failed.
            }
    
          //--- Read Sql request output data
          if(DatabaseRead(request))
            {
             //-- Store the first column data into string variable Sch_Dst
             if(!DatabaseColumnText(request,0,Sch_Dst))
               {
                Print("DatabaseRead() failed with code ", GetLastError());
                DatabaseFinalize(request);//Finalize request
                DatabaseClose(db);//Closes the database 'Calendar'
                return DST_NONE;//return default value when failed.
               }
            }
          DatabaseFinalize(request);//Finalize request
          DatabaseClose(db);//Closes the database 'Calendar'
          return (Sch_Dst=="DST_UK")?DST_UK:(Sch_Dst=="DST_US")?DST_US:
                 (Sch_Dst=="DST_AU")?DST_AU:DST_NONE;//Returns the enumeration value for each corresponding string
         }
    
       //--- Retrieve Sql request string for calendar event Importance
       string            Request_Importance(Calendar_Importance Importance)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventImportance";
          //--- switch statement for Calendar_Importance enumeration
          switch(Importance)
            {
             case Calendar_Importance_All://String Request for all event Importance
                return constant+"<>'"+EnumToString(myImportance)+"'";
                break;
             default://String Request for any event Importance
                return constant+"='"+EnumToString(IMPORTANCE(myImportance))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event Frequency
       string            Request_Frequency(Event_Frequency Frequency)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventFrequency";
          //--- switch statement for Event_Frequency enumeration
          switch(Frequency)
            {
             case Event_Frequency_ALL://String Request for all event frequencies
                return constant+"<>'"+EnumToString(myFrequency)+"'";
                break;
             default://String Request for any event frequency
                return constant+"='"+EnumToString(FREQUENCY(myFrequency))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event Sector
       string            Request_Sector(Event_Sector Sector)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventSector";
          //--- switch statement for Event_Sector enumeration
          switch(Sector)
            {
             case Event_Sector_ALL://String Request for all event sectors
                return constant+"<>'"+EnumToString(mySector)+"'";
                break;
             default://String Request for any event sector
                return constant+"='"+EnumToString(SECTOR(mySector))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event type
       string            Request_Type(Event_Type Type)
         {
          //--- Constant request prefix string
          const string constant="MQ.EventType";
          //--- switch statement for Event_Type enumeration
          switch(Type)
            {
             case Event_Type_All://String Request for all event types
                return constant+"<>'"+EnumToString(myType)+"'";
                break;
             default://String request for any event type
                return constant+"='"+EnumToString(TYPE(myType))+"'";
                break;
            }
         }
    
       //--- Retrieve Sql request string for calendar event Currency
       string            Request_Currency(Event_Currency Currency)
         {
          //--- Constant request prefix string and request suffix
          const string constant_prefix="(MQ.EventCurrency",constant_suffix="')";
          //--- switch statement for Event_Currency enumeration
          switch(Currency)
            {
             case Event_Currency_ALL://String Request for all currencies
                return constant_prefix+"<>'"+EnumToString(myCurrency)+constant_suffix;
                break;
             case Event_Currency_Symbol://String Request for all symbol currencies
                return constant_prefix+"='"+CSymbol.CurrencyBase()+"' or MQ.EventCurrency='"+
                       CSymbol.CurrencyMargin()+"' or MQ.EventCurrency='"+CSymbol.CurrencyProfit()+constant_suffix;
                break;
             case Event_Currency_Margin://String Request for Margin currency
                return constant_prefix+"='"+CSymbol.CurrencyMargin()+constant_suffix;
                break;
             case Event_Currency_Base://String Request for Base currency
                return constant_prefix+"='"+CSymbol.CurrencyBase()+constant_suffix;
                break;
             case Event_Currency_Profit://String Request for Profit currency
                return constant_prefix+"='"+CSymbol.CurrencyProfit()+constant_suffix;
                break;
             case Event_Currency_NZD_NZ://String Request for NZD currency
                return constant_prefix+"='NZD' and MQ.EventCode='NZ"+constant_suffix;
                break;
             case Event_Currency_EUR_EU://String Request for EUR currency and EU code
                return constant_prefix+"='EUR' and MQ.EventCode='EU"+constant_suffix;
                break;
             case Event_Currency_JPY_JP://String Request for JPY currency
                return constant_prefix+"='JPY' and MQ.EventCode='JP"+constant_suffix;
                break;
             case Event_Currency_CAD_CA://String Request for CAD currency
                return constant_prefix+"='CAD' and MQ.EventCode='CA"+constant_suffix;
                break;
             case Event_Currency_AUD_AU://String Request for AUD currency
                return constant_prefix+"='AUD' and MQ.EventCode='AU"+constant_suffix;
                break;
             case Event_Currency_CNY_CN://String Request for CNY currency
                return constant_prefix+"='CNY' and MQ.EventCode='CN"+constant_suffix;
                break;
             case Event_Currency_EUR_IT://String Request for EUR currency and IT code
                return constant_prefix+"='EUR' and MQ.EventCode='IT"+constant_suffix;
                break;
             case Event_Currency_SGD_SG://String Request for SGD currency
                return constant_prefix+"='SGD' and MQ.EventCode='SG"+constant_suffix;
                break;
             case Event_Currency_EUR_DE://String Request for EUR currency and DE code
                return constant_prefix+"='EUR' and MQ.EventCode='DE"+constant_suffix;
                break;
             case Event_Currency_EUR_FR://String Request for EUR currency and FR code
                return constant_prefix+"='EUR' and MQ.EventCode='FR"+constant_suffix;
                break;
             case Event_Currency_BRL_BR://String Request for BRL currency
                return constant_prefix+"='BRL' and MQ.EventCode='BR"+constant_suffix;
                break;
             case Event_Currency_MXN_MX://String Request for MXN currency
                return constant_prefix+"='MXN' and MQ.EventCode='MX"+constant_suffix;
                break;
             case Event_Currency_ZAR_ZA://String Request for ZAR currency
                return constant_prefix+"='ZAR' and MQ.EventCode='ZA"+constant_suffix;
                break;
             case Event_Currency_HKD_HK://String Request for HKD currency
                return constant_prefix+"='HKD' and MQ.EventCode='HK"+constant_suffix;
                break;
             case Event_Currency_INR_IN://String Request for INR currency
                return constant_prefix+"='INR' and MQ.EventCode='IN"+constant_suffix;
                break;
             case Event_Currency_NOK_NO://String Request for NOK currency
                return constant_prefix+"='NOK' and MQ.EventCode='NO"+constant_suffix;
                break;
             case Event_Currency_USD_US://String Request for USD currency
                return constant_prefix+"='USD' and MQ.EventCode='US"+constant_suffix;
                break;
             case Event_Currency_GBP_GB://String Request for GBP currency
                return constant_prefix+"='GBP' and MQ.EventCode='GB"+constant_suffix;
                break;
             case Event_Currency_CHF_CH://String Request for CHF currency
                return constant_prefix+"='CHF' and MQ.EventCode='CH"+constant_suffix;
                break;
             case Event_Currency_KRW_KR://String Request for KRW currency
                return constant_prefix+"='KRW' and MQ.EventCode='KR"+constant_suffix;
                break;
             case Event_Currency_EUR_ES://String Request for EUR currency and ES code
                return constant_prefix+"='EUR' and MQ.EventCode='ES"+constant_suffix;
                break;
             case Event_Currency_SEK_SE://String Request for SEK currency
                return constant_prefix+"='SEK' and MQ.EventCode='SE"+constant_suffix;
                break;
             case Event_Currency_ALL_WW://String Request for ALL currency
                return constant_prefix+"='ALL' and MQ.EventCode='WW"+constant_suffix;
                break;
             default://String Request for no currencies
                return constant_prefix+"='"+constant_suffix;
                break;
            }
         }
    
       //Public declarations accessable via a class's Object
    public:
                         CNews(void);//Constructor
                        ~CNews(void);//Destructor
       void              CreateEconomicDatabase();//Creates the Calendar database for a specific Broker
       datetime          GetLatestNewsDate();//Gets the latest/newest date in the Calendar database
       void              EconomicDetails(Calendar &NewsTime[],datetime date_from=0,datetime date_to=0);//Gets values from the MQL5 economic Calendar
       void              EconomicDetailsMemory(Calendar &NewsTime[],datetime date);//Gets values from the MQL5 DB Calendar in Memory
       void              CreateEconomicDatabaseMemory();//Create calendar database in memory
       void              EconomicNextEvent(datetime date=0);//Will update UpcomingNews structure variable with the next event data
       bool              UpdateRecords();//Checks if the main Calendar database needs an update or not
       ENUM_CALENDAR_EVENT_IMPACT GetImpact();//Will retrieve Upcoming Event Impact data
    
       //--- Convert Importance string into Calendar Event Importance Enumeration
       ENUM_CALENDAR_EVENT_IMPORTANCE IMPORTANCE(string Importance)
         {
          //--- Calendar Importance is High
          if(Importance==EnumToString(CALENDAR_IMPORTANCE_HIGH))
            {
             return CALENDAR_IMPORTANCE_HIGH;
            }
          else
             //--- Calendar Importance is Moderate
             if(Importance==EnumToString(CALENDAR_IMPORTANCE_MODERATE))
               {
                return CALENDAR_IMPORTANCE_MODERATE;
               }
             else
                //--- Calendar Importance is Low
                if(Importance==EnumToString(CALENDAR_IMPORTANCE_LOW))
                  {
                   return CALENDAR_IMPORTANCE_LOW;
                  }
                else
                   //--- Calendar Importance is None
                  {
                   return CALENDAR_IMPORTANCE_NONE;
                  }
         }
    
       //--- Convert Calendar_Importance Enumeration into Calendar Event Importance Enumeration
       ENUM_CALENDAR_EVENT_IMPORTANCE IMPORTANCE(Calendar_Importance Importance)
         {
          //--- switch statement for Calendar_Importance enumeration
          switch(Importance)
            {
             case Calendar_Importance_None://None
                return CALENDAR_IMPORTANCE_NONE;
                break;
             case Calendar_Importance_Low://Low
                return CALENDAR_IMPORTANCE_LOW;
                break;
             case Calendar_Importance_Moderate://Moderate
                return CALENDAR_IMPORTANCE_MODERATE;
                break;
             case Calendar_Importance_High://High
                return CALENDAR_IMPORTANCE_HIGH;
                break;
             default://None
                return CALENDAR_IMPORTANCE_NONE;
                break;
            }
         }
    
       //--- Convert Calendar Event Importance Enumeration into string Importance Rating
       string            GetImportance(ENUM_CALENDAR_EVENT_IMPORTANCE Importance)
         {
          //--- switch statement for ENUM_CALENDAR_EVENT_IMPORTANCE enumeration
          switch(Importance)
            {
             case  CALENDAR_IMPORTANCE_HIGH://High
                return "HIGH";
                break;
             case CALENDAR_IMPORTANCE_MODERATE://Moderate
                return "MODERATE";
                break;
             case CALENDAR_IMPORTANCE_LOW://Low
                return "LOW";
                break;
             default://None
                return "NONE";
                break;
            }
         }
    
       //--- Retrieve color for each Calendar Event Importance Enumeration
       color             GetImportance_color(ENUM_CALENDAR_EVENT_IMPORTANCE Importance)
         {
          //--- switch statement for ENUM_CALENDAR_EVENT_IMPORTANCE enumeration
          switch(Importance)
            {
             case CALENDAR_IMPORTANCE_HIGH://High
                return clrRed;
                break;
             case CALENDAR_IMPORTANCE_MODERATE://Moderate
                return clrOrange;
                break;
             case CALENDAR_IMPORTANCE_LOW://Low
                return (isLightMode)?clrBlue:clrLightBlue;
                break;
             default://None
                return (isLightMode)?clrBlack:clrWheat;
                break;
            }
         }
    
       //--- Convert Event_Sector Enumeration into Calendar Event Sector Enumeration
       ENUM_CALENDAR_EVENT_SECTOR SECTOR(Event_Sector Sector)
         {
          //--- switch statement for Event_Sector enumeration
          switch(Sector)
            {
             case Event_Sector_None://NONE
                return CALENDAR_SECTOR_NONE;
                break;
             case Event_Sector_Market://MARKET
                return CALENDAR_SECTOR_MARKET;
                break;
             case Event_Sector_Gdp://GDP
                return CALENDAR_SECTOR_GDP;
                break;
             case Event_Sector_Jobs://JOBS
                return CALENDAR_SECTOR_JOBS;
                break;
             case Event_Sector_Prices://PRICES
                return CALENDAR_SECTOR_PRICES;
                break;
             case Event_Sector_Money://MONEY
                return CALENDAR_SECTOR_MONEY;
                break;
             case Event_Sector_Trade://TRADE
                return CALENDAR_SECTOR_TRADE;
                break;
             case Event_Sector_Government://GOVERNMENT
                return CALENDAR_SECTOR_GOVERNMENT;
                break;
             case Event_Sector_Business://BUSINESS
                return CALENDAR_SECTOR_BUSINESS;
                break;
             case Event_Sector_Consumer://CONSUMER
                return CALENDAR_SECTOR_CONSUMER;
                break;
             case Event_Sector_Housing://HOUSING
                return CALENDAR_SECTOR_HOUSING;
                break;
             case Event_Sector_Taxes://TAXES
                return CALENDAR_SECTOR_TAXES;
                break;
             case Event_Sector_Holidays://HOLIDAYS
                return CALENDAR_SECTOR_HOLIDAYS;
                break;
             default://Unknown
                return CALENDAR_SECTOR_NONE;
                break;
            }
         }
    
       //--- Convert Event_Frequency Enumeration into Calendar Event Frequency Enumeration
       ENUM_CALENDAR_EVENT_FREQUENCY FREQUENCY(Event_Frequency Frequency)
         {
          //--- switch statement for Event_Frequency enumeration
          switch(Frequency)
            {
             case  Event_Frequency_None://NONE
                return CALENDAR_FREQUENCY_NONE;
                break;
             case Event_Frequency_Day://DAY
                return CALENDAR_FREQUENCY_DAY;
                break;
             case Event_Frequency_Week://WEEK
                return CALENDAR_FREQUENCY_WEEK;
                break;
             case Event_Frequency_Month://MONTH
                return CALENDAR_FREQUENCY_MONTH;
                break;
             case Event_Frequency_Quarter://QUARTER
                return CALENDAR_FREQUENCY_QUARTER;
                break;
             case Event_Frequency_Year://YEAR
                return CALENDAR_FREQUENCY_YEAR;
                break;
             default://Unknown
                return CALENDAR_FREQUENCY_NONE;
                break;
            }
         }
    
       //--- Convert Event_Type Enumeration into Calendar Event Type Enumeration
       ENUM_CALENDAR_EVENT_TYPE TYPE(Event_Type Type)
         {
          //--- switch statement for Event_Type enumeration
          switch(Type)
            {
             case Event_Type_Event://EVENT
                return CALENDAR_TYPE_EVENT;
                break;
             case Event_Type_Indicator://INDICATOR
                return CALENDAR_TYPE_INDICATOR;
                break;
             case Event_Type_Holiday://HOLIDAY
                return CALENDAR_TYPE_HOLIDAY;
                break;
             default://Unknown
                return CALENDAR_TYPE_EVENT;
                break;
            }
         }
      };

    まずGetCalendar関数のSQL文を見てみましょう。この関数は、共通フォルダにあるカレンダーDBから、メモリ内のカレンダーDBにすべてのデータをリクエストします。このリクエストでは、MQL5CalendarテーブルとTimeScheduleテーブルのすべての列を選択し、IDが同じテーブルを結合します。次に、EAのニュース設定入力パラメータでトレーダーやユーザーが選択した列挙体に基づいてデータをフィルタリングします。

    //--- Get filtered calendar DB data
          string SqlRequest = StringFormat("Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,"
                                           "MQ.EventCode,MQ.EventSector,MQ.EventForecast,MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,"
                                           "TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from %s MQ "
                                           "Inner Join %s TS on TS.ID=MQ.ID "
                                           "Where %s and %s and %s and %s and %s;",
                                           CalendarStruct(MQL5Calendar_Table).name,CalendarStruct(TimeSchedule_Table).name,
                                           Request_Importance(myImportance),Request_Frequency(myFrequency),
                                           Request_Sector(mySector),Request_Type(myType),Request_Currency(myCurrency));

    EURUSD銘柄に対する以下のニュース設定構成のSQLリクエストを見てみましょう。

    NEWS SETTINGSの構成1

    以下に示すように、[CALENDAR IMPORTANCE]で[ALL]を選択した場合、意図的にCalendar_Importance列挙体変数myImportanceを変換しません。なぜなら、値がCalendar_Importance_Allであるイベントの重要度は存在しないからです。そのため、EventImportance がCalendar_Importance_Allと等しくないすべてのイベントを簡単に選択することができます。ALLに選択されているすべてのニュース設定の入力パラメータについても同じことが言えます。

    case Calendar_Importance_All://String Request for all event Importance
                return constant+"<>'"+EnumToString(myImportance)+"'";
    Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,MQ.EventCode,MQ.EventSector,
    MQ.EventForecast,MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from MQL5Calendar MQ
    Inner Join TimeSchedule TS on TS.ID=MQ.ID Where MQ.EventImportance<>'Calendar_Importance_All' and MQ.EventFrequency<>'Event_Frequency_ALL'
    and MQ.EventSector<>'Event_Sector_ALL' and MQ.EventType<>'Event_Type_All' and (MQ.EventCurrency='EUR' or MQ.EventCurrency='EUR' or 
    MQ.EventCurrency='USD');

    EURUSD銘柄に対する次のニュース設定構成におけるGetCalendar関数からの別のSQLリクエストを再度確認しましょう。

    ニュース設定構成2

    以下に示すように、[CALENDAR IMPORTANCE]で[ALL]以外のオプションを選択した場合、Calendar_Importance列挙体変数myImportanceを列挙体ENUM_CALENDAR_EVENT_IMPORTANCEに変換し、文字列をMQL5Calendarテーブルに格納されているものと一致させて、特定のタイプのイベントの重要性を正しく取得できるようにします。

    default://String Request for any event Importance
                return constant+"='"+EnumToString(IMPORTANCE(myImportance))+"'";

    Select MQ.EventId,MQ.Country,MQ.EventName,MQ.EventType,MQ.EventImportance,MQ.EventCurrency,MQ.EventCode,MQ.EventSector,MQ.EventForecast,
    MQ.EventPreValue,MQ.EventImpact,MQ.EventFrequency,TS.DST_UK,TS.DST_US,TS.DST_AU,TS.DST_NONE from MQL5Calendar MQ Inner Join TimeSchedule TS 
    on TS.ID=MQ.ID Where MQ.EventImportance='CALENDAR_IMPORTANCE_HIGH' and MQ.EventFrequency='CALENDAR_FREQUENCY_MONTH' and 
    MQ.EventSector='CALENDAR_SECTOR_JOBS' and MQ.EventType='CALENDAR_TYPE_INDICATOR' and (MQ.EventCurrency<>'Event_Currency_ALL');

     ニュースクラスのコンストラクタでは、共通フォルダのカレンダーDB用の新しいビューの配列インデックスを初期化する必要があります。イベント情報ビューでは、以下のように配列インデックスを初期化します。

    //--- initializing properties for the EventInfo view
       CalendarContents[5].Content = EventInfo_View;
       CalendarContents[5].name = "Event Info";
       CalendarContents[5].sql = "CREATE VIEW IF NOT EXISTS 'Event Info' "
                                 "AS SELECT EVENTID as 'ID',COUNTRY as 'Country',EVENTNAME as 'Name',"
                                 "REPLACE(EVENTTYPE,'CALENDAR_TYPE_','') as 'Type',REPLACE(EVENTSECTOR,'CALENDAR_SECTOR_','') as 'Sector',"
                                 "REPLACE(EVENTIMPORTANCE,'CALENDAR_IMPORTANCE_','') as 'Importance',EVENTCURRENCY as 'Currency' "
                                 "FROM MQL5Calendar GROUP BY \"Name\" ORDER BY \"Country\" Asc,"
                                 "CASE \"Importance\" WHEN 'HIGH' THEN 1 WHEN 'MODERATE' THEN 2 WHEN 'LOW' THEN 3 ELSE 4 END,\"Sector\" Desc;";
       CalendarContents[5].tbl_name = "Event Info";
       CalendarContents[5].type = "view";

    ビュー「Event Info」を作成するSQL文を見てみましょう。まず、ビューがまだ存在しない場合のみ作成し、その後、次の列を選択して名前変更します。EVENTIDを「ID」に、COUNTRYを「Country」に、EVENTNAMEを「Name」に、EVENTTYPEのテキスト「CALENDAR_TYPE_」を空の文字列に置き換えて列名をTypeに、EVENTSECTORのテキスト「CALENDAR_SECTOR_」 を空の文字列に置き換えて列名をSectorに、EVENTIMPORTANCEのテキスト「CALENDAR_IMPORTANCE_」を空の文字列に置き換えて列名をImportanceに、EVENTCURRENCYをCurrencyに。このすべては、MQL5Calendarテーブルからおこないます。次に、同じイベント名のイベントが複数回ビューに表示されないように、クエリをEVENTNAMEでグループ化します。次に、クエリに順序を付けます。まず、結果をCountry列で昇順に並べ替え、アルファベットの最初がAの国、例えばオーストラリアが最初に表示されるようにします。その後、EVENTIMPORTANCE(現在は「Importance」と呼ばれている)で結果を並べ替えます。重要度の高いイベントを表示したかったので、そのためには、重要度の文字列/テキスト値にランクを付ける必要があります。この場合、ImportanceがHIGHのときが最優先で、次にMODERATEが第2位、LOWが第3位、最後にその他の値が最下位となります。さらに、クエリ結果をEVENTSECTOR(現在は「Sector」と呼ばれている)で降順に並べます。以下にサンプルを掲載します。

    CREATE VIEW IF NOT EXISTS 'Event Info' AS SELECT MQ.EVENTID as 'ID',MQ.COUNTRY as 'Country',MQ.EVENTNAME as 'Name',REPLACE(MQ.EVENTTYPE,
    'CALENDAR_TYPE_','') as 'Type',REPLACE(MQ.EVENTSECTOR,'CALENDAR_SECTOR_','') as 'Sector',REPLACE(MQ.EVENTIMPORTANCE,'CALENDAR_IMPORTANCE_','') 
    as 'Importance',MQ.EVENTCURRENCY as 'Currency' FROM MQL5Calendar MQ INNER JOIN TimeSchedule TS on TS.ID=MQ.ID GROUP BY "Name" ORDER BY 
    "Country" Asc,CASE "Importance" WHEN 'HIGH' THEN 1 WHEN 'MODERATE' THEN 2 WHEN 'LOW' THEN 3 ELSE 4 END,"Sector" Desc;

    イベント情報ビュー

    ID       Country  Name                                          Type            Sector        Importance   Currency
    36030006 Australia  RBA Governor Lowe Speech                    EVENT           MONEY         HIGH         AUD 
    36030008 Australia  RBA Interest Rate Decision                  INDICATOR       MONEY         HIGH         AUD 
    36010029 Australia  PPI q/q                                     INDICATOR       PRICES        MODERATE     AUD 
    36030014 Australia  RBA Trimmed Mean CPI q/q                    INDICATOR       PRICES        MODERATE     AUD 
    36030009 Australia  RBA Weighted Median CPI q/q                 INDICATOR       PRICES        MODERATE     AUD 
    36010031 Australia  Wage Price Index q/q                        INDICATOR       PRICES        MODERATE     AUD 
    36030026 Australia  RBA Assistant Governor Boulton Speech       EVENT           MONEY         MODERATE     AUD 
    36030024 Australia  RBA Assistant Governor Bullock Speech       EVENT           MONEY         MODERATE     AUD 
    36030025 Australia  RBA Assistant Governor Ellis Speech         EVENT           MONEY         MODERATE     AUD 
    
    62 lines later...
    
    76020002 Brazil  BCB Interest Rate Decision                     INDICATOR       MONEY         HIGH         BRL 
    76020004 Brazil  BCB Inflation Report                           EVENT           PRICES        MODERATE     BRL 
    76050001 Brazil  FIPE CPI m/m                                   INDICATOR       PRICES        MODERATE     BRL 
    76010005 Brazil  Mid-Month CPI m/m                              INDICATOR       PRICES        MODERATE     BRL 
    76020001 Brazil  BCB Focus Market Report                        EVENT           MONEY         MODERATE     BRL 
    76020003 Brazil  BCB MPC (Copom) Minutes                        EVENT           MONEY         MODERATE     BRL 
    76020005 Brazil  BCB National Monetary Council Meeting          EVENT           MONEY         MODERATE     BRL 
    76010009 Brazil  Unemployment Rate 3-months                     INDICATOR       JOBS          MODERATE     BRL 
    76020010 Brazil  Nominal Budget Balance                         INDICATOR       GOVERNMENT    MODERATE     BRL 
    76020011 Brazil  Primary Budget balance                         INDICATOR       GOVERNMENT    MODERATE     BRL 
    76010014 Brazil  Services Volume m/m                            INDICATOR       BUSINESS      MODERATE     BRL 
    
    98 lines later...
    
    124040017 Canada  BoC Governor Macklem Speech                   EVENT           MONEY          HIGH         CAD 
    124040003 Canada  BoC Governor Poloz Speech                     EVENT           MONEY          HIGH         CAD 
    124040006 Canada  BoC Interest Rate Decision                    INDICATOR       MONEY          HIGH         CAD 
    124040009 Canada  BoC Monetary Policy Report Press Conference   EVENT           MONEY          HIGH         CAD 
    124010011 Canada  Employment Change                             INDICATOR       JOBS           HIGH         CAD 
    124010021 Canada  GDP m/m                                       INDICATOR       GDP            HIGH         CAD 
    124010008 Canada  Core Retail Sales m/m                         INDICATOR       CONSUMER       HIGH         CAD 
    124020001 Canada  Ivey PMI                                      INDICATOR       BUSINESS       HIGH         CAD 
    124010024 Canada  IPPI m/m                                      INDICATOR       PRICES         MODERATE     CAD 
    124010026 Canada  RMPI m/m                                      INDICATOR       PRICES         MODERATE     CAD 
    124040001 Canada  BoC Business Outlook Survey                   EVENT           MONEY          MODERATE     CAD 
    

    通貨ビューでは、テーブルMQL5Calendarから一意のEventCurrencyとEventCodeを選択します。

    //--- initializing properties for the Currencies view
       CalendarContents[6].Content = Currencies_View;
       CalendarContents[6].name = "Currencies";
       CalendarContents[6].sql = "CREATE VIEW IF NOT EXISTS Currencies AS "
                                 "SELECT Distinct EventCurrency as 'Currency',EventCode as 'Code' FROM 'MQL5Calendar';";
       CalendarContents[6].tbl_name = "Currencies";
       CalendarContents[6].type = "view";
    SELECT * FROM 'Currencies';
    Currency  	Code
    NZD  		NZ
    EUR 		EU
    JPY  		JP
    CAD  		CA
    AUD  		AU
    CNY  		CN
    EUR  		IT
    SGD  		SG
    EUR  		DE
    EUR  		FR
    BRL  		BR
    MXN  		MX
    ZAR  		ZA
    HKD  		HK
    INR  		IN
    NOK  		NO
    USD  		US
    GBP  		GB
    CHF  		CH
    KRW  		KR
    EUR  		ES
    SEK  		SE
    ALL  		WW

    ここで、メモリ内のDBにあるテーブルMQL5Calendarのプロパティを初期化します。このテーブルは、基本的にストレージ内のDBのテーブルを組み合わせた1つの大きなテーブルになります。具体的には、MQL5CalendarテーブルとTimeScheduleテーブルが含まれます。

    //-- initializing properties for the MQL5Calendar table for DB in System Memory
       DBMemory.Content = MQL5Calendar_Table;
       DBMemory.name = "MQL5Calendar";
       DBMemory.sql = "CREATE TABLE IF NOT EXISTS MQL5Calendar(EVENTID  INT   NOT NULL,COUNTRY  TEXT   NOT NULL,"
                      "EVENTNAME   TEXT   NOT NULL,EVENTTYPE   TEXT   NOT NULL,EVENTIMPORTANCE   TEXT   NOT NULL,"
                      "EVENTCURRENCY  TEXT   NOT NULL,EVENTCODE   TEXT   NOT NULL,EVENTSECTOR TEXT   NOT NULL,"
                      "EVENTFORECAST  TEXT   NOT NULL,EVENTPREVALUE  TEXT   NOT NULL,EVENTIMPACT TEXT   NOT NULL,"
                      "EVENTFREQUENCY TEXT   NOT NULL,DST_UK   TEXT   NOT NULL,DST_US   TEXT   NOT NULL,"
                      "DST_AU   TEXT   NOT NULL,DST_NONE   TEXT   NOT NULL)STRICT;";
       DBMemory.tbl_name="MQL5Calendar";
       DBMemory.type = "table";
       DBMemory.insert = "INSERT INTO 'MQL5Calendar'(EVENTID,COUNTRY,EVENTNAME,EVENTTYPE,EVENTIMPORTANCE,EVENTCURRENCY,EVENTCODE,"
                         "EVENTSECTOR,EVENTFORECAST,EVENTPREVALUE,EVENTIMPACT,EVENTFREQUENCY,DST_UK,DST_US,DST_AU,DST_NONE) "
                         "VALUES (%d,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s', '%s', '%s');";

    デストラクタでは、メモリ内のデータベースへの接続を閉じます。メモリ内のデータベースへの接続を閉じると、データベース全体が削除されます。そのため、データベースが不要になったときだけ接続を閉じます。

    //+------------------------------------------------------------------+
    //|Destructor                                                        |
    //+------------------------------------------------------------------+
    CNews::~CNews(void)
      {
       if(FileIsExist(NEWS_TEXT_FILE,FILE_COMMON))//Check if the news database open text file exists
         {
          FileDelete(NEWS_TEXT_FILE,FILE_COMMON);
         }
       DatabaseClose(DBMemoryConnection);//Close DB in memory
      }

    前回、関数UpdateRecordsでは、ストレージ内のカレンダーデータベースを更新すべきかどうかを確認するためにシーケンスを通過しました。一連の流れは次のようなものでした。

    1. カレンダーデータベースが共通フォルダに存在するかどうかを確認し、データベースが存在しなければ更新を実行します。
    2. すべてのデータベースオブジェクトがデータベースに存在し、そのSQL文が期待通りのものであるかどうかを確認し、そうでなければ更新を実行します。
    3. レコードテーブルの日付が現在の日付と等しいかどうかを確認し、等しくなければ更新を実行します。

    この記事では、このシーケンスにもう1つの手順を追加します。この追加手順の目的は、Calendar_NONEビューのニュースデータが正確かどうかを確認することです。私はMQL5カレンダーのニュースデータが時間の経過とともに変化することがあることに気づきました。変化していないニュースを保存している場合、保存しているものとMQL5カレンダーから更新されたものとの間に矛盾がないか確認できるようにする必要があります。

    以下のコードでは、関数EconomicDetailsを使用して現在の日のニュースデータを取得し、このデータを配列TodayNewsに格納しています。ニュースデータがTodayNewsの配列に入ったら、配列内の各ニュースイベントを繰り返し処理し、ビューのCalendar_NONEに一致するものがあるかどうかを確認します。すべてのニュースデータがCalendar_NONEビューで一致する場合、ストレージ内のデータベースへの更新は実行しません。

          Calendar TodaysNews[];
          datetime Today = CTime.Time(TimeTradeServer(),0,0,0);
          EconomicDetails(TodaysNews,Today,Today+CTime.DaysS());
    
          for(uint i=0;i<TodaysNews.Size();i++)
            {
             request_text=StringFormat("SELECT ID FROM %s where Replace(Date,'.','-')=Replace('%s','.','-') and ID=%d;",
                                       CalendarStruct(CalendarNONE_View).name,TodaysNews[i].EventDate,TodaysNews[i].EventId);
             request=DatabasePrepare(db,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
             if(request==INVALID_HANDLE)//Checks if the request failed to be completed
               {
                Print("DB: ",NEWS_DATABASE_FILE, " request failed with code ", GetLastError());
                DatabaseFinalize(request);
                DatabaseClose(db);
                return perform_update;
               }
             //PrintFormat(request_text);
             if(!DatabaseRead(request))//Will be true if there are results from the sql query/request
               {
                DatabaseFinalize(request);
                DatabaseClose(db);
                return perform_update;
               }
             DatabaseFinalize(request);
            }
          DatabaseClose(db);//Closes the database
          perform_update=false;
          return perform_update;

    以下のコードは、メモリ内にデータベースを作成する役割を担います。まず、データベースへの接続を開き、テーブルMQL5Calendarがすでに存在する場合はそれを削除し、テーブルMQL5Calendarを作成します。テーブルを作成したら、関数GetCalendarからすべての関連データを取得し、関数から取得したすべてのデータをメモリ内のデータベースのMQL5Calendarテーブルに挿入します。さらに、配列DB_Data全体をクリアし、DSTスケジュールを変数MyScheduleに設定します。ストラテジーテスター以外の取引では、ユーザーやトレーダーは夏時間スケジュールを手動で変更することはできません。これは、夏時間スケジュールの設定がストラテジーテスターでのみ必要であるため、間違った夏時間スケジュールを設定することを防ぐためです。

    //+------------------------------------------------------------------+
    //|Create calendar database in memory                                |
    //+------------------------------------------------------------------+
    void CNews::CreateEconomicDatabaseMemory()
      {
    //--- Open/create the database in memory
       DBMemoryConnection=DatabaseOpen(NEWS_DATABASE_MEMORY,DATABASE_OPEN_MEMORY);
       if(DBMemoryConnection==INVALID_HANDLE)//Checks if the database failed to open/create
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " open failed with code ", GetLastError());
          return;//will terminate execution of the rest of the code below
         }
    //--- Drop the table if it already exists
       DatabaseExecute(DBMemoryConnection,StringFormat("Drop table IF EXISTS %s",DBMemory.name));
    //--- Attempt to create the table
       if(!DatabaseExecute(DBMemoryConnection,DBMemory.sql))
         {
          Print("DB: create the Calendar table failed with code ", GetLastError());
          return;
         }
    //--- Check if the table exists
       if(DatabaseTableExists(DBMemoryConnection,DBMemory.tbl_name))
         {
          //--- Get all news data and time from the database in storage
          GetCalendar(DB_Data);
          //--- Insert all the news data and times into the table
          for(uint i=0;i<DB_Data.Size();i++)
            {
             string request_text=StringFormat(DBMemory.insert,DB_Data[i].EventId,DB_Data[i].Country,
                                              DB_Data[i].EventName,DB_Data[i].EventType,DB_Data[i].EventImportance,
                                              DB_Data[i].EventCurrency,DB_Data[i].EventCode,DB_Data[i].EventSector,
                                              DB_Data[i].EventForecast,DB_Data[i].EventPreval,DB_Data[i].EventImpact,
                                              DB_Data[i].EventFrequency,DB_Data[i].DST_UK,DB_Data[i].DST_US,
                                              DB_Data[i].DST_AU,DB_Data[i].DST_NONE);
    
             if(!DatabaseExecute(DBMemoryConnection, request_text))//Will attempt to run this sql request/query
               {
                //--- failed to run sql request/query
                Print(GetLastError());
                PrintFormat(request_text);
                return;
               }
            }
         }
    //--- Remove all data from the array
       ArrayRemove(DB_Data,0,WHOLE_ARRAY);
    //--- Assign the DST schedule
       MySchedule = (MQLInfoInteger(MQL_TESTER))?(MyDST==AutoDst_Selection)?GetAutoDST():MySchedule:DST_NONE;
      }

    さて、EconomicDetailsMemoryと呼ばれる以下の関数は、ある日付に発生したすべてのニュースイベントを取得し、参照渡しされる構造体配列のパラメータNewsTimeにニュースデータを格納します。 

    //+------------------------------------------------------------------+
    //|Gets values from the MQL5 DB Calendar in Memory                   |
    //+------------------------------------------------------------------+
    void CNews::EconomicDetailsMemory(Calendar &NewsTime[],datetime date)
      {
    //--- SQL query to retrieve news data for a certain date
       string request_text=StringFormat("WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',EventType as 'Type'"
                                        ",EventImportance as 'Importance',%s as 'CTime',EventCurrency as 'Currency',EventCode as 'Code',"
                                        "EventSector as 'Sector',EventForecast as 'Forecast',EventPrevalue as 'Prevalue',EventImpact as'Impact',"
                                        "EventFrequency as 'Freq',RANK() OVER (PARTITION BY %s Order BY CASE EventPrevalue WHEN 'None' "
                                        "THEN 2 ELSE 1 END,CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,CASE EventImportance WHEN "
                                        "'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 WHEN 'CALENDAR_IMPORTANCE_LOW'"
                                        " THEN 3 ELSE 4 END) Ranking FROM %s) SELECT Id,Country,Name,Type,Importance,CTime,Currency,Code,Sector,"
                                        "Forecast,Prevalue,Impact,Freq FROM MySubQuery where Date(Replace(CTime,'.','-'))=Date(Replace('%s','.','-')) and "
                                        "Ranking<2 Group by CTime;",EnumToString(MySchedule),EnumToString(MySchedule),DBMemory.name,
                                        TimeToString(date));
       int request=DatabasePrepare(DBMemoryConnection,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
       if(request==INVALID_HANDLE)//Checks if the request failed to be completed
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " request failed with code ", GetLastError());
          PrintFormat(request_text);
         }
    //--- Calendar structure variable
       Calendar ReadDB_Data;
    //--- Remove any data in the array
       ArrayRemove(NewsTime,0,WHOLE_ARRAY);
       for(int i=0; DatabaseReadBind(request,ReadDB_Data); i++)//Will read all the results from the sql query/request
         {
          //--- Resize array NewsTime
          ArrayResize(NewsTime,i+1,i+2);
          //--- Assign calendar structure values into NewsTime array index
          NewsTime[i]  = ReadDB_Data;
         }
    //--- Removes a request created in DatabasePrepare()
       DatabaseFinalize(request);
      }

    SQLクエリを分解してみましょう。過去のどのクエリよりも複雑です。このクエリでは、句と RANK()関数を使用します。

    WITH句とその仕組みについて

    WITH句は共通テーブル式(CTE:Common Table Expression)とも呼ばれ、SELECT、INSERT、UPDATE、またはDELETE文の中で参照できる一時的な結果セットを定義するために使用されます。WITH句は、複雑なクエリをより単純な部分に分割することで、クエリの理解と保守を容易にします。また、高価なサブクエリの結果を再利用することで、パフォーマンスを向上させることもできます。 CTEは一時的なもので、クエリの間だけ存在します。データベースに永続的なオブジェクトは作成されません。

    RANK()関数とその仕組みについて

    RANK() 関数は、1つ以上の列の値に基づいて結果セット内の各行に一意な順位を割り当てるために使用されます。行は指定された基準に従って並べられ、その結果に応じて順位が付けられます。RANK()関数はSQLのウィンドウ関数の一部であり、行のウィンドウ(またはサブセット)を操作し、入力セットの各行に対して順位を返すことができます。 RANK()関数は、ウィンドウ関数の定義内のORDER BY句で指定された順序に基づいて各行に順位を割り当てます。複数の行が順序付けのために指定された列に同じ値を持つ場合、それらの行には同じ順位が与えられ、次の順位は同じ順位の数だけスキップされます。 オプションのPARTITION BY句を使用することで、結果セットをパーティションに分割し、RANK()関数を各パーティションに独立して適用することができます。

    この下に強調表示されたWITH句では、EventId、Country、EventName、EventType、EventImportance、DST_NONE(ユーザーやトレーダーがEA入力で設定したDSTスケジュール)、EventCurrency、EventCode、EventSector、EventForecast、EventPrevalue、EventImpact、EventFrequencyをSELECTします。そして、ランキング関数を使用します。この関数の目的は、各SELECT結果にランキングを付与することです。このランキングは、ユニークなイベント時刻(DST_NONE)に対して常に1となります。もし同じイベント時刻を持つ複数のイベントがある場合、ランキングを適用します。イベントのEventPrevalueがNoneの場合はランキングが2となり、それ以外の場合はランキングが1になります。これは、ORDER BY句の残りの部分にも同様に適用されます。

    WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',EventType as 'Type',EventImportance as 'Importance',
    DST_NONE as 'CTime',EventCurrency as 'Currency',EventCode as 'Code',EventSector as 'Sector',EventForecast as 'Forecast',
    EventPrevalue as 'Prevalue',EventImpact as'Impact',EventFrequency as 'Freq',RANK() OVER (PARTITION BY DST_NONE 
    Order BY CASE EventPrevalue WHEN 'None' THEN 2 ELSE 1 END,CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,
    CASE EventImportance WHEN 'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 
    WHEN 'CALENDAR_IMPORTANCE_LOW' THEN 3 ELSE 4 END) Ranking FROM MQL5Calendar) SELECT Id,Country,Name,Type,
    Importance,CTime,Currency,Code,Sector,Forecast,Prevalue,Impact,Freq FROM MySubQuery where 
    Date(Replace(CTime,'.','-'))=Date(Replace('2024.07.30 00:00','.','-')) and Ranking<2 Group by CTime;

    以下は、CTE(MySubQuery)の結果の例です。順位が1を超えるために結果から除外されるイベントを強調表示しています。ランキングが2未満のイベントのみを考慮し、その後、時間で結果をグループ化します。チャートにイベントオブジェクトをプロットする際に、同じ時間を持つ複数のイベントオブジェクトを作成したくないためです。最も重要なイベントのみが表示されることを望んでいます。

    Id 		Country 	Name 					Type 			Importance 			CTime 		Currency Code Sector 			Forecast  Prevalue   Impact 		Freq 			  Ranking
    392030007 	Japan 		Unemployment Rate 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	2500000   2600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    392050002 	Japan 		Jobs to Applicants Ratio 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	1240000   1240000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    36010001 	Australia 	Building Approvals m/m 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 03:30 AUD 	 AU   CALENDAR_SECTOR_BUSINESS 	-900000   5500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    36010002 	Australia 	Private House Approvals m/m 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 03:30 AUD 	 AU   CALENDAR_SECTOR_BUSINESS 	None 	  2100000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    250010005 	France 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_GDP 	200000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    250010006 	France 		GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_GDP 	1000000	  1100000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    250010008 	France 		Consumer Spending m/m 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_CONSUMER 	800000 	  1500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    756050001 	Switzerland 	KOF Economic Barometer 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 CHF 	 CH   CALENDAR_SECTOR_BUSINESS 	101500000 102700000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    724010001 	Spain 		CPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_PRICES 	200000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    724010003 	Spain 		HICP m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_PRICES 	300000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    724010005 	Spain 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_GDP 	300000 	  800000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    724010002 	Spain 		CPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 EUR  	 ES   CALENDAR_SECTOR_PRICES 	3000000   3400000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    724010004 	Spain 		HICP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_PRICES 	3500000   3600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    724010006 	Spain 		GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 EUR 	 ES   CALENDAR_SECTOR_GDP 	1900000   2500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 5
    752020001 	Sweden 		Business Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_BUSINESS 	95500000  97300000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020002 	Sweden 		Manufacturing Confidence 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_BUSINESS 	99000000  99200000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020003 	Sweden 		Consumer Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_CONSUMER 	95300000  93300000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020004 	Sweden 		Inflation Expectations 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_CONSUMER 	6300000   6200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    752020005 	Sweden 		Economic Tendency Indicator 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 09:00 SEK 	 SE   CALENDAR_SECTOR_BUSINESS 	94800000  96300000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   5
    276010008 	Germany 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 10:00 EUR 	 DE   CALENDAR_SECTOR_GDP 	100000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    380010020 	Italy 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 10:00 EUR 	 IT   CALENDAR_SECTOR_GDP 	200000 	  300000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    276010009 	Germany 	GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 10:00 EUR 	 DE   CALENDAR_SECTOR_GDP 	-400000   -900000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    380010021 	Italy 		GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 10:00 EUR 	 IT   CALENDAR_SECTOR_GDP 	400000 	  700000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 4
    999030016 	European Union 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_GDP 	200000 	  300000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    999030017 	European Union 	GDP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_GDP 	400000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    999040003 	European Union 	Industrial Confidence Indicator 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	-9700000  -10100000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040004 	European Union 	Services Sentiment Indicator 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	8300000   6500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040005 	European Union 	Economic Sentiment Indicator 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	95300000  95900000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040006 	European Union 	Consumer Confidence Index 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_CONSUMER 	-13000000 -13000000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040007 	European Union 	Consumer Price Expectations 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR  	 EU   CALENDAR_SECTOR_CONSUMER 	14400000  13100000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    999040008 	European Union 	Industry Selling Price Expectations 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_BUSINESS 	6300000   6100000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   3
    380020007 	Italy 		10-Year BTP Auction 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 11:30 EUR 	 IT   CALENDAR_SECTOR_MARKET 	None 	  4010000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    1
    380020005 	Italy 		5-Year BTP Auction 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:30 EUR 	 IT   CALENDAR_SECTOR_MARKET 	None 	  3550000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    2
    826130002 	United Kingdom 	10-Year Treasury Gilt Auction 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 11:30 GBP 	 GB   CALENDAR_SECTOR_MARKET 	None 	  4371000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    2
    724080001 	Spain 		Business Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 12:00 EUR 	 ES   CALENDAR_SECTOR_BUSINESS 	-4100000  -5700000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    76030002 	Brazil 		FGV IGP-M Inflation Index m/m 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 13:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	1000000   810000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484020016 	Mexico 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 14:00 MXN 	 MX   CALENDAR_SECTOR_GDP 	0 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    276010020 	Germany 	CPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	0 	  100000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    276010022 	Germany 	HICP m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	-100000   200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    76010012 	Brazil 		PPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	700000 	  450000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    484020017 	Mexico 		GDP n.s.a. y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 14:00 MXN 	 MX   CALENDAR_SECTOR_GDP 	2000000   1600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 2
    276010021 	Germany 	CPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	2200000   2200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   6
    276010023 	Germany 	HICP y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 14:00 EUR 	 DE   CALENDAR_SECTOR_PRICES 	2500000   2500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   6
    76010013 	Brazil 		PPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 14:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	2200000   170000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   6
    840170001 	United States 	S&P/CS HPI Composite-20 y/y 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	6800000   7200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840110001 	United States 	HPI m/m 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	300000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840110002 	United States 	HPI y/y 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	5700000   6300000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840110003 	United States 	HPI 					CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	427700000 424300000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840170002 	United States 	S&P/CS HPI Composite-20 n.s.a. m/m 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	700000 	  1400000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840170003 	United States 	S&P/CS HPI Composite-20 s.a. m/m 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	200000 	  400000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   2
    840030021 	United States 	JOLTS Job Openings 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 16:00 USD 	 US   CALENDAR_SECTOR_JOBS 	7979000   8140000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840180002 	United States 	CB Consumer Confidence Index 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 16:00 USD 	 US   CALENDAR_SECTOR_CONSUMER 	108000000 100400000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840060003 	United States 	Dallas Fed Services Revenues 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 16:30 USD 	 US   CALENDAR_SECTOR_BUSINESS 	3900000   1900000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840060004 	United States 	Dallas Fed Services Business Activity 	CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 16:30 USD 	 US   CALENDAR_SECTOR_BUSINESS 	-6700000  -4100000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484010001 	Mexico Fiscal 	Balance 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 22:30 MXN 	 MX   CALENDAR_SECTOR_TRADE 	-900000   -174071000 CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    

    最終結果は以下の通りです。

    Id 		Country 	Name 					Type 			Importance 			CTime 		Currency Code Sector 			Forecast  Prevalue   Impact 		Freq 			  Ranking
    392030007 	Japan 		Unemployment Rate 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	2500000   2600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    36010001 	Australia 	Building Approvals m/m 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 03:30 AUD 	 AU   CALENDAR_SECTOR_BUSINESS 	-900000   5500000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    250010005 	France 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 07:30 EUR 	 FR   CALENDAR_SECTOR_GDP 	200000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    756050001 	Switzerland 	KOF Economic Barometer 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 09:00 CHF 	 CH   CALENDAR_SECTOR_BUSINESS 	101500000 102700000  CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    276010008 	Germany 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 10:00 EUR 	 DE   CALENDAR_SECTOR_GDP 	100000 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    999030016 	European Union 	GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 11:00 EUR 	 EU   CALENDAR_SECTOR_GDP 	200000 	  300000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    380020007 	Italy 		10-Year BTP Auction 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 11:30 EUR 	 IT   CALENDAR_SECTOR_MARKET 	None 	  4010000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_NONE    1
    724080001 	Spain 		Business Confidence 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 12:00 EUR 	 ES   CALENDAR_SECTOR_BUSINESS 	-4100000  -5700000   CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    76030002 	Brazil 		FGV IGP-M Inflation Index m/m 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 13:00 BRL 	 BR   CALENDAR_SECTOR_PRICES 	1000000   810000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484020016 	Mexico 		GDP q/q 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 14:00 MXN 	 MX   CALENDAR_SECTOR_GDP 	0 	  200000     CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_QUARTER 1
    840170001 	United States 	S&P/CS HPI Composite-20 y/y 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 15:00 USD 	 US   CALENDAR_SECTOR_HOUSING 	6800000   7200000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840030021 	United States 	JOLTS Job Openings 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_HIGH 	2024.07.30 16:00 USD 	 US   CALENDAR_SECTOR_JOBS 	7979000   8140000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    840060003 	United States 	Dallas Fed Services Revenues 		CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 16:30 USD 	 US   CALENDAR_SECTOR_BUSINESS 	3900000   1900000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    484010001 	Mexico Fiscal 	Balance 				CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_LOW 	2024.07.30 22:30 MXN 	 MX   CALENDAR_SECTOR_TRADE 	-900000   -174071000 CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1

    これらの結果は以下の変数に格納されます。

    Calendar &NewsTime[]

    以下のEconomicNextEvent関数は先に述べたEconomicDetailsMemoryの関数と似ていますが、主な違いは、特定の日付のすべてのイベントを取得するのではなく、次のイベントを取得することです。

    //+------------------------------------------------------------------+
    //|Will update UpcomingNews structure variable with the next event   |
    //|data                                                              |
    //+------------------------------------------------------------------+
    void CNews::EconomicNextEvent(datetime date=0)
      {
    //--- Declare unassigned Calendar structure variable Empty
       Calendar Empty;
    //--- assign empty values to Calendar structure variable UpcomingNews
       UpcomingNews = Empty;
    //--- If date variable is zero then assign current date
       date = (date==0)?TimeTradeServer():date;
    //--- Query to retrieve next upcoming event.
       string request_text=StringFormat("WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',"
                                        "EventType as 'Type',EventImportance as 'Importance',%s as 'CTime',EventCurrency as 'Currency',"
                                        "EventCode as 'Code',EventSector as 'Sector',EventForecast as 'Forecast',"
                                        "EventPrevalue as 'Prevalue',EventImpact as 'Impact',EventFrequency as 'Freq',"
                                        "RANK() OVER (PARTITION BY %s ORDER BY CASE EventPrevalue WHEN 'None' THEN 2 ELSE 1 END"
                                        ", CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,CASE EventImportance "
                                        "WHEN 'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 WHEN"
                                        " 'CALENDAR_IMPORTANCE_LOW' THEN 3 ELSE 4 END) Ranking FROM %s) SELECT Id,Country,Name,"
                                        "Type,Importance,CTime,Currency,Code,Sector,Forecast,Prevalue,Impact,Freq FROM MySubQuery "
                                        "where Replace(CTime,'.','-')>=Replace('%s','.','-') AND Ranking<2 Group by CTime LIMIT 1;",
                                        EnumToString(MySchedule),EnumToString(MySchedule),DBMemory.name,TimeToString(date));
    
       int request=DatabasePrepare(DBMemoryConnection,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
       if(request==INVALID_HANDLE)//Checks if the request failed to be completed
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " request failed with code ", GetLastError());
          PrintFormat(request_text);
         }
    //--- Assign query results to Calendar structure variable UpcomingNews
       DatabaseReadBind(request,UpcomingNews);
    //--- Removes a request created in DatabasePrepare()
       DatabaseFinalize(request);
      }

    以下のEconomicNextEvent関数のクエリは前回説明したEconomicDetailsMemory関数のクエリと似ていますが、唯一の違いは結果を1で制限することです。

    WITH MySubQuery AS (SELECT EventId as 'Id',Country,EventName as 'Name',EventType as 'Type',EventImportance as 'Importance',
    DST_NONE as 'CTime',EventCurrency as 'Currency',EventCode as 'Code',EventSector as 'Sector',EventForecast as 'Forecast',
    EventPrevalue as 'Prevalue',EventImpact as'Impact',EventFrequency as 'Freq',RANK() OVER (PARTITION BY DST_NONE 
    Order BY CASE EventPrevalue WHEN 'None' THEN 2 ELSE 1 END,CASE EventForecast WHEN 'None' THEN 2 ELSE 1 END,
    CASE EventImportance WHEN 'CALENDAR_IMPORTANCE_HIGH' THEN 1 WHEN 'CALENDAR_IMPORTANCE_MODERATE' THEN 2 
    WHEN 'CALENDAR_IMPORTANCE_LOW' THEN 3 ELSE 4 END) Ranking FROM MQL5Calendar) SELECT Id,Country,Name,Type,
    Importance,CTime,Currency,Code,Sector,Forecast,Prevalue,Impact,Freq FROM MySubQuery where 
    Date(Replace(CTime,'.','-'))=Date(Replace('2024.07.30 00:00','.','-')) and Ranking<2 Group by CTime LIMIT 1;

    上記のクエリのサンプル結果を以下に示します。

    Id 		Country 	Name 					Type 			Importance 			CTime 		Currency Code Sector 			Forecast  Prevalue   Impact 		Freq 			  Ranking
    392030007 	Japan 		Unemployment Rate 			CALENDAR_TYPE_INDICATOR CALENDAR_IMPORTANCE_MODERATE 	2024.07.30 01:30 JPY 	 JP   CALENDAR_SECTOR_JOBS 	2500000   2600000    CALENDAR_IMPACT_NA CALENDAR_FREQUENCY_MONTH   1
    

    上記のサンプル結果は、ニュースクラスの外で宣言したUpcomingNewsという変数に格納されます。

    //--- Assign query results to Calendar structure variable UpcomingNews
       DatabaseReadBind(request,UpcomingNews);

    第2回以降にニュースクラスに追加された最後の関数はGetImpactと呼ばれるもので、以下に示します。この関数の目的は、ENUM_CALENDAR_EVENT_IMPACTと呼ばれる列挙体の列挙値を、今後のイベントに類似したプロパティや値を持つ過去のイベントに基づいて返すことです。さらに詳しく説明します。

    //+------------------------------------------------------------------+
    //|Will retrieve Upcoming Event Impact data                          |
    //+------------------------------------------------------------------+
    ENUM_CALENDAR_EVENT_IMPACT CNews::GetImpact()
      {
    //--- Declaration of string variable
       string impact=NULL;
    //--- Query to get impact data from previous event with the same event id and matching EventPrevalue and EventForecast scenarios.
       string request_text=StringFormat("SELECT EventImpact FROM %s where Replace(%s,'.','-')<Replace('%s','.','-') AND EventId=%d"
                                        " %s ORDER BY %s DESC LIMIT 1;",DBMemory.name,EnumToString(MySchedule),UpcomingNews.EventDate,
                                        UpcomingNews.EventId,((UpcomingNews.EventPreval=="None"||UpcomingNews.EventForecast=="None")?
                                              "AND EventImpact='CALENDAR_IMPACT_NA'":(int(UpcomingNews.EventPreval)<int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue<EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              (int(UpcomingNews.EventPreval)>int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue>EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              "AND EventPrevalue=EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'"),
                                        EnumToString(MySchedule));
    
       int request=DatabasePrepare(DBMemoryConnection,request_text);//Creates a handle of a request, which can then be executed using DatabaseRead()
    
       if(request==INVALID_HANDLE)//Checks if the request failed to be completed
         {
          Print("DB: ",NEWS_DATABASE_MEMORY, " request failed with code ", GetLastError());
          PrintFormat(request_text);
         }
       if(DatabaseRead(request))//Will read the one record in the 'Record' table
         {
          //--- assign first column result into impact variable
          DatabaseColumnText(request,0,impact);
         }
    //--- Removes a request created in DatabasePrepare()
       DatabaseFinalize(request);
    //--- Return equivalent Event impact in the enumeration ENUM_CALENDAR_EVENT_IMPACT
       if(impact=="CALENDAR_IMPACT_POSITIVE")
         {
          return CALENDAR_IMPACT_POSITIVE;
         }
       else
          if(impact=="CALENDAR_IMPACT_NEGATIVE")
            {
             return CALENDAR_IMPACT_NEGATIVE;
            }
          else
            {
             return CALENDAR_IMPACT_NA;
            }
      }

    私が観察したところ、イベントの影響は基本的に、今後のイベントや当日に発生したイベントにはすべてCALENDAR_IMPACT_NAという影響の列挙値が設定されており、これはそのイベントの影響が利用できないことを意味します。イベントの影響は、イベントの日が過ぎた後にのみ更新され、イベントが発生する前にイベントの前値とイベント予測値の両方が利用可能であった場合に限り更新されます。ただし、これらの要件がすべて満たされていても、イベントの影響が「利用不可」として登録される場合もあります。 


    前回のイベント影響値が必要な理由とその活用法

    第一に、前回のイベントの影響を必要とする理由は、次のイベントの影響結果を予測するためです。次のイベントの前の値が「なし」でなく、予測値でもない場合、これらの値が等しいか、どちらの値が他より大きいかを確認します。どちらの値が他方より大きいか、あるいは同じ値であるかが分かったら、次に同じ構成を持つ過去のイベントを探し、そのイベントの影響を取得して、今度のイベントの影響を予測します。例:次のイベントの前回値が3000で予測値が10000の場合、同じイベントIDで前回値が予測値より小さかった最後のイベントを探し、このイベントの影響を今度のイベントに使用します。

    <>イベントの影響についてと影響の基盤

    イベントの影響とは、特定のイベントが通貨に与えた影響を測定するもので、影響はイベントの通貨に基づいています。たとえば、失業率が今後のイベントであり、同様の前回値と予測値の構成を持つ過去のイベントの影響がCALENDAR_IMPACT_NEGATIVEでイベント通貨がUSDである場合、これは本質的に米ドルが前回の失業率にマイナスの影響を受けたことを意味します。したがって、前回の失業率が発生した直後にEURUSDにいた場合、理想的にはEURUSDが強まるのを見るでしょう。 

    以下のクエリでは、メモリ内データベースMQL5Calendarテーブルからイベントの影響をSELECTし、WHERE句で、次のイベント日より前のイベント日を検索し、同じイベントIDをフィルタリングしています。次に、イベントの前回値 (EventPreval) とイベント予測値 (EventForecast) の間に同じ関係シナリオがあるかどうかをフィルタリングします。UpcomingNews.EventPrevalがNoneに等しいか、UpcomingNews.EventForecastがNoneに等しい場合、イベントの影響がNoneになることはすでに分かっています。また、UpcomingNews.EventPrevalがUpcomingNews.EventForecastより小さい場合、イベントの影響はNoneになります。EventPrevalue<EventForecastで、イベントの影響がNAでない過去のイベントを探します。UpcomingNews.EventPrevalがUpcomingNewsEventForecastより大きい場合、EventPreval > EventForecastかつイベントの影響がNAでない過去のイベントを探します。それ以外の場合、EventPrevalue=EventForecastかつイベントの影響がNAでない者を探します。ORDER BY句はイベント日付の降順であり、LIMIT句は1つのレコードのみを返すように設定しているため、すべての結果は最新の日付でフィルタリングされます。

    //--- Query to get impact data from previous event with the same event id and matching EventPrevalue and EventForecast scenarios.
       string request_text=StringFormat("SELECT EventImpact FROM %s where Replace(%s,'.','-')<Replace('%s','.','-') AND EventId=%d"
                                        " %s ORDER BY %s DESC LIMIT 1;",DBMemory.name,EnumToString(MySchedule),UpcomingNews.EventDate,
                                        UpcomingNews.EventId,((UpcomingNews.EventPreval=="None"||UpcomingNews.EventForecast=="None")?
                                              "AND EventImpact='CALENDAR_IMPACT_NA'":(int(UpcomingNews.EventPreval)<int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue<EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              (int(UpcomingNews.EventPreval)>int(UpcomingNews.EventForecast))?
                                              "AND EventPrevalue>EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'":
                                              "AND EventPrevalue=EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA'"),
                                        EnumToString(MySchedule));

    上のクエリで、すべての変数がデータで満たされたときの例。そこで、以下に示すように、MQL5CalendarからEventImpactをSELECTし、DST_NONEが2024.08.01 16:30よりも前で、EventIdが124500001に等しく、EventPrevalueがEventForecastより小さく、かつEventImpactが'CALENDAR_IMPACT_NAでない行を取得します。その後、結果をDST_NONEに基づいて降順に並べ替え、最終的に結果を1件に制限します。

    SELECT EventImpact FROM MQL5Calendar where Replace(DST_NONE,'.','-')<Replace('2024.08.01 16:30','.','-') AND EventId=124500001 
    AND EventPrevalue<EventForecast AND EventImpact<>'CALENDAR_IMPACT_NA' ORDER BY DST_NONE DESC LIMIT 1;


    共通グラフィックスクラス

    このクラスは、チャート上にEAの視覚的要素を表示する役割を担っています。これまでのところ、第3回の視覚要素は第2回に比べて大幅に進化していることに気づいたでしょう。そして、これらの視覚要素を作成するコードも同様に進化しています。コードを見てみましょう。このクラスはニュース情報、リスク管理情報、口座情報にアクセスする必要があるため、これらのクラスはインクルードされています。

    #include "ObjectProperties.mqh"
    #include "RiskManagement.mqh"
    #include "CommonVariables.mqh"
    #include "News.mqh"
    //+------------------------------------------------------------------+
    //|CommonGraphics class                                              |
    //+------------------------------------------------------------------+
    class CCommonGraphics:CObjectProperties
      {
    private:
       //--- GraphicText structure this structure is responsible for managing the graphical text
       struct GraphicText
         {
          //--- private declaration for struct GraphicText
       private:
          //--- this structure will store properties for the subtext
          struct subtextformat
            {
             string      Label;//Store text label
             string      Text;//Store text value
            };
          //--- this structure inherits from subtextformat and is responsible for finding text
          struct found:subtextformat
            {
             bool        isFound;//Check if text is found
             int         index;//Get index for the text
            };
          //--- structure array for subtexts
          subtextformat  sub_text[];
          //--- function to find text properties from text's label
          found          FoundText(string label)
            {
             found find;
             find.Label="";
             find.Text="";
             find.isFound=false;
             find.index=-1;
             for(uint i=0;i<sub_text.Size();i++)
               {
                //--- If text label is found in array
                if(label==sub_text[i].Label)
                  {
                   //--- Assign text properties
                   find.Label=sub_text[i].Label;
                   find.Text=sub_text[i].Text;
                   find.isFound=true;
                   find.index=int(i);
                   return find;//return found text properties
                  }
               }
             return find;//return text properties
            }
          //--- public declaration for struct GraphicText
       public:
          //--- string variable
          string         text;
          //--- function to set/add text properties
          void           subtext(string label,string value)
            {
             //--- Get text properties from label
             found result = FoundText(label);
             //--- Check if text label was found/exists in array sub_text
             if(!result.isFound)
               {
                //--- Resize array sub_text
                ArrayResize(sub_text,sub_text.Size()+1,sub_text.Size()+2);
                //--- Add text properties for new array index
                sub_text[sub_text.Size()-1].Label = label;
                sub_text[sub_text.Size()-1].Text = value;
               }
             else
               {
                /* Set new text/override text from text label that exists
                in the array sub_text array */
                sub_text[result.index].Text = value;
               }
            }
          //--- function to retrieve text from text label
          string         subtext(string label)
            {
             return FoundText(label).Text;
            }
         };// End of struct GraphicText
    
       //--- AccountInfo object declaration
       CAccountInfo      CAccount;
       //--- News object declaration
       CNews             NewsObj;
       //--- TimeManagement object declaration
       CTimeManagement   CTime;
       //--- Calendar structure array declaration
       Calendar          CalendarArray[];
       //--- color variable declaration
       color             EventColor;
       //--- unit variable declarations
       uint              Fontsize,X_start,Y_start;
       //--- void function declarations for Graphical blocks
       void              Block_1();
       void              Block_2(uint SecondsPreEvent=5);
       CRiskManagement   CRisk;//Risk management class object
       //--- GraphicText structure array declarations
       GraphicText       Texts_Block1[9],Texts_Block2[7];
       //--- structure to store text height and width
       struct Text_Prop_Size
         {
          uint           Height;//store text height
          uint           Width;//store text width
         };
    
       //--- void function to retrieve sum of the texts height and the maximum width of texts from GraphicText array Texts
       void              GetTextMaxWidthAndHeight(GraphicText &Texts[],uint &Max_Height,uint &Max_Width,uint FontSize)
         {
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- set variables to default value of zero
          Max_Height=0;
          Max_Width=0;
          //--- loop through all texts in the GraphicText array Texts
          for(uint i=0;i<Texts.Size();i++)
            {
             //--- temporary declarations for height and width
             uint Height=0,Width=0;
             //--- retrieve text height and width from index in Texts array
             TextGetSize(Texts[i].text,Width,Height);
             //--- sum texts height to variable Max_Height
             Max_Height+=Height;
             //--- assign width if text width is more than variable Max_Width value
             Max_Width=(Width>Max_Width)?Width:Max_Width;
            }
         }
       //--- function to retrieve text height and width properties in the structure Text_Prop_Size format
       Text_Prop_Size    GetText(string Text,uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- retrieve text height and width from Text string variable
          TextGetSize(Text,Size.Width,Size.Height);
          //--- return structure Text_Prop_Size variable
          return Size;
         }
       //--- Function to get texts height sum and max width in the structure Text_Prop_Size format
       Text_Prop_Size    GetTextMax(GraphicText &Texts[],uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- uint variable declarations for text properties
          uint Max_Height;
          uint Max_Width;
          //--- Retrieve sum of texts height and maximum texts width into Max_Height,Max_Width
          GetTextMaxWidthAndHeight(Texts,Max_Height,Max_Width,FontSize);
          //--- assign values into structure Text_Prop_Size variable
          Size.Height = Max_Height;
          Size.Width = Max_Width;
          //--- return structure Text_Prop_Size variable
          return Size;
         }
       //--- Boolean declarations
       bool              is_date,is_spread,is_news,is_events;
    
    public:
       //--- class constructor
                         CCommonGraphics(bool display_date,bool display_spread,bool display_news,bool display_events);
                        ~CCommonGraphics(void) {}//class destructor
       void              GraphicsRefresh(uint SecondsPreEvent=5);//will create/refresh the chart objects
       //--- will update certain graphics at an interval
       void              Block_2_Realtime(uint SecondsPreEvent=5);
       //--- will create chart event objects
       void              NewsEvent();
      };

    下のGraphicTextという構造体は、MQL5において一般的な構造体とは異なり、構造体、構造体配列、関数、文字列変数のprivate宣言やpublic宣言が含まれています。この場合、GraphicText構造体は全く別のクラスのように振る舞います。この構造体の目的は、グラフィカルなテキストを管理・保存することであり、構造体配列sub_textにはすべてのテキストプロパティが格納されます。関数 FoundText はsub_text配列内で一致するテキストラベルを検索し、一致するものがあれば、構造体subtextformatを継承したfoundという構造体の中に一致するものの詳細を返します。public宣言では、textという文字列変数が、テキストの全長をsub_text構造体配列に格納します。void関数subtextは、テキストラベルとテキスト/サブテキストをsub_text配列に追加するか、文字列変数 label が配列内に見つかった場合は、配列に格納されているテキスト/サブテキストを上書きします。また、subtextと呼ばれる文字列関数は、sub_text構造体配列のラベルに関連付けられたラベルのテキストを取得します。

       //--- GraphicText structure this structure is responsible for managing the graphical text
       struct GraphicText
         {
          //--- private declaration for struct GraphicText
       private:
          //--- this structure will store properties for the subtext
          struct subtextformat
            {
             string      Label;//Store text label
             string      Text;//Store text value
            };
          //--- this structure inherits from subtextformat and is responsible for finding text
          struct found:subtextformat
            {
             bool        isFound;//Check if text is found
             int         index;//Get index for the text
            };
          //--- structure array for subtexts
          subtextformat  sub_text[];
          //--- function to find text properties from text's label
          found          FoundText(string label)
            {
             found find;
             find.Label="";
             find.Text="";
             find.isFound=false;
             find.index=-1;
             for(uint i=0;i<sub_text.Size();i++)
               {
                //--- If text label is found in array
                if(label==sub_text[i].Label)
                  {
                   //--- Assign text properties
                   find.Label=sub_text[i].Label;
                   find.Text=sub_text[i].Text;
                   find.isFound=true;
                   find.index=int(i);
                   return find;//return found text properties
                  }
               }
             return find;//return text properties
            }
          //--- public declaration for struct GraphicText
       public:
          //--- string variable
          string         text;
          //--- function to set/add text properties
          void           subtext(string label,string value)
            {
             //--- Get text properties from label
             found result = FoundText(label);
             //--- Check if text label was found/exists in array sub_text
             if(!result.isFound)
               {
                //--- Resize array sub_text
                ArrayResize(sub_text,sub_text.Size()+1,sub_text.Size()+2);
                //--- Add text properties for new array index
                sub_text[sub_text.Size()-1].Label = label;
                sub_text[sub_text.Size()-1].Text = value;
               }
             else
               {
                /* Set new text/override text from text label that exists
                in the array sub_text array */
                sub_text[result.index].Text = value;
               }
            }
          //--- function to retrieve text from text label
          string         subtext(string label)
            {
             return FoundText(label).Text;
            }
         };// End of struct GraphicText

    以下の関数は、構造体配列Texts内のテキストの高さの合計と、配列内のテキストの最大幅を取得するために作成されています。

     //--- void function to retrieve sum of the texts height and the maximum width of texts from GraphicText array Texts
       void              GetTextMaxWidthAndHeight(GraphicText &Texts[],uint &Max_Height,uint &Max_Width,uint FontSize)
         {
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- set variables to default value of zero
          Max_Height=0;
          Max_Width=0;
          //--- loop through all texts in the GraphicText array Texts
          for(uint i=0;i<Texts.Size();i++)
            {
             //--- temporary declarations for height and width
             uint Height=0,Width=0;
             //--- retrieve text height and width from index in Texts array
             TextGetSize(Texts[i].text,Width,Height);
             //--- sum texts height to variable Max_Height
             Max_Height+=Height;
             //--- assign width if text width is more than variable Max_Width value
             Max_Width=(Width>Max_Width)?Width:Max_Width;
            }
         }

    以下の関数は、文字列変数Textから、構造体Text_Prop_Size形式の高さと幅のプロパティを取得するために作成されています。

    //--- function to retrieve text height and width properties in the structure Text_Prop_Size format
       Text_Prop_Size    GetText(string Text,uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- set fontsize properties to get accurate text height and width sizes
          TextSetFont("Arial",(-1*FontSize)-100);
          //--- retrieve text height and width from Text string variable
          TextGetSize(Text,Size.Width,Size.Height);
          //--- return structure Text_Prop_Size variable
          return Size;
         }

    以下の関数は、構造体配列Textsから、構造体Text_Prop_Size形式の高さの合計と最大幅のプロパティを取得するために作成されています。

    //--- Function to get texts height sum and max width in the structure Text_Prop_Size format
       Text_Prop_Size    GetTextMax(GraphicText &Texts[],uint FontSize)
         {
          //--- structure Text_Prop_Size variable
          Text_Prop_Size Size;
          //--- uint variable declarations for text properties
          uint Max_Height;
          uint Max_Width;
          //--- Retrieve sum of texts height and maximum texts width into Max_Height,Max_Width
          GetTextMaxWidthAndHeight(Texts,Max_Height,Max_Width,FontSize);
          //--- assign values into structure Text_Prop_Size variable
          Size.Height = Max_Height;
          Size.Width = Max_Width;
          //--- return structure Text_Prop_Size variable
          return Size;
         }

    クラスのコンストラクタでは、以前に宣言した変数を初期化します。具体的には、is_date(チャートに日付情報を表示するかどうかを判断するために使用)、is_spread(チャートにスプレッド情報を表示するかどうかを判断するために使用)、is_news(チャートにニュース情報を表示するかどうかを判断するために使用)、および is_events(チャートにイベントオブジェクト情報を表示するかどうかを判断するために使用)を初期化します。ニュースオブジェクトEconomicNextEvent関数は、次のニュースの詳細でUpcomingNews変数を更新します。

    //+------------------------------------------------------------------+
    //|Constructor                                                       |
    //+------------------------------------------------------------------+
    CCommonGraphics::CCommonGraphics(bool display_date,bool display_spread,bool display_news,bool display_events):
    //--- Assign variables
       is_date(display_date),is_spread(display_spread),is_news(display_news),is_events(display_events)
      {
    //--- get next news event
       NewsObject.EconomicNextEvent();
      }

    GraphicsRefreshは、まず、以前に作成されたオブジェクトがあればそれを消去し、次に、現在のチャートに様々な情報を表示するためのチャートオブジェクトを作成する他の関数を呼び出します。

    //+------------------------------------------------------------------+
    //|will create/refresh the chart objects                             |
    //+------------------------------------------------------------------+
    void CCommonGraphics::GraphicsRefresh(uint SecondsPreEvent=5)
      {
    //--- create graphics if outside the strategy tester or in the strategy tester and visual mode is enabled
       if((!MQLInfoInteger(MQL_TESTER))||(MQLInfoInteger(MQL_TESTER)&&MQLInfoInteger(MQL_VISUAL_MODE)))
         {
          //--- Delete chart objects
          DeleteObj();//function from Object properties class
          Block_1();//Create graphics for block 1
          //--- Check whether to create graphics for block 2
          if(is_date||is_news||is_spread)
            {
             Block_2(SecondsPreEvent);//Create graphics for block 2
            }
          //--- creates event objects
          NewsEvent();
         }
      }

    Block_1と呼ばれる以下の関数は、以下に示すグラフィカルブロック1のグラフィカル要素の作成を担当します。

    • 銘柄名
    • 銘柄期間
    • 銘柄の説明
    • 銘柄契約サイズ
    • 銘柄最小ロットサイズ
    • 銘柄最大ロットサイズ
    • 銘柄ボリュームステップ
    • 銘柄ボリューム制限
    • リスクオプション
    • リスク下限
    • リスク上限

    グラフィカルブロック1

    //+------------------------------------------------------------------+
    //|Graphical Block 1                                                 |
    //+------------------------------------------------------------------+
    void CCommonGraphics::Block_1()
      {
    //--- Set text object color depending if the chart color mode is LightMode or not
       TextObj_color = (isLightMode)?clrBlack:clrWheat;
    //--- Set text properties for Symbol name,Symbol period and Symbol description # section 1
       Texts_Block1[0].text = Symbol()+", "+GetChartPeriodName()+": "+CSymbol.Description();//set main text
       Texts_Block1[0].subtext("Symbol Name",Symbol()+",");//set subtext - label,value
       Texts_Block1[0].subtext("Symbol Period",GetChartPeriodName());//set subtext - label,value
       Texts_Block1[0].subtext("Symbol Desc",": "+CSymbol.Description());//set subtext - label,value
    //--- Set text properties for Contract size # section 2
       Texts_Block1[1].text = "Contract Size: "+string(CSymbol.ContractSize());//set main text
       Texts_Block1[1].subtext("Contract Size Text","Contract Size:");//set subtext - label,value
       Texts_Block1[1].subtext("Contract Size",string(CSymbol.ContractSize()));//set subtext - label,value
    //--- Set text properties for Minimum lot # section 3
       Texts_Block1[2].text = "Minimum Lot: "+string(CSymbol.LotsMin());//set main text
       Texts_Block1[2].subtext("Minimum Lot Text","Minimum Lot:");//set subtext - label,value
       Texts_Block1[2].subtext("Minimum Lot",string(CSymbol.LotsMin()));//set subtext - label,value
    //--- Set text properties for Max lot # section 4
       Texts_Block1[3].text = "Max Lot: "+string(CSymbol.LotsMax());//set main text
       Texts_Block1[3].subtext("Max Lot Text","Max Lot:");//set subtext - label,value
       Texts_Block1[3].subtext("Max Lot",string(CSymbol.LotsMax()));//set subtext - label,value
    //--- Set text properties for Volume step # section 5
       Texts_Block1[4].text = "Volume Step: "+string(CSymbol.LotsStep());//set main text
       Texts_Block1[4].subtext("Volume Step Text","Volume Step:");//set subtext - label,value
       Texts_Block1[4].subtext("Volume Step",string(CSymbol.LotsStep()));//set subtext - label,value
    //--- Set text properties for Volume limit # section 6
       Texts_Block1[5].text = "Volume Limit: "+string(CSymbol.LotsLimit());//set main text
       Texts_Block1[5].subtext("Volume Limit Text","Volume Limit:");//set subtext - label,value
       Texts_Block1[5].subtext("Volume Limit",string(CSymbol.LotsLimit()));//set subtext - label,value
    //--- Set text properties for Risk option # section 7
       Texts_Block1[6].text = "Risk Option: "+CRisk.GetRiskOption();//set main text
       Texts_Block1[6].subtext("Risk Option Text","Risk Option:");//set subtext - label,value
       Texts_Block1[6].subtext("Risk Option",CRisk.GetRiskOption());//set subtext - label,value
    //--- Set text properties for Risk floor # section 8
       Texts_Block1[7].text = "Risk Floor: "+CRisk.GetRiskFloor();//set main text
       Texts_Block1[7].subtext("Risk Floor Text","Risk Floor:");//set subtext - label,value
       Texts_Block1[7].subtext("Risk Floor",CRisk.GetRiskFloor());//set subtext - label,value
    //--- Set text properties for Risk ceiling # section 9
       Texts_Block1[8].text = "Risk Ceiling: "+CRisk.GetRiskCeil();//set main text
       Texts_Block1[8].subtext("Risk Ceiling Text","Risk Ceiling:");//set subtext - label,value
       Texts_Block1[8].subtext("Risk Ceiling",CRisk.GetRiskCeil());//set subtext - label,value
    
    //--- Set basic properties
       Fontsize=10;//Set Fontsize
       X_start=2;//Set X distance
       Y_start=2;//Set Y distance
    
    /* Create objects # section 1*/
    //-- Create the background object for width and height+3 of section 1 text
       Square(0,"Symbol Name background",X_start,Y_start,GetText(Texts_Block1[0].text,Fontsize).Width,
              GetText(Texts_Block1[0].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 1
       TextObj(0,"Symbol Name",Texts_Block1[0].subtext("Symbol Name"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[0].subtext("Symbol Name"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Period",Texts_Block1[0].subtext("Symbol Period"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[0].subtext("Symbol Period"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Desc",Texts_Block1[0].subtext("Symbol Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 2*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[0].text,Fontsize).Height;//Re-adjust Y distance, add height from section 1
       //-- Create the background object for width and height+3 of section 2 text
       Square(0,"Symbol Contract Size background",X_start,Y_start,GetText(Texts_Block1[1].text,Fontsize).Width,
              GetText(Texts_Block1[1].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 2
       TextObj(0,"Symbol Contract Size Text",Texts_Block1[1].subtext("Contract Size Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[1].subtext("Contract Size Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Contract Size",Texts_Block1[1].subtext("Contract Size"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 3*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[1].text,Fontsize).Height;//Re-adjust Y distance, add height from section 2
       //-- Create the background object for width and height+3 of section 3 text
       Square(0,"Symbol MinLot background",X_start,Y_start,GetText(Texts_Block1[2].text,Fontsize).Width,
              GetText(Texts_Block1[2].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 3
       TextObj(0,"Symbol MinLot Text",Texts_Block1[2].subtext("Minimum Lot Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[2].subtext("Minimum Lot Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol MinLot",Texts_Block1[2].subtext("Minimum Lot"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 4*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[2].text,Fontsize).Height;//Re-adjust Y distance, add height from section 3
       //-- Create the background object for width and height+3 of section 4 text
       Square(0,"Symbol MaxLot background",X_start,Y_start,GetText(Texts_Block1[3].text,Fontsize).Width,
              GetText(Texts_Block1[3].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 4
       TextObj(0,"Symbol MaxLot Text",Texts_Block1[3].subtext("Max Lot Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[3].subtext("Max Lot Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol MaxLot",Texts_Block1[3].subtext("Max Lot"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 5*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[3].text,Fontsize).Height;//Re-adjust Y distance, add height from section 4
       //-- Create the background object for width and height+3 of section 5 text
       Square(0,"Symbol Volume Step background",X_start,Y_start,GetText(Texts_Block1[4].text,Fontsize).Width,
              GetText(Texts_Block1[4].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 5
       TextObj(0,"Symbol Volume Step Text",Texts_Block1[4].subtext("Volume Step Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[4].subtext("Volume Step Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Volume Step",Texts_Block1[4].subtext("Volume Step"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 6*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[4].text,Fontsize).Height;//Re-adjust Y distance, add height from section 5
       //-- Create the background object for width and height+3 of section 6 text
       Square(0,"Symbol Volume Limit background",X_start,Y_start,GetText(Texts_Block1[5].text,Fontsize).Width,
              GetText(Texts_Block1[5].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 6
       TextObj(0,"Symbol Volume Limit Text",Texts_Block1[5].subtext("Volume Limit Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[5].subtext("Volume Limit Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Symbol Volume Limit",Texts_Block1[5].subtext("Volume Limit"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 7*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[5].text,Fontsize).Height;//Re-adjust Y distance, add height from section 6
       //-- Create the background object for width and height+3 of section 7 text
       Square(0,"Risk Option background",X_start,Y_start,GetText(Texts_Block1[6].text,Fontsize).Width,
              GetText(Texts_Block1[6].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 7
       TextObj(0,"Risk Option Text",Texts_Block1[6].subtext("Risk Option Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[6].subtext("Risk Option Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Risk Option",Texts_Block1[6].subtext("Risk Option"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 8*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[6].text,Fontsize).Height;//Re-adjust Y distance, add height from section 7
       //-- Create the background object for width and height+3 of section 8 text
       Square(0,"Risk Floor background",X_start,Y_start,GetText(Texts_Block1[7].text,Fontsize).Width,
              GetText(Texts_Block1[7].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 8
       TextObj(0,"Risk Floor Text",Texts_Block1[7].subtext("Risk Floor Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[7].subtext("Risk Floor Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Risk Floor",Texts_Block1[7].subtext("Risk Floor"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /* Create objects # section 9*/
       X_start=2;//Reset X distance
       Y_start+=GetText(Texts_Block1[7].text,Fontsize).Height;//Re-adjust Y distance, add height from section 8
       //-- Create the background object for width and height+3 of section 9 text
       Square(0,"Risk Ceil background",X_start,Y_start,GetText(Texts_Block1[8].text,Fontsize).Width,
              GetText(Texts_Block1[8].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
       Y_start+=3;//Re-adjust Y distance
       X_start+=2;//Re-adjust X distance
    //-- Will create the text objects for section 9
       TextObj(0,"Risk Ceil Text",Texts_Block1[8].subtext("Risk Ceiling Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
       X_start+=GetText(Texts_Block1[8].subtext("Risk Ceiling Text"),Fontsize).Width;//Re-adjust X distance
       TextObj(0,"Risk Ceil",Texts_Block1[8].subtext("Risk Ceiling"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
      }

    Block_2と呼ばれる以下の関数は、以下に示すグラフィカルブロック2のグラフィカル要素の作成を担当します。

    • 現在の日付と時刻
    • イベント日
    • イベント名
    • イベント開催国
    • イベント通貨
    • イベントの重要性
    • スプレッド評価

    グラフィカルブロック2

    //+------------------------------------------------------------------+
    //|Graphical Block 2                                                 |
    //+------------------------------------------------------------------+
    void CCommonGraphics::Block_2(uint SecondsPreEvent=5)
      {
    //--- Set text object color depending if the chart color mode is LightMode or not
       TextObj_color=(isLightMode)?clrBlack:clrWheat;
       if(is_date)//Check whether to display date information
         {
          //--- Set text properties for Date and Time # section 10
          Texts_Block2[0].text = "Date:"+TimeToString(TimeTradeServer(),TIME_DATE)+"|| Time:"+TimeToString(TimeTradeServer(),TIME_MINUTES)
                                 +"   ";//set main text
          Texts_Block2[0].subtext("Date Text","Date:");//set subtext - label,value
          Texts_Block2[0].subtext("Date",TimeToString(TimeTradeServer(),TIME_DATE));//set subtext - label,value
          Texts_Block2[0].subtext("Time Text","|| Time:");//set subtext - label,value
          Texts_Block2[0].subtext("Time",TimeToString(TimeTradeServer(),TIME_MINUTES));//set subtext - label,value
         }
       if(is_news)//Check whether to display news information
         {
          //--- Set text object color depending on upcoming news event's Importance
          EventColor = NewsObj.GetImportance_color(NewsObj.IMPORTANCE(UpcomingNews.EventImportance));
          //--- Set text properties for Event Date # section 11
          Texts_Block2[1].text = "Event: @"+UpcomingNews.EventDate+" ";//set main text
          Texts_Block2[1].subtext("Event Date Text","Event: @");//set subtext - label,value
          Texts_Block2[1].subtext("Event Date",UpcomingNews.EventDate);//set subtext - label,value
          //--- Set text properties for Event Name # section 12
          Texts_Block2[2].text = "Name: "+UpcomingNews.EventName+" ";//set main text
          Texts_Block2[2].subtext("Event Name Text","Name: ");//set subtext - label,value
          Texts_Block2[2].subtext("Event Name",UpcomingNews.EventName);//set subtext - label,value
          //--- Set text properties for Event Country # section 13
          Texts_Block2[3].text = "Country: "+UpcomingNews.CountryName+" ";//set main text
          Texts_Block2[3].subtext("Event Country Text","Country: ");//set subtext - label,value
          Texts_Block2[3].subtext("Event Country",UpcomingNews.CountryName);//set subtext - label,value
          //--- Set text properties for Event Currency # section 14
          Texts_Block2[4].text = "Currency: "+UpcomingNews.EventCurrency+" ";//set main text
          Texts_Block2[4].subtext("Event Currency Text","Currency: ");//set subtext - label,value
          Texts_Block2[4].subtext("Event Currency",UpcomingNews.EventCurrency);//set subtext - label,value
          //--- Set text properties for Event Importance # section 15
          Texts_Block2[5].text = "Importance: "+NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance))+" ";//set main text
          Texts_Block2[5].subtext("Importance Text","Importance: ");//set subtext - label,value
          Texts_Block2[5].subtext("Importance",NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance)));//set subtext - label,value
         }
       if(is_spread)//Check whether to display spread information
         {
          //--- Set text properties for Spread # section 16
          Texts_Block2[6].text = "Spread: "+string(CSymbol.Spread())+" Rating: "+CSymbol.SpreadDesc()+" ";//set main text
          Texts_Block2[6].subtext("Spread Text","Spread:");//set subtext - label,value
          Texts_Block2[6].subtext("Spread",string(CSymbol.Spread()));//set subtext - label,value
          Texts_Block2[6].subtext("Rating Text"," Rating:");//set subtext - label,value
          Texts_Block2[6].subtext("Rating Desc",CSymbol.SpreadDesc());//set subtext - label,value
         }
    
    //--- Set basic properties
       Fontsize=10;
       X_start=2;//Reset X distance
       Y_start=GetTextMax(Texts_Block1,Fontsize).Height+29;//Re-adjust Y distance from graphical block 1 Height
    
       /* Create objects # section 10*/
       if(is_date)//Check whether to display date information
         {
          //-- Create the background object for width and height+3 of section 10 text
          Square(0,"Datetime background",X_start,Y_start,GetText(Texts_Block2[0].text,Fontsize).Width,
                 GetText(Texts_Block2[0].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //-- Will create the text objects for section 10
          TextObj(0,"Date Text",Texts_Block2[0].subtext("Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date Text"),Fontsize).Width;//Re-adjust X distance
          TextObj(0,"Date",Texts_Block2[0].subtext("Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date"),Fontsize).Width;//Re-adjust X distance
          TextObj(0,"Time Text",Texts_Block2[0].subtext("Time Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Time Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Time",Texts_Block2[0].subtext("Time"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
         }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       if(UpcomingNews.CountryName!=NULL&&is_news)//Check whether to display news information and if upcoming news is available
         {
          /* Create objects # section 11*/
          Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;//Re-adjust Y distance depending if section 10 is shown
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 11 text
          Square(0,"Event Date background",X_start,Y_start,GetText(Texts_Block2[1].text,Fontsize).Width,
                 GetText(Texts_Block2[1].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 11
          TextObj(0,"Event Date Text",Texts_Block2[1].subtext("Event Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[1].subtext("Event Date Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Event Date",Texts_Block2[1].subtext("Event Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 12*/
          Y_start+=GetText(Texts_Block2[1].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 12 text
          Square(0,"Event Name background",X_start,Y_start,GetText(Texts_Block2[2].text,Fontsize).Width,
                 GetText(Texts_Block2[2].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 12
          TextObj(0,"Event Name Text",Texts_Block2[2].subtext("Event Name Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[2].subtext("Event Name Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Name",Texts_Block2[2].subtext("Event Name"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 13*/
          Y_start+=GetText(Texts_Block2[2].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 13 text
          Square(0,"Event Country background",X_start,Y_start,GetText(Texts_Block2[3].text,Fontsize).Width,
                 GetText(Texts_Block2[3].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 13
          TextObj(0,"Event Country Text",Texts_Block2[3].subtext("Event Country Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[3].subtext("Event Country Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Country",Texts_Block2[3].subtext("Event Country"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 14*/
          Y_start+=GetText(Texts_Block2[3].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 14 text
          Square(0,"Event Currency background",X_start,Y_start,GetText(Texts_Block2[4].text,Fontsize).Width,
                 GetText(Texts_Block2[4].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 14
          TextObj(0,"Event Currency Text",Texts_Block2[4].subtext("Event Currency Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[4].subtext("Event Currency Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Currency",Texts_Block2[4].subtext("Event Currency"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 15*/
          Y_start+=GetText(Texts_Block2[4].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Create the background object for width and height+3 of section 15 text
          Square(0,"Event Importance background",X_start,Y_start,GetText(Texts_Block2[5].text,Fontsize).Width,
                 GetText(Texts_Block2[5].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will create the text objects for section 15
          TextObj(0,"Importance Text",Texts_Block2[5].subtext("Importance Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[5].subtext("Importance Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Importance",Texts_Block2[5].subtext("Importance"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=GetText(Texts_Block2[5].text,Fontsize).Height;//Re-adjust Y distance
             X_start=2;//Reset X distance
             //-- Create the background object for width and height+3 of section 16 text
             Square(0,"Spread background",X_start,Y_start,GetText(Texts_Block2[6].text,Fontsize).Width,
                    GetText(Texts_Block2[6].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             //-- Will create the text objects for section 16
             TextObj(0,"Symbol Spread Text",Texts_Block2[6].subtext("Spread Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
         }
       else
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;//Re-adjust Y distance depending if section 10 is shown
             X_start=2;//Reset X distance
             //-- Create the background object for width and height+3 of section 16 text
             Square(0,"Spread background",X_start,Y_start,GetText(Texts_Block2[6].text,Fontsize).Width,
                    GetText(Texts_Block2[6].text,Fontsize).Height+3,ANCHOR_LEFT_UPPER);
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             //-- Will create the text objects for section 16
             TextObj(0,"Symbol Spread Text",Texts_Block2[6].subtext("Spread Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
      }

    以下の関数は、グラフィカルブロック2セクションの変更を更新します。また、関数Block_2からすべての要素を再作成することはありません。

    //+------------------------------------------------------------------+
    //|will update certain graphics at an interval                       |
    //+------------------------------------------------------------------+
    void CCommonGraphics::Block_2_Realtime(uint SecondsPreEvent=5)
      {
       if(MQLInfoInteger(MQL_TESTER)&&!MQLInfoInteger(MQL_VISUAL_MODE))
         {
          return;//exit if in strategy tester and not in visual mode
         }
    
       if(is_date)//Check whether to display date information
         {
          //--- Set text properties for Date and Time # section 10
          Texts_Block2[0].text = "Date:"+TimeToString(TimeTradeServer(),TIME_DATE)+"|| Time:"+TimeToString(TimeTradeServer(),TIME_SECONDS)
                                 +"   ";//set main text
          Texts_Block2[0].subtext("Date Text","Date:");//set subtext - label,value
          Texts_Block2[0].subtext("Date",TimeToString(TimeTradeServer(),TIME_DATE));//set subtext - label,value
          Texts_Block2[0].subtext("Time Text","|| Time:");//set subtext - label,value
          Texts_Block2[0].subtext("Time",TimeToString(TimeTradeServer(),TIME_SECONDS));//set subtext - label,value
         }
       if(is_news)//Check whether to display news information
         {
          //--- Set text object color depending on upcoming news event's Importance
          EventColor = NewsObj.GetImportance_color(NewsObj.IMPORTANCE(UpcomingNews.EventImportance));
          //--- Set text properties for Event Date # section 11
          Texts_Block2[1].text = "Event: @"+UpcomingNews.EventDate+" ";//set main text
          Texts_Block2[1].subtext("Event Date Text","Event: @");//set subtext - label,value
          Texts_Block2[1].subtext("Event Date",UpcomingNews.EventDate);//set subtext - label,value
          //--- Set text properties for Event Name # section 12
          Texts_Block2[2].text = "Name: "+UpcomingNews.EventName+" ";//set main text
          Texts_Block2[2].subtext("Event Name Text","Name: ");//set subtext - label,value
          Texts_Block2[2].subtext("Event Name",UpcomingNews.EventName);//set subtext - label,value
          //--- Set text properties for Event Country # section 13
          Texts_Block2[3].text = "Country: "+UpcomingNews.CountryName+" ";//set main text
          Texts_Block2[3].subtext("Event Country Text","Country: ");//set subtext - label,value
          Texts_Block2[3].subtext("Event Country",UpcomingNews.CountryName);//set subtext - label,value
          //--- Set text properties for Event Currency # section 14
          Texts_Block2[4].text = "Currency: "+UpcomingNews.EventCurrency+" ";//set main text
          Texts_Block2[4].subtext("Event Currency Text","Currency: ");//set subtext - label,value
          Texts_Block2[4].subtext("Event Currency",UpcomingNews.EventCurrency);//set subtext - label,value
          //--- Set text properties for Event Importance # section 15
          Texts_Block2[5].text = "Importance: "+NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance))+" ";//set main text
          Texts_Block2[5].subtext("Importance Text","Importance: ");//set subtext - label,value
          Texts_Block2[5].subtext("Importance",NewsObj.GetImportance(NewsObj.IMPORTANCE(UpcomingNews.EventImportance)));//set subtext - label,value
         }
       if(is_spread)//Check whether to display spread information
         {
          //--- Set text properties for Spread # section 16
          Texts_Block2[6].text = "Spread: "+string(CSymbol.Spread())+" Rating: "+CSymbol.SpreadDesc()+" ";//set main text
          Texts_Block2[6].subtext("Spread Text","Spread:");//set subtext - label,value
          Texts_Block2[6].subtext("Spread",string(CSymbol.Spread()));//set subtext - label,value
          Texts_Block2[6].subtext("Rating Text"," Rating:");//set subtext - label,value
          Texts_Block2[6].subtext("Rating Desc",CSymbol.SpreadDesc());//set subtext - label,value
         }
    
    //--- Set basic properties
       Fontsize=10;
       X_start=2;//Reset X distance
       Y_start=GetTextMax(Texts_Block1,Fontsize).Height+29;//Re-adjust Y distance from section block 1
    
       /* Create objects # section 10*/
       if(is_date)//Check whether to display date information
         {
          //-- Check if the background object x-size for section 10 is the same size as section 10 text width
          if(ObjectGetInteger(0,"Datetime background",OBJPROP_XSIZE)!=GetText(Texts_Block2[0].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 10 text width
             ObjectSetInteger(0,"Datetime background",OBJPROP_XSIZE,long(GetText(Texts_Block2[0].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 10
          TextObj(0,"Date Text",Texts_Block2[0].subtext("Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Date",Texts_Block2[0].subtext("Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Date"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Time Text",Texts_Block2[0].subtext("Time Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[0].subtext("Time Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Time",Texts_Block2[0].subtext("Time"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
         }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       if(UpcomingNews.CountryName!=NULL&&is_news)//Check whether to display news information
         {
          /* Create objects # section 11*/
          Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 11 is the same size as section 11 text width
          if(ObjectGetInteger(0,"Event Date background",OBJPROP_XSIZE)!=GetText(Texts_Block2[1].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 11 text width
             ObjectSetInteger(0,"Event Date background",OBJPROP_XSIZE,long(GetText(Texts_Block2[1].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 11
          TextObj(0,"Event Date Text",Texts_Block2[1].subtext("Event Date Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[1].subtext("Event Date Text"),Fontsize).Width;//Re-adjust X distance
          //--- Adjust text color depending if chart color mode is LightMode and if a news event is occurring
          TextObj_color = CTime.TimeIsInRange(CTime.TimeMinusOffset(datetime(UpcomingNews.EventDate),SecondsPreEvent),
                                              CTime.TimePlusOffset(datetime(UpcomingNews.EventDate),59))?clrRed:(isLightMode)?clrBlack:clrWheat;
          TextObj(0,"Event Date",Texts_Block2[1].subtext("Event Date"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 12*/
          Y_start+=GetText(Texts_Block2[1].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 12 is the same size as section 12 text width
          if(ObjectGetInteger(0,"Event Name background",OBJPROP_XSIZE)!=GetText(Texts_Block2[2].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 12 text width
             ObjectSetInteger(0,"Event Name background",OBJPROP_XSIZE,long(GetText(Texts_Block2[2].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 12
          TextObj(0,"Event Name Text",Texts_Block2[2].subtext("Event Name Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[2].subtext("Event Name Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Name",Texts_Block2[2].subtext("Event Name"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 13*/
          Y_start+=GetText(Texts_Block2[2].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 13 is the same size as section 13 text width
          if(ObjectGetInteger(0,"Event Country background",OBJPROP_XSIZE)!=GetText(Texts_Block2[3].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 13 text width
             ObjectSetInteger(0,"Event Country background",OBJPROP_XSIZE,long(GetText(Texts_Block2[3].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 13
          TextObj(0,"Event Country Text",Texts_Block2[3].subtext("Event Country Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[3].subtext("Event Country Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Country",Texts_Block2[3].subtext("Event Country"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 14*/
          Y_start+=GetText(Texts_Block2[3].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 14 is the same size as section 14 text width
          if(ObjectGetInteger(0,"Event Currency background",OBJPROP_XSIZE)!=GetText(Texts_Block2[4].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 14 text width
             ObjectSetInteger(0,"Event Currency background",OBJPROP_XSIZE,long(GetText(Texts_Block2[4].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 14
          TextObj(0,"Event Currency Text",Texts_Block2[4].subtext("Event Currency Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[4].subtext("Event Currency Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Event Currency",Texts_Block2[4].subtext("Event Currency"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 15*/
          Y_start+=GetText(Texts_Block2[4].text,Fontsize).Height;//Re-adjust Y distance
          X_start=2;//Reset X distance
          //-- Check if the background object x-size for section 15 is the same size as section 15 text width
          if(ObjectGetInteger(0,"Event Importance background",OBJPROP_XSIZE)!=GetText(Texts_Block2[5].text,Fontsize).Width)
            {
             //-- Will re-adjust background object to any changes of section 15 text width
             ObjectSetInteger(0,"Event Importance background",OBJPROP_XSIZE,long(GetText(Texts_Block2[5].text,Fontsize).Width));
            }
          Y_start+=3;//Re-adjust Y distance
          X_start+=2;//Re-adjust X distance
          //--- Set text object color depending if the chart color mode is LightMode or not
          TextObj_color=(isLightMode)?clrBlack:clrWheat;
          //-- Will update the text objects for section 15
          TextObj(0,"Importance Text",Texts_Block2[5].subtext("Importance Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          X_start+=GetText(Texts_Block2[5].subtext("Importance Text"),Fontsize).Width;//Re-adjust X distance
          //--- Set text object color depending on upcoming news event's Importance
          TextObj_color=EventColor;
          TextObj(0,"Importance",Texts_Block2[5].subtext("Importance"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=GetText(Texts_Block2[5].text,Fontsize).Height;//Re-adjust Y distance
             X_start=2;//Reset X distance
             //-- Check if the background object x-size for section 16 is the same size as section 16 text width
             if(ObjectGetInteger(0,"Spread background",OBJPROP_XSIZE)!=GetText(Texts_Block2[6].text,Fontsize).Width)
               {
                //-- Will re-adjust background object to any changes of section 16 text width
                ObjectSetInteger(0,"Spread background",OBJPROP_XSIZE,long(GetText(Texts_Block2[6].text,Fontsize).Width));
               }
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //-- Will create the text object for the Symbol's name
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             //-- Will update the text objects for section 16
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
         }
       else
          /* Create objects # section 16*/
          if(is_spread)//Check whether to display spread information
            {
             Y_start+=(is_date)?GetText(Texts_Block2[0].text,Fontsize).Height:0;//Re-adjust Y distance
             X_start=2;//Reset X distance
             //-- Check if the background object x-size for section 16 is the same size as section 16 text width
             if(ObjectGetInteger(0,"Spread background",OBJPROP_XSIZE)!=GetText(Texts_Block2[6].text,Fontsize).Width)
               {
                //-- Will re-adjust background object to any changes of section 16 text width
                ObjectSetInteger(0,"Spread background",OBJPROP_XSIZE,long(GetText(Texts_Block2[6].text,Fontsize).Width));
               }
             Y_start+=3;//Re-adjust Y distance
             X_start+=2;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             color Spread_clr=CSymbol.SpreadColor();
             //-- Will create the text object for the Symbol's name
             X_start+=GetText(Texts_Block2[6].subtext("Spread Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             //-- Will update the text objects for section 16
             TextObj(0,"Symbol Spread",Texts_Block2[6].subtext("Spread"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Spread"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending if the chart color mode is LightMode or not
             TextObj_color=(isLightMode)?clrBlack:clrWheat;
             TextObj(0,"Symbol Rating Text",Texts_Block2[6].subtext("Rating Text"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
             X_start+=GetText(Texts_Block2[6].subtext("Rating Text"),Fontsize).Width;//Re-adjust X distance
             //--- Set text object color depending on spread rating
             TextObj_color=Spread_clr;
             TextObj(0,"Symbol Rating",Texts_Block2[6].subtext("Rating Desc"),X_start,Y_start,CORNER_LEFT_UPPER,Fontsize);
            }
      }

    以下の関数は、チャート上にイベントオブジェクトを作成し、その日のニュースイベントをすべて表示します。

    セクション17

    //+------------------------------------------------------------------+
    //|will create chart event objects                                   |
    //+------------------------------------------------------------------+
    void CCommonGraphics::NewsEvent()
      {
       if(!is_events||(MQLInfoInteger(MQL_TESTER)&&!MQLInfoInteger(MQL_VISUAL_MODE)))
         {return;}//exit if in strategy tester and not in visual mode or is_events variable is false
    //--- Retrieve news events for the current Daily period into array CalendarArray
       NewsObj.EconomicDetailsMemory(CalendarArray,iTime(Symbol(),PERIOD_D1,0));
    //--- Iterate through all events in CalendarArray
       for(uint i=0;i<CalendarArray.Size();i++)
         {
          //--- Create event object with the news properties
          EventObj(0,CalendarArray[i].EventName+" "+CalendarArray[i].CountryName+" "+CalendarArray[i].EventDate,
                   CalendarArray[i].EventName+"["+CalendarArray[i].CountryName+"]",StringToTime(CalendarArray[i].EventDate));
         }
    //--- Refresh the chart/ update the chart
       ChartRefresh();
      }


    取引管理クラス

    このクラスはEAの取引開始を担当します。その機能は、後の記事で拡張される予定です。取引管理クラスはリスク管理クラスを継承し、各取引のロットサイズを設定します。

    #include <Trade\Trade.mqh>
    #include <Trade\OrderInfo.mqh>
    #include <Trade\SymbolInfo.mqh>
    #include "RiskManagement.mqh"
    #include "TimeManagement.mqh"
    //+------------------------------------------------------------------+
    //|TradeManagement class                                             |
    //+------------------------------------------------------------------+
    class CTradeManagement:CRiskManagement
      {
    private:
       CTrade            Trade;//Trade class object
       CSymbolProperties CSymbol;//SymbolProperties class object
       CTimeManagement   CTime;//TimeManagement class object
       bool              TradeResult;//boolean to store trade result
       double            mySL;//double variable to store Stoploss
       double            myTP;//double variable to store Takeprofit
    public:
       //--- Class constructor
                         CTradeManagement(string SYMBOL=NULL)
         {
          //--- Set symbol name
          CSymbol.SetSymbolName(SYMBOL);
         }
       //--- Class destructor
                        ~CTradeManagement(void) {}
       //--- Will retrieve if there are any open trades
       bool              OpenTrade(ENUM_POSITION_TYPE Type,ulong Magic,string COMMENT=NULL);
       //--- Will retrieve if there are any deals
       bool              OpenedDeal(ENUM_DEAL_TYPE Type,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade
       bool              Buy(double SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade with integer SL
       bool              Buy(int SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade with integer TP
       bool              Buy(double SL,int TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open buy trade with integer SL & TP
       bool              Buy(int SL,int TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade
       bool              Sell(double SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade with integer SL
       bool              Sell(int SL,double TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade with integer TP
       bool              Sell(double SL,int TP,ulong Magic,string COMMENT=NULL);
       //--- Will attempt open sell trade with integer SL & TP
       bool              Sell(int SL,int TP,ulong Magic,string COMMENT=NULL);
      };

    以下の関数は、特定のポジションのタイプ(買い/売り)、マジック(ユニークフットプリント)、コメント(ポジションの詳細)を持つポジションを確認します。この関数を使用して、ニュースイベントが発生したときにすでに取引を開始しているかどうかを確認し、余分な取引や不要な取引をおこなわないようにします。

    //+------------------------------------------------------------------+
    //|Will retrieve if there are any open trades                        |
    //+------------------------------------------------------------------+
    bool CTradeManagement::OpenTrade(ENUM_POSITION_TYPE Type,ulong Magic,string COMMENT=NULL)
      {
    //--- Iterate through all open positions
       for(int i=0; i<PositionsTotal(); i++)
         {
          //--- Check if Position ticket is above zero
          if(PositionGetTicket(i)>0)
            {
             //--- Check if the Position's Symbol,Magic,Type,Comment is correct
             if(PositionGetString(POSITION_SYMBOL)==CSymbol.GetSymbolName()&&PositionGetInteger(POSITION_MAGIC)==Magic
                &&PositionGetInteger(POSITION_TYPE)==Type&&PositionGetString(POSITION_COMMENT)==COMMENT)
               {
                //--- Return true when there is an open position
                return true;
               }
            }
         }
    //--- No open positions found.
       return false;
      }

    OpenedDeal関数は、開かれた取引(開かれた売買取引)があるかどうかを確認します。この関数は、ニュースイベント中に取引がクローズされたときに、自分たち/EAが新しい取引を開始するのを防ぐために必要です。この関数がないと、例えばNFP(非農業部門雇用者数)の発表直前にEAが買い注文を開いてしまう可能性があります。もしボラティリティの影響でそのポジションがクローズされた場合、EAが新たな注文を再度開くことは避けたいです。なぜなら、すでにイベントに対して取引をおこなっているため、追加の取引は不要であり、無駄な損失を招く可能性があるからです。 

    //+------------------------------------------------------------------+
    //|Will retrieve if there are any deals                              |
    //+------------------------------------------------------------------+
    bool CTradeManagement::OpenedDeal(ENUM_DEAL_TYPE Type,ulong Magic,string COMMENT=NULL)
      {
    //--- Check History starting from 2 minutes ago
       if(HistorySelect(CTime.TimeMinusOffset(TimeTradeServer(),CTime.MinutesS(2)),TimeTradeServer()))
         {
          //--- Iterate through all history deals
          for(int i=0; i<HistoryDealsTotal(); i++)
            {
             //--- Assign history deal ticket
             ulong ticket = HistoryDealGetTicket(i);
             //--- Check if ticket is more than zero
             if(ticket>0)
               {
                //--- Check if the Deal's Symbol,Magic,Type,Comment is correct
                if(HistoryDealGetString(ticket,DEAL_SYMBOL)==CSymbol.GetSymbolName()&&
                   HistoryDealGetInteger(ticket,DEAL_MAGIC)==Magic&&HistoryDealGetInteger(ticket,DEAL_TYPE)==Type
                   &&HistoryDealGetString(ticket,DEAL_COMMENT)==COMMENT)
                  {
                   //--- Return true when there are any deals
                   return true;
                  }
               }
            }
         }
    //--- No deals found.
       return false;
      }

    以下の関数は、買い(ロング)のすべての成行注文を出します。

    //+------------------------------------------------------------------+
    //|Will attempt open buy trade                                       |
    //+------------------------------------------------------------------+
    bool CTradeManagement::Buy(double SL,double TP,ulong Magic,string COMMENT=NULL)
      {
    //--- Normalize the SL Price
       CSymbol.NormalizePrice(SL);
    //--- Normalize the TP Price
       CSymbol.NormalizePrice(TP);
    //--- Set the order type for Risk management calculation
       SetOrderType(ORDER_TYPE_BUY);
    //--- Set open price for Risk management calculation
       OpenPrice = CSymbol.Ask();
    //--- Set close price for Risk management calculation
       ClosePrice = SL;
    //--- Set Trade magic number
       Trade.SetExpertMagicNumber(Magic);
    //--- Check if there are any open trades or opened deals already
       if(!OpenTrade(POSITION_TYPE_BUY,Magic,COMMENT)&&!OpenedDeal(DEAL_TYPE_BUY,Magic,COMMENT))
         {
          //--- Iterate through the Lot-sizes if they're more than max-lot
          for(double i=Volume();i>=CSymbol.LotsMin();i-=CSymbol.LotsMax())
            {
             //--- normalize Lot-size
             NormalizeLotsize(i);
             //--- Open trade with a Lot-size not more than max-lot
             TradeResult = Trade.Buy((i>CSymbol.LotsMax())?CSymbol.LotsMax():i,CSymbol.GetSymbolName(),CSymbol.Ask(),SL,TP,COMMENT);
             //--- Check if trade failed.
             if(!TradeResult)
               {
                return TradeResult;
               }
            }
         }
       else
         {
          //--- Trade failed because there is an open trade or opened deal
          return false;
         }
    //--- Return trade result.
       return TradeResult;
      }

    以下の関数は、売り(ショート)のすべての成行注文を出します。

    //+------------------------------------------------------------------+
    //|Will attempt open sell trade                                      |
    //+------------------------------------------------------------------+
    bool CTradeManagement::Sell(double SL,double TP,ulong Magic,string COMMENT=NULL)
      {
    //--- Normalize the SL Price
       CSymbol.NormalizePrice(SL);
    //--- Normalize the TP Price
       CSymbol.NormalizePrice(TP);
    //--- Set the order type for Risk management calculation
       SetOrderType(ORDER_TYPE_SELL);
    //--- Set open price for Risk management calculation
       OpenPrice = CSymbol.Bid();
    //--- Set close price for Risk management calculation
       ClosePrice = SL;
    //--- Set Trade magic number
       Trade.SetExpertMagicNumber(Magic);
    //--- Check if there are any open trades or opened deals already
       if(!OpenTrade(POSITION_TYPE_SELL,Magic,COMMENT)&&!OpenedDeal(DEAL_TYPE_SELL,Magic,COMMENT))
         {
          //--- Iterate through the Lot-sizes if they're more than max-lot
          for(double i=Volume();i>=CSymbol.LotsMin();i-=CSymbol.LotsMax())
            {
             //--- normalize Lot-size
             NormalizeLotsize(i);
             //--- Open trade with a Lot-size not more than max-lot
             TradeResult = Trade.Sell((i>CSymbol.LotsMax())?CSymbol.LotsMax():i,CSymbol.GetSymbolName(),CSymbol.Bid(),SL,TP,COMMENT);
             //--- Check if trade failed.
             if(!TradeResult)
               {
                return TradeResult;
               }
            }
         }
       else
         {
          //--- Trade failed because there is an open trade or opened deal
          return false;
         }
    //--- Return trade result.
       return TradeResult;
      }


    ニュース取引EA

    EAのために新しい入力を用意しており、「はじめに」ですでに説明済みです。

    //--- width and height of the canvas (used for drawing)
    #define IMG_WIDTH  200
    #define IMG_HEIGHT 100
    //--- enable to set color format
    ENUM_COLOR_FORMAT clr_format=COLOR_FORMAT_XRGB_NOALPHA;
    //--- drawing array (buffer)
    uint ExtImg[IMG_WIDTH*IMG_HEIGHT];
    
    #include "News.mqh"
    CNews NewsObject;//Class object for News
    #include "TimeManagement.mqh"
    CTimeManagement CTM;//Class object for Time Management
    #include "WorkingWithFolders.mqh"
    CFolders Folder;//Class object for Folders
    #include "ChartProperties.mqh"
    CChartProperties Chart;//Class object for Chart Properties
    #include "RiskManagement.mqh"
    CRiskManagement CRisk;//Class object for Risk Management
    #include "CommonGraphics.mqh"
    CCommonGraphics *CGraphics;//Class pointer object for Common Graphics
    CCandleProperties *CP;//Class pointer object for Candle Properties
    #include "TradeManagement.mqh"
    CTradeManagement Trade;//Class object for Trade Management
    
    //--- used to separate Input Menu
    enum iSeparator
      {
       Delimiter//__________________________
      };
    
    //--- for chart color Mode selection
    enum DisplayMode
      {
       Display_LightMode,//LIGHT MODE
       Display_DarkMode//DARK MODE
      };
    
    sinput group "+--------|   DISPLAY   |--------+";
    sinput DisplayMode iDisplayMode=Display_LightMode;//CHART COLOUR MODE
    sinput Choice iDisplay_NewsInfo=Yes;//DISPLAY NEWS INFO
    sinput Choice iDisplay_EventObj=Yes;//DISPLAY EVENT OBJ
    sinput Choice iDisplay_Spread=Yes;//DISPLAY SPREAD RATING
    sinput Choice iDisplay_Date=Yes;//DISPLAY DATE
    sinput group "";
    sinput group "+--------|   DST SCHEDULE   |--------+";
    input DSTSchedule ScheduleDST=AutoDst_Selection;//SELECT DST OPTION
    sinput iSeparator iCustomSchedule=Delimiter;//__________________________
    sinput iSeparator iCustomScheduleL=Delimiter;//CUSTOM DST
    input DST_type CustomSchedule=DST_NONE;//SELECT CUSTOM DST
    sinput group "";
    sinput group "+--------| RISK MANAGEMENT |--------+";
    input RiskOptions RISK_Type=MINIMUM_LOT;//SELECT RISK OPTION
    input RiskFloor RISK_Mini=RiskFloorMin;//RISK FLOOR
    input double RISK_Mini_Percent=75;//MAX-RISK [100<-->0.01]%
    input RiskCeil  RISK_Maxi=RiskCeilMax;//RISK CEILING
    sinput iSeparator iRisk_1=Delimiter;//__________________________
    sinput iSeparator iRisk_1L=Delimiter;//PERCENTAGE OF [BALANCE | FREE-MARGIN]
    input double Risk_1_PERCENTAGE=3;//[100<-->0.01]%
    sinput iSeparator iRisk_2=Delimiter;//__________________________
    sinput iSeparator iRisk_2L=Delimiter;//AMOUNT PER [BALANCE | FREE-MARGIN]
    input double Risk_2_VALUE=1000;//[BALANCE | FREE-MARGIN]
    input double Risk_2_AMOUNT=10;//EACH AMOUNT
    sinput iSeparator iRisk_3=Delimiter;//__________________________
    sinput iSeparator iRisk_3L=Delimiter;//LOTSIZE PER [BALANCE | FREE-MARGIN]
    input double Risk_3_VALUE=1000;//[BALANCE | FREE-MARGIN]
    input double Risk_3_LOTSIZE=0.1;//EACH LOTS(VOLUME)
    sinput iSeparator iRisk_4=Delimiter;//__________________________
    sinput iSeparator iRisk_4L=Delimiter;//CUSTOM LOTSIZE
    input double Risk_4_LOTSIZE=0.01;//LOTS(VOLUME)
    sinput iSeparator iRisk_5=Delimiter;//__________________________
    sinput iSeparator iRisk_5L=Delimiter;//PERCENTAGE OF MAX-RISK
    input double Risk_5_PERCENTAGE=1;//[100<-->0.01]%
    sinput group "";
    sinput group "+--------| NEWS SETTINGS |--------+";
    input Calendar_Importance iImportance=Calendar_Importance_High;//CALENDAR IMPORTANCE
    input Event_Frequency iFrequency=Event_Frequency_ALL;//EVENT FREQUENCY
    input Event_Sector iSector=Event_Sector_ALL;//EVENT SECTOR
    input Event_Type iType=Event_Type_Indicator;//EVENT TYPE
    input Event_Currency iCurrency=Event_Currency_Symbol;//EVENT CURRENCY
    sinput group "";
    sinput group "+--------| TRADE SETTINGS |--------+";
    input uint iStoploss=500;//STOPLOSS [0=NONE]
    input uint iTakeprofit=500;//TAKEPROFIT [0=NONE]
    input uint iSecondsPreEvent=5;//PRE-ENTRY SEC
    input DayOfTheWeek TradingDay=AllDays;//TRADING DAY OF WEEK
    sinput group "";
    //--- to keep track of start-up time
    datetime Startup_date;

    以下の整数型OnInit関数では、ストラテジーテスターであろうとなかろうと、EAが取引できるように設定する際のさまざまな手順を説明します。

    //+------------------------------------------------------------------+
    //| Expert initialization function                                   |
    //+------------------------------------------------------------------+
    int OnInit()
      {
    //--- Assign if in LightMode or not
       isLightMode=(iDisplayMode==Display_LightMode)?true:false;
    //--- call function for common initialization procedure
       InitCommon();
    //--- store Init result
       int InitResult;
       if(!MQLInfoInteger(MQL_TESTER))//Checks whether the program is in the strategy tester
         {
          //--- initialization procedure outside strategy tester
          InitResult=InitNonTester();
         }
       else
         {
          //--- initialization procedure inside strategy tester
          InitResult=InitTester();
         }
    //--- Create DB in memory
       NewsObject.CreateEconomicDatabaseMemory();
    //--- Initialize Common graphics class pointer object
       CGraphics = new CCommonGraphics(Answer(iDisplay_Date),Answer(iDisplay_Spread),Answer(iDisplay_NewsInfo),Answer(iDisplay_EventObj));
       CGraphics.GraphicsRefresh(iSecondsPreEvent);//-- Create chart objects
    //--- Initialize Candle properties pointer object
       CP = new CCandleProperties();
    //--- Store start-up time.
       Startup_date = TimeTradeServer();
    //--- return Init result
       return InitResult;
      }

    以下の関数では、ストラテジーテスターと通常の取引環境の両方のプロパティを初期化しています。

    //+------------------------------------------------------------------+
    //|function for common initialization procedure                      |
    //+------------------------------------------------------------------+
    void InitCommon()
      {
    //Initializing CRiskManagement variable for Risk options
       RiskProfileOption = RISK_Type;
    //Initializing CRiskManagement variable for Risk floor
       RiskFloorOption = RISK_Mini;
    //Initializing CRiskManagement variable for RiskFloorMax
       RiskFloorPercentage = (RISK_Mini_Percent>100)?100:
                             (RISK_Mini_Percent<0.01)?0.01:RISK_Mini_Percent;//Percentage cannot be more than 100% or less than 0.01%
    //Initializing CRiskManagement variable for Risk ceiling
       RiskCeilOption = RISK_Maxi;
    //Initializing CRiskManagement variable for Risk options (PERCENTAGE OF BALANCE and PERCENTAGE OF FREE-MARGIN)
       Risk_Profile_1 = (Risk_1_PERCENTAGE>100)?100:
                        (Risk_1_PERCENTAGE<0.01)?0.01:Risk_1_PERCENTAGE;//Percentage cannot be more than 100% or less than 0.01%
    //Initializing CRiskManagement variables for Risk options (AMOUNT PER BALANCE and AMOUNT PER FREE-MARGIN)
       Risk_Profile_2.RiskAmountBoF = Risk_2_VALUE;
       Risk_Profile_2.RiskAmount = Risk_2_AMOUNT;
    //Initializing CRiskManagement variables for Risk options (LOTSIZE PER BALANCE and LOTSIZE PER FREE-MARGIN)
       Risk_Profile_3.RiskLotBoF = Risk_3_VALUE;
       Risk_Profile_3.RiskLot = Risk_3_LOTSIZE;
    //Initializing CRiskManagement variable for Risk option (CUSTOM LOTSIZE)
       Risk_Profile_4 = Risk_4_LOTSIZE;
    //Initializing CRiskManagement variable for Risk option (PERCENTAGE OF MAX-RISK)
       Risk_Profile_5 = (Risk_5_PERCENTAGE>100)?100:
                        (Risk_5_PERCENTAGE<0.01)?0.01:Risk_5_PERCENTAGE;//Percentage cannot be more than 100% or less than 0.01%
    //--- Initializing DST Schedule variables
       MyDST = ScheduleDST;
       MySchedule = CustomSchedule;
    //--- Initializing News filter variables
       myFrequency=iFrequency;
       myImportance=iImportance;
       mySector=iSector;
       myType=iType;
       myCurrency=iCurrency;
       Chart.ChartRefresh();//Load chart configurations
      }

    以下の関数は、通常の取引環境でのみ初期化されます。

    //+------------------------------------------------------------------+
    //|function for initialization procedure outside strategy tester     |
    //+------------------------------------------------------------------+
    int InitNonTester()
      {
    //--- Check if in Strategy tester!
       if(MQLInfoInteger(MQL_TESTER))
         {
          //--- Initialization failed.
          return(INIT_SUCCEEDED);
         }
    //--- create OBJ_BITMAP_LABEL object for drawing
       ObjectCreate(0,"STATUS",OBJ_BITMAP_LABEL,0,0,0);
       ObjectSetInteger(0,"STATUS",OBJPROP_XDISTANCE,5);
       ObjectSetInteger(0,"STATUS",OBJPROP_YDISTANCE,22);
    //--- specify the name of the graphical resource
       ObjectSetString(0,"STATUS",OBJPROP_BMPFILE,"::PROGRESS");
       uint   w,h;          // variables for receiving text string sizes
       uint    x,y;          // variables for calculation of the current coordinates of text string anchor points
       /*
       In the Do while loop below, the code will check if the terminal is connected to the internet.
       If the the program is stopped the loop will break, if the program is not stopped and the terminal
       is connected to the internet the function CreateEconomicDatabase will be called from the News.mqh header file's
       object called NewsObject and the loop will break once called.
       */
       bool done=false;
       do
         {
          //--- clear the drawing buffer array
          ArrayFill(ExtImg,0,IMG_WIDTH*IMG_HEIGHT,0);
    
          if(!TerminalInfoInteger(TERMINAL_CONNECTED))
            {
             //-- integer dots used as a loading animation
             static int dots=0;
             //--- set the font
             TextSetFont("Arial",-150,FW_EXTRABOLD,0);
             TextGetSize("Waiting",w,h);//get text width and height values
             //--- calculate the coordinates of the 'Waiting' text
             x=10;//horizontal alignment
             y=IMG_HEIGHT/2-(h/2);//alignment for the text to be centered vertically
             //--- output the 'Waiting' text to ExtImg[] buffer
             TextOut("Waiting",x,y,TA_LEFT|TA_TOP,ExtImg,IMG_WIDTH,IMG_HEIGHT,ColorToARGB(CSymbol.Background()),clr_format);
             //--- calculate the coordinates for the dots after the 'Waiting' text
             x=w+13;//horizontal alignment
             y=IMG_HEIGHT/2-(h/2);//alignment for the text to be centered vertically
             TextSetFont("Arial",-160,FW_EXTRABOLD,0);
             //--- output of dots to ExtImg[] buffer
             TextOut(StringSubstr("...",0,dots),x,y,TA_LEFT|TA_TOP,ExtImg,IMG_WIDTH,IMG_HEIGHT,ColorToARGB(CSymbol.Background()),clr_format);
             //--- update the graphical resource
             ResourceCreate("::PROGRESS",ExtImg,IMG_WIDTH,IMG_HEIGHT,0,0,IMG_WIDTH,clr_format);
             //--- force chart update
             Chart.Redraw();
             dots=(dots==3)?0:dots+1;
             //-- Notify user that program is waiting for connection
             Print("Waiting for connection...");
             Sleep(500);
             continue;
            }
          else
            {
             //--- set the font
             TextSetFont("Arial",-120,FW_EXTRABOLD,0);
             TextGetSize("Getting Ready",w,h);//get text width and height values
             x=20;//horizontal alignment
             y=IMG_HEIGHT/2-(h/2);//alignment for the text to be centered vertically
             //--- output the text 'Getting Ready...' to ExtImg[] buffer
             TextOut("Getting Ready...",x,y,TA_LEFT|TA_TOP,ExtImg,IMG_WIDTH,IMG_HEIGHT,ColorToARGB(CSymbol.Background()),clr_format);
             //--- update the graphical resource
             ResourceCreate("::PROGRESS",ExtImg,IMG_WIDTH,IMG_HEIGHT,0,0,IMG_WIDTH,clr_format);
             //--- force chart update
             Chart.Redraw();
             //-- Notify user that connection is successful
             Print("Connection Successful!");
             NewsObject.CreateEconomicDatabase();//calling the database create function
             done=true;
            }
         }
       while(!done&&!IsStopped());
    //-- Delete chart object
       ObjectDelete(0,"STATUS");
    //-- force chart to update
       Chart.Redraw();
    //--- Initialization succeeded.
       return(INIT_SUCCEEDED);
      }

    以下の関数は、ストラテジーテスター環境のみの初期化をおこないます。

    //+------------------------------------------------------------------+
    //|function for initialization procedure inside strategy tester      |
    //+------------------------------------------------------------------+
    int InitTester()
      {
    //--- Check if not in Strategy tester!
       if(!MQLInfoInteger(MQL_TESTER))
         {
          //--- Initialization failed.
          return(INIT_SUCCEEDED);
         }
    //Checks whether the database file exists
       if(!FileIsExist(NEWS_DATABASE_FILE,FILE_COMMON))
         {
          //--- Warning messages
          Print("Necessary Files Do not Exist!");
          Print("Run Program outside of the Strategy Tester");
          Print("Necessary Files Should be Created First");
          //--- Initialization failed.
          return(INIT_FAILED);
         }
       else
         {
          //Checks whether the latest database date includes the time and date being tested
          datetime latestdate = CTM.TimeMinusOffset(NewsObject.GetLatestNewsDate(),CTM.DaysS());//Day before the latest recorded time in the database
          if(latestdate<TimeTradeServer())
            {
             Print("Necessary Files outdated!");
             Print("To Update Files: Run Program outside of the Strategy Tester");
            }
          Print("Database Dates End at: ",latestdate);
          PrintFormat("Dates after %s will not be available for backtest",TimeToString(latestdate));
         }
    //--- Initialization succeeded.
       return(INIT_SUCCEEDED);
      }

    以下の関数は新しいティックごとに実行されます。

    //+------------------------------------------------------------------+
    //| Expert tick function                                             |
    //+------------------------------------------------------------------+
    void OnTick()
      {
    //--- Run procedures
       Execution();
      }

    以下の関数では、EAを機能させるためのすべての関数を呼び出します。すべての関数がすべてのティックで実行される必要はないので、特定の関数を新しい特定のローソク足(例えば日足のローソク足)ごとにのみ呼び出します。これにより、パフォーマンスが向上し、不要な関数呼び出しやリソースの使用が減ります。

    //+------------------------------------------------------------------+
    //|Execute program procedures                                        |
    //+------------------------------------------------------------------+
    void Execution()
      {
    //--- Update realtime Graphic every 1 min
       if(CP.NewCandle(1,PERIOD_M1))
         {
          CGraphics.Block_2_Realtime(iSecondsPreEvent);
         }
    //--- function to open trades
       EnterTrade();
    //--- Check if not start-up date
       if(!CTM.DateisToday(Startup_date))
         {
          //--- Run every New Daily Candle
          if(CP.NewCandle(2,PERIOD_D1))
            {
             //--- Check if not in strategy tester
             if(!MQLInfoInteger(MQL_TESTER))
               {
                //--- Update/Create DB in Memory
                NewsObject.CreateEconomicDatabaseMemory();
               }
             CGraphics.GraphicsRefresh(iSecondsPreEvent);//-- Create/Re-create chart objects
             //--- Update Realtime Graphics
             CGraphics.Block_2_Realtime(iSecondsPreEvent);
            }
          //--- Check if not in strategy tester
          if(!MQLInfoInteger(MQL_TESTER))
            {
             //--- Run every New Hourly Candle
             if(CP.NewCandle(3,PERIOD_H1))
               {
                //--- Check if DB in Storage needs an update
                if(NewsObject.UpdateRecords())
                  {
                   //--- initialization procedure outside strategy tester
                   InitNonTester();
                  }
               }
            }
         }
       else
         {
          //--- Run every New Daily Candle
          if(CP.NewCandle(4,PERIOD_D1))
            {
             //--- Update Event objects on chart
             CGraphics.NewsEvent();
            }
         }
      }

    以下の関数は、イベント影響とイベント通貨に基づく成行注文の取引開始を担当します。イベント通貨が利益通貨と等しく、影響タイプがCALENDAR_IMPACT_NEGATIVEである場合、利益通貨がニュースイベント中に弱まると仮定して買い注文を開きます。逆に、イベント通貨が利益通貨と等しく、影響タイプがCALENDAR_IMPACT_POSITIVEである場合は、利益通貨が強まると仮定して売り注文を開きます。 

    //+------------------------------------------------------------------+
    //|function to open trades                                           |
    //+------------------------------------------------------------------+
    void EnterTrade()
      {
    //--- static variable for storing upcoming event Impact value
       static ENUM_CALENDAR_EVENT_IMPACT Impact=CALENDAR_IMPACT_NA;
    //--- Check if Upcoming news date has passed and if upcoming news is not null and if new minute candle has formed.
       if(datetime(UpcomingNews.EventDate)<TimeTradeServer()&&UpcomingNews.CountryName!=NULL&&CP.NewCandle(5,PERIOD_M1))
         {
          //--- Update for next upcoming news
          NewsObject.EconomicNextEvent();
          //--- Get impact value for upcoming news
          Impact=NewsObject.GetImpact();
         }
    //--- Check if upcoming news date is about to occur and if it is the trading day of week
       if(CTM.TimePreEvent(CTM.TimeMinusOffset(datetime(UpcomingNews.EventDate),(iSecondsPreEvent==0)?1:iSecondsPreEvent)
                           ,datetime(UpcomingNews.EventDate))
          &&CTM.isDayOfTheWeek(TradingDay))
         {
          //--- Check each Impact value type
          switch(Impact)
            {
             //--- When Impact news is negative
             case CALENDAR_IMPACT_NEGATIVE:
                //--- Check if profit currency is news event currency
                if(UpcomingNews.EventCurrency==CSymbol.CurrencyProfit())
                  {
                   //--- Open buy trade with Event id as Magic number
                   Trade.Buy(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                else
                  {
                   //--- Open sell trade with Event id as Magic number
                   Trade.Sell(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                break;
             //--- When Impact news is positive
             case CALENDAR_IMPACT_POSITIVE:
                //--- Check if profit currency is news event currency
                if(UpcomingNews.EventCurrency==CSymbol.CurrencyProfit())
                  {
                   //--- Open sell trade with Event id as Magic number
                   Trade.Sell(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                else
                  {
                   //--- Open buy trade with Event id as Magic number
                   Trade.Buy(iStoploss,iTakeprofit,ulong(UpcomingNews.EventId),"NewsTrading");
                  }
                break;
             //--- Unknown
             default:
                break;
            }
         }
      }


    結論

    この記事では、メモリ内にデータベースを追加し、MQL5経済指標カレンダーのイベントに関する詳細情報を提供するための追加ビューを作成する方法を解説しました。今後のイベント情報を表示するために、チャート上に追加のグラフィカルオブジェクトを作成し、ダークモード機能も実装しました。さらに、ユーザーやトレーダーの好みに応じてニュースデータをフィルタリングするための関連入力オプションや、取引用のEA入力も追加しています。また、この記事では、イベントの影響に基づいた成行注文の出し方や、イベントの影響が取引戦略にどのように関連しているかについても説明しました。

    ご意見をお聞かせいただければ幸いです。次回は、ニュース入力にさらなる機能を追加し、個別の経済イベントや、より柔軟なペンディングオーダーによる取引、さらにはイベントインパクトを必要としない取引に対応する予定です。ご精読ありがとうございました。



    ビデオ




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

    添付されたファイル |
    NewsTrading_Part3.zip (567.27 KB)
    古典的な戦略を再構築する(第4回):SP500と米財務省中期証券 古典的な戦略を再構築する(第4回):SP500と米財務省中期証券
    この連載では、最新のアルゴリズムを用いて古典的な取引戦略を分析し、AIによって戦略を改善できるかどうかを検証します。本日の記事では、SP500と米財務省中期証券との関係を活用した古典的な取引手法を再考します。
    Candlestick Trend Constraintモデルの構築(第8回):エキスパートアドバイザーの開発 (I) Candlestick Trend Constraintモデルの構築(第8回):エキスパートアドバイザーの開発 (I)
    今回は、前回の記事で作成した指標を元に、MQL5で最初のエキスパートアドバイザー(EA)を作成します。リスク管理を含め、取引プロセスを自動化するために必要な全機能を紹介します。これにより、手動の取引執行から自動化されたシステムへとスムーズに移行できるメリットがあります。
    MQL5における動的時間伸縮を用いたパターン認識 MQL5における動的時間伸縮を用いたパターン認識
    本稿では、金融時系列における予測パターンを特定する手段として、動的時間伸縮の概念について論じます。その仕組みと、純粋なMQL5での実装を紹介します。
    MQL5の統合:Python MQL5の統合:Python
    Pythonは、特に金融、データサイエンス、人工知能、機械学習の分野で多くの特徴を持つ、よく知られた人気のプログラミング言語です。また、Pythonは取引にも有効な強力なツールです。MQL5では、この強力な言語を統合して使用することで、目的を効果的に達成することができます。本記事では、Pythonの基本的な情報を学んだ後、MQL5でPythonを統合して使用する方法を紹介します。