HYROLEAN

hyrIQueue.mqh

Mar 17th, 2026 (edited)
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.41 KB | Money | 0 0
  1. // hyrIQueue.mqh for MT5 - インジケータ用順列クラス
  2. //   by Copyright 2026 hyrolean
  3. //---------------------------------------------------------------------------
  4. // Local:: <DataFolder>\MQL5\Include\User\hyrIQueue.mqh
  5. // URL:: https://pastebin.com/3pRKTce4
  6. //---------------------------------------------------------------------------
  7. //+------------------------------------------------------------------+
  8. //| 半自動生成ヘッダーファイル by Claude                             |
  9. //+------------------------------------------------------------------+
  10. //| hyrIQueue.mqh                                                    |
  11. //| CHyrIQueue / CHyrIQueueMA / CHyrIQueueATR                        |
  12. //|                                                                  |
  13. //| 設計方針:                                                        |
  14. //|  - CHyrIQueue  : CopyBuffer + fixed_queue の共通ロジックを内包   |
  15. //|  - CHyrIQueueMA    : iMA ハンドルを作って CHyrIQueue::Init() に渡す |
  16. //|  - CHyrIQueueATR   : iATR ハンドルを作って CHyrIQueue::Init() に渡す |
  17. //|                                                                  |
  18. //| 将来の拡張例:                                                    |
  19. //|  class CHyrIQueueRSI : public CHyrIQueue {                       |
  20. //|     bool Init(...) {                                             |
  21. //|        int h = iRSI(...);                                        |
  22. //|        return CHyrIQueue::Init(h, queueSize);                    |
  23. //|     }                                                            |
  24. //|  };                                                              |
  25. //+------------------------------------------------------------------+
  26. #ifndef HYR_I_QUEUE_MQH
  27. #define HYR_I_QUEUE_MQH
  28.  
  29. #include <User/hyrGlobal.mqh>  // https://pastebin.com/2PdBW6NQ
  30. #include <User/hyrQueue.mqh>  // https://pastebin.com/X1N3nEB4
  31.  
  32. //+------------------------------------------------------------------+
  33. //| CHyrIQueue                                                       |
  34. //| 指標ハンドルから CopyBuffer でデータを取得し、                   |
  35. //| fixed_queue に蓄えるベースクラス。                               |
  36. //| ハンドルの作成は派生クラスの Init() で行い、                     |
  37. //| CHyrIQueue::Init() にハンドル値を渡して初期化する。              |
  38. //+------------------------------------------------------------------+
  39. class CHyrIQueue
  40. {
  41. protected:
  42.    fixed_queue<double> queue_;          // 値を蓄える循環バッファ
  43.    int                 handle_;         // 指標ハンドル
  44.    bool                handleInherited_; // 指標ハンドル継承可否
  45.    int                 bufferIndex_;    // CopyBuffer のバッファ番号
  46.    int                 shiftIndex_;     // 履歴開始の起点シフト位置
  47.    datetime            lastTime_;       // 最後に処理したバーの時刻
  48.    string              symbol_;         // 対象シンボル
  49.    ENUM_TIMEFRAMES     period_;         // 対象時間軸
  50.    bool                initialized_;    // 初期化済みフラグ
  51.  
  52. public:
  53.    //--- コンストラクタ(Init()前はダミーサイズ)
  54.    CHyrIQueue(bool handleInherited=true)
  55.       : queue_(1), handle_(INVALID_HANDLE), bufferIndex_(0), shiftIndex_(0),
  56.         lastTime_(0), initialized_(false), handleInherited_(handleInherited) {}
  57.  
  58.    //--- デストラクタ
  59.    ~CHyrIQueue()
  60.    {
  61.       if(handleInherited_) {
  62.         if(handle_ != INVALID_HANDLE)
  63.            IndicatorRelease(handle_);
  64.       }
  65.    }
  66.  
  67.    //-------------------------------------------------------------------
  68.    // 基底クラスの初期化
  69.    // 派生クラスの Init() が iMA/iATR 等でハンドルを作り、
  70.    // このメソッドを呼び出す。
  71.    //
  72.    // handle      : 派生クラスが作った指標ハンドル
  73.    // symbol      : 対象シンボル
  74.    // period      : 対象時間軸
  75.    // queueSize   : キューに保持するバー数
  76.    // bufferIndex : CopyBuffer のバッファ番号(省略時=0)
  77.    //-------------------------------------------------------------------
  78.    bool Init(int handle, string symbol, ENUM_TIMEFRAMES period,
  79.              int queueSize, int bufferIndex = 0, int shiftIndex = -1)
  80.    {
  81.       if(handle == INVALID_HANDLE) {
  82.          PrintMessage("handle の値が不正","CHyrIQueue::Init()");
  83.          return false;
  84.       }
  85.  
  86.       handle_      = handle;
  87.       symbol_      = symbol;
  88.       period_      = period;
  89.       bufferIndex_ = bufferIndex;
  90.  
  91.       //--- 過去バーを一括投入
  92.       int si = shiftIndex<0 ? shiftIndex_ : shiftIndex ;
  93.       if(!LoadHistory_(queueSize,si)) return false;
  94.       shiftIndex_ = si;
  95.  
  96.       initialized_ = true;
  97.       return true;
  98.    }
  99.  
  100.    //-------------------------------------------------------------------
  101.    // OnTick() から毎回呼ぶ
  102.    // lastTime_ 以降の新バー分だけ値を取得してキューに追加する
  103.    //-------------------------------------------------------------------
  104.    bool Update()
  105.    {
  106.       if(!initialized_) return false;
  107.  
  108.       datetime currentTime = iTime(symbol_, period_, shiftIndex_);
  109.       if(currentTime == 0)      return false;
  110.       //if(currentTime == lastTime_) return true; // 新バーなし ← これはマズイ
  111.  
  112.       //--- 差分バー数を計算
  113.       int rdBars = Bars(symbol_, period_, lastTime_, currentTime) + (queue_.empty()?-1:0) ;
  114.       if(rdBars <= 0) return true;
  115.  
  116.       //--- 新バー分を取得
  117.       double buf[];
  118.       ArraySetAsSeries(buf, true);
  119.       if(CopyBuffer(handle_, bufferIndex_, shiftIndex_, rdBars, buf) != rdBars) {
  120.          PrintMessage("CopyBuffer 失敗: "+IntegerToString(GetLastError())
  121.            ,"CHyrIQueue::Update()");
  122.          return false;
  123.       }
  124.  
  125.       //--- 新バーがなくても、最新値を常に更新するように追加修正 by hyrolean
  126.       if(!queue_.empty()&&rdBars>0) {
  127.         queue_.set(0,buf[rdBars-1]);
  128.         rdBars--; // この分は減らしておく
  129.       }
  130.  
  131.       //--- 古い順(末尾から)キューに追加、溢れた分は pop
  132.       for(int i = rdBars - 1; i >= 0; i--) {
  133.          if(queue_.full()) queue_.pop();
  134.          queue_.push(buf[i]);
  135.       }
  136.  
  137.       lastTime_ = currentTime;
  138.       return true;
  139.    }
  140.  
  141.    // 履歴開始の起点シフト位置の更新 ( by hyrolean )
  142.    bool UpdateShift(int newShiftIndex) {
  143.      if(newShiftIndex<0) return false ;
  144.      if(!initialized_) {
  145.        shiftIndex_ = newShiftIndex; // シフト位置の事前設定
  146.        return true;
  147.      }
  148.      datetime currentTime = iTime(symbol_, period_, shiftIndex_);
  149.      if(currentTime!=lastTime_) {
  150.        if(!Update()) // タイム値を正確にするため一旦更新しておく
  151.          return false ;
  152.      }
  153.      if(newShiftIndex<shiftIndex_) { // 後方を起点に更新
  154.        int nShift = shiftIndex_-newShiftIndex;
  155.        if(nShift>=queue_.capacity()) { // 現行キューのキャパオーバー位置にシフト
  156.          // 履歴のリロード処理
  157.          int numBars = iBars(symbol_, period_);
  158.          int nHistory = MathMin(numBars-newShiftIndex,queue_.capacity());
  159.          if(!LoadHistory_(nHistory,newShiftIndex)) return false ;
  160.        }
  161.        shiftIndex_ = newShiftIndex ; // Ok
  162.      }else { // 前方を起点に更新
  163.        int nShift = newShiftIndex-shiftIndex_;
  164.        if(size()>=nShift) { // 現行キューの範囲内に収まる
  165.          for(int i=0;i<nShift;i++) queue_.pop(); // シフトした分だけ排除
  166.        }else { // 現行キューの範囲外
  167.          // 履歴のリロード処理
  168.          int numBars = iBars(symbol_, period_);
  169.          if(numBars<=newShiftIndex) return false ; // バー限界数を超えている
  170.          int nHistory = MathMin(numBars-newShiftIndex,queue_.capacity());
  171.          if(!LoadHistory_(nHistory,newShiftIndex)) return false ;
  172.        }
  173.        shiftIndex_ = newShiftIndex; // Ok
  174.      }
  175.      // 最後に更新
  176.      return Update();
  177.    }
  178.  
  179.    //-------------------------------------------------------------------
  180.    // アクセサ
  181.    //-------------------------------------------------------------------
  182.  
  183.    //--- 相対位置の値(0=最新相対位置、1=1本前、…)
  184.    double operator[](int index) const
  185.    {
  186.       int i = queue_.size() - 1 - index ;
  187.       if(i < 0 || i >= queue_.size()) {
  188.          PrintMessage("range error. index="+IntegerToString(index)
  189.            ,"CHyrIQueue::operator[]");
  190.          return 0.0;
  191.       }
  192.       return queue_[i];
  193.    }
  194.  
  195.    //--- 絶対位置の値(0=最新絶対位置、1=1本前、…)
  196.    double sv(int shifted_index) // shifted value
  197.    {
  198.       if(!is_range(shifted_index)) UpdateShift(shifted_index);
  199.       return operator[](shifted_index-shiftIndex_) ;
  200.    }
  201.  
  202.    int  capacity()    const { return queue_.capacity(); }
  203.    int  size()        const { return queue_.size(); }
  204.    bool empty()       const { return queue_.empty(); }
  205.    bool initialized() const { return initialized_; }
  206.  
  207.    //--- 範囲チェック
  208.    bool is_range(int shifted_index) const
  209.    { return shiftIndex_+size()>shifted_index && shifted_index>=shiftIndex_; }
  210.  
  211.    //--- 最新値([0]の糖衣構文)
  212.    double latest() const { return operator[](0); }
  213.  
  214.    //--- 1本前の値([1]の糖衣構文)
  215.    double prev()   const { return operator[](1); }
  216.  
  217.    //--- 遷移 shift_index / last_time
  218.    int shift_index()    const { return shiftIndex_ ; }
  219.    datetime last_time() const { return lastTime_ ; }
  220.  
  221. private:
  222.    //-------------------------------------------------------------------
  223.    // 過去バーを一括投入(Init() 内部から呼ぶ)
  224.    //-------------------------------------------------------------------
  225.    bool LoadHistory_(int queueSize,int si=0)
  226.    {
  227.       //--- データが揃うまでリトライ
  228.       double tmp[];
  229.       int retry = 0;
  230.       while(CopyBuffer(handle_, bufferIndex_, si, queueSize, tmp) != queueSize) {
  231.          if(++retry > 50) {
  232.             PrintMessage("データ取得タイムアウト"
  233.               ,"CHyrIQueue::LoadHistory_()");
  234.             return false;
  235.          }
  236.          Sleep(100);
  237.       }
  238.  
  239.       /*
  240.       //--- 古い順にキューへ push
  241.       ArraySetAsSeries(tmp, true); // tmp[0]=最新
  242.       for(int i = queueSize - 1; i >= 0; i--)
  243.          queue_.push(tmp[i]);
  244.       */
  245.  
  246.       //--- キューを入れ替える(modified by hyrolean)
  247.       ArraySetAsSeries(tmp, false); // 最初のデータが一番古い順に並べ替え
  248.       fixed_queue<double> queue_tmp(tmp,true/*入れ替えx1*/);
  249.       queue_.swap(queue_tmp) ; // 入れ替えx2
  250.  
  251.       lastTime_ = iTime(symbol_, period_, si);
  252.       return true;
  253.    }
  254. };
  255.  
  256. //+------------------------------------------------------------------+
  257. //| CHyrIQueueMA                                                           |
  258. //| iMA ハンドルを作って CHyrIQueue::Init() に渡す派生クラス。         |
  259. //+------------------------------------------------------------------+
  260. class CHyrIQueueMA : public CHyrIQueue
  261. {
  262. public:
  263.    //-------------------------------------------------------------------
  264.    // 初期化
  265.    // symbol       : 通貨ペア
  266.    // period       : 時間軸
  267.    // maPeriod     : MAの期間
  268.    // maMethod     : MODE_SMA / MODE_EMA / MODE_SMMA / MODE_LWMA
  269.    // appliedPrice : PRICE_CLOSE 等
  270.    // queueSize    : キューに保持するバー数
  271.    //-------------------------------------------------------------------
  272.    bool Init(string             symbol,
  273.              ENUM_TIMEFRAMES    period,
  274.              int                maPeriod,
  275.              ENUM_MA_METHOD     maMethod,
  276.              ENUM_APPLIED_PRICE appliedPrice,
  277.              int                queueSize)
  278.    {
  279.       int handle = iMA(symbol, period, maPeriod, 0, maMethod, appliedPrice);
  280.       if(handle == INVALID_HANDLE) {
  281.          PrintMessage("CHyrIQueueMA::Init() - iMA handle 作成失敗: "
  282.            + IntegerToString(GetLastError()));
  283.          return false;
  284.       }
  285.       return CHyrIQueue::Init(handle, symbol, period, queueSize);
  286.    }
  287. };
  288.  
  289. //+------------------------------------------------------------------+
  290. //| CHyrIQueueATR                                                          |
  291. //| iATR ハンドルを作って CHyrIQueue::Init() に渡す派生クラス。        |
  292. //+------------------------------------------------------------------+
  293. class CHyrIQueueATR : public CHyrIQueue
  294. {
  295. public:
  296.    //-------------------------------------------------------------------
  297.    // 初期化
  298.    // symbol    : 通貨ペア
  299.    // period    : 時間軸
  300.    // atrPeriod : ATRの期間
  301.    // queueSize : キューに保持するバー数
  302.    //-------------------------------------------------------------------
  303.    bool Init(string          symbol,
  304.              ENUM_TIMEFRAMES period,
  305.              int             atrPeriod,
  306.              int             queueSize)
  307.    {
  308.       int handle = iATR(symbol, period, atrPeriod);
  309.       if(handle == INVALID_HANDLE) {
  310.          Print("CHyrIQueueATR::Init() - iATR handle 作成失敗: "
  311.            + IntegerToString(GetLastError()));
  312.          return false;
  313.       }
  314.       return CHyrIQueue::Init(handle, symbol, period, queueSize);
  315.    }
  316. };
  317.  
  318. // CHyrIQueueRSI (追加 by hyrolean)
  319. class CHyrIQueueRSI : public CHyrIQueue
  320. {
  321. public:
  322.   bool Init(string symbol, ENUM_TIMEFRAMES period,
  323.               int rsiPeriod, ENUM_APPLIED_PRICE price, int queueSize) {
  324.        int handle = iRSI(symbol, period, rsiPeriod, price);
  325.        if(handle == INVALID_HANDLE) {
  326.          Print("CHyrIQueueRSI::Init() - iRSI handle 作成失敗: "
  327.            + IntegerToString(GetLastError()));
  328.          return false;
  329.        }
  330.        return CHyrIQueue::Init(handle, symbol, period, queueSize);
  331.   }
  332. };
  333.  
  334. #endif // HYR_I_QUEUE_MQH
  335.  
  336. //+------------------------------------------------------------------+
  337. //| 使用例                                                            |
  338. //+------------------------------------------------------------------+
  339. /*
  340.  
  341. #include <User/hyrIQueue.mqh>
  342.  
  343. CHyrIQueueMA  gFastMA, gMediumMA, gSlowMA;
  344. CHyrIQueueATR gATR;
  345.  
  346. int OnInit()
  347. {
  348.    int qsize = 50;
  349.    if(!gFastMA.Init  (_Symbol, PERIOD_CURRENT, 10, MODE_EMA, PRICE_CLOSE, qsize)) return INIT_FAILED;
  350.    if(!gMediumMA.Init(_Symbol, PERIOD_CURRENT, 20, MODE_EMA, PRICE_CLOSE, qsize)) return INIT_FAILED;
  351.    if(!gSlowMA.Init  (_Symbol, PERIOD_CURRENT, 50, MODE_EMA, PRICE_CLOSE, qsize)) return INIT_FAILED;
  352.    if(!gATR.Init     (_Symbol, PERIOD_CURRENT, 14, qsize))                        return INIT_FAILED;
  353.    return INIT_SUCCEEDED;
  354. }
  355.  
  356. void OnTick()
  357. {
  358.    gFastMA.Update();
  359.    gMediumMA.Update();
  360.    gSlowMA.Update();
  361.    gATR.Update();
  362.  
  363.    double fastMA   = gFastMA[0];    // 最新 Fast MA
  364.    double mediumMA = gMediumMA[0];  // 最新 Medium MA
  365.    double slowMA   = gSlowMA[0];    // 最新 Slow MA
  366.    double atr14    = gATR[0];       // 最新 ATR(14)
  367.    double atrPrev  = gATR[1];       // 1本前 ATR(14)
  368. }
  369.  
  370. // 将来の拡張例(RSI):
  371. //
  372. // class CHyrIQueueRSI : public CHyrIQueue {
  373. // public:
  374. //    bool Init(string symbol, ENUM_TIMEFRAMES period,
  375. //              int rsiPeriod, ENUM_APPLIED_PRICE price, int queueSize) {
  376. //       int handle = iRSI(symbol, period, rsiPeriod, price);
  377. //       if(handle == INVALID_HANDLE) return false;
  378. //       return CHyrIQueue::Init(handle, symbol, period, queueSize);
  379. //    }
  380. // };
  381.  
  382. */
  383. //+------------------------------------------------------------------+
  384.  
Tags: Mt5
Advertisement
Add Comment
Please, Sign In to add comment