//+------------------------------------------------------------------+
//|                                                   NewBarDemo.mq5 |
//|                                     冏掉的Alan羅  orzalanluo.com |
//+------------------------------------------------------------------+
#property copyright "orzalanluo.com"
#property link      "https://orzalanluo.com"
#property version   "1.00"
#property description "MT5 教學：自己寫 struct 與 class（只印不下單）"

//=== 1. struct：把幾個值綁成一包 ====================================
struct BarStat
{
   int      count;                    // 觸發了幾次
   datetime last;                     // 最後一次是哪根 K 線
};

//=== 2. class：資料和方法放在一起 ===================================
class CNewBar
{
private:
   string          m_Symbol;          // 商品
   ENUM_TIMEFRAMES m_Period;          // 週期
   datetime        m_LastBar;         // 上次看到的 K 線開盤時間

public:
                   CNewBar(string symbol, ENUM_TIMEFRAMES period);
                  ~CNewBar();
   bool            IsNew();           // 本體寫在類別外面
   datetime        LastBar() { return m_LastBar; }
   string          Name()             // PERIOD_H1 取出 H1
   {
      return m_Symbol + " " + StringSubstr(EnumToString(m_Period), 7);
   }
};

//=== 3. 方法寫在類別外面：類別名:: ==================================
bool CNewBar::IsNew()
{
   datetime t = iTime(m_Symbol, m_Period, 0);   // 這根的開盤時間
   if(t == 0 || t == m_LastBar)                 // 0＝資料還沒到
      return false;
   m_LastBar = t;
   return true;
}

//=== 4. 建構子與解構子 ==============================================
CNewBar::CNewBar(string symbol, ENUM_TIMEFRAMES period)
   : m_Symbol(symbol), m_Period(period), m_LastBar(0)
{
   Print("建構 ", Name());
}

CNewBar::~CNewBar()
{
   Print("解構 ", Name());
}

//=== 5. 一個類別，兩個物件 ==========================================
CNewBar g_H1(_Symbol, PERIOD_H1);
CNewBar g_H4(_Symbol, PERIOD_H4);
BarStat g_StatH1 = {0, 0};
BarStat g_StatH4 = {0, 0};

int OnInit()
{
   Print("OnInit");
   return INIT_SUCCEEDED;
}

void OnTick()
{
   if(g_H1.IsNew())
      Count(g_H1, g_StatH1);
   if(g_H4.IsNew())
      Count(g_H4, g_StatH4);
}

void Count(CNewBar &bar, BarStat &stat)   // 物件、結構要加 &
{
   stat.count++;
   stat.last = bar.LastBar();
   Print(bar.Name(), " 新 K 線 ", TimeToString(stat.last),
         "  第 ", stat.count, " 次");
}

void OnDeinit(const int reason)
{
   Print("OnDeinit");
   Summary(g_H1, g_StatH1);
   Summary(g_H4, g_StatH4);
}

void Summary(CNewBar &bar, BarStat &stat)
{
   Print(bar.Name(), " 共 ", stat.count, " 次，最後一根 ",
         TimeToString(stat.last));
}
//+------------------------------------------------------------------+
