Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // hyrIQueue.mqh for MT5 - インジケータ用順列クラス
- // by Copyright 2026 hyrolean
- //---------------------------------------------------------------------------
- // Local:: <DataFolder>\MQL5\Include\User\hyrIQueue.mqh
- // URL:: https://pastebin.com/3pRKTce4
- //---------------------------------------------------------------------------
- //+------------------------------------------------------------------+
- //| 半自動生成ヘッダーファイル by Claude |
- //+------------------------------------------------------------------+
- //| hyrIQueue.mqh |
- //| CHyrIQueue / CHyrIQueueMA / CHyrIQueueATR |
- //| |
- //| 設計方針: |
- //| - CHyrIQueue : CopyBuffer + fixed_queue の共通ロジックを内包 |
- //| - CHyrIQueueMA : iMA ハンドルを作って CHyrIQueue::Init() に渡す |
- //| - CHyrIQueueATR : iATR ハンドルを作って CHyrIQueue::Init() に渡す |
- //| |
- //| 将来の拡張例: |
- //| class CHyrIQueueRSI : public CHyrIQueue { |
- //| bool Init(...) { |
- //| int h = iRSI(...); |
- //| return CHyrIQueue::Init(h, queueSize); |
- //| } |
- //| }; |
- //+------------------------------------------------------------------+
- #ifndef HYR_I_QUEUE_MQH
- #define HYR_I_QUEUE_MQH
- #include <User/hyrGlobal.mqh> // https://pastebin.com/2PdBW6NQ
- #include <User/hyrQueue.mqh> // https://pastebin.com/X1N3nEB4
- //+------------------------------------------------------------------+
- //| CHyrIQueue |
- //| 指標ハンドルから CopyBuffer でデータを取得し、 |
- //| fixed_queue に蓄えるベースクラス。 |
- //| ハンドルの作成は派生クラスの Init() で行い、 |
- //| CHyrIQueue::Init() にハンドル値を渡して初期化する。 |
- //+------------------------------------------------------------------+
- class CHyrIQueue
- {
- protected:
- fixed_queue<double> queue_; // 値を蓄える循環バッファ
- int handle_; // 指標ハンドル
- bool handleInherited_; // 指標ハンドル継承可否
- int bufferIndex_; // CopyBuffer のバッファ番号
- int shiftIndex_; // 履歴開始の起点シフト位置
- datetime lastTime_; // 最後に処理したバーの時刻
- string symbol_; // 対象シンボル
- ENUM_TIMEFRAMES period_; // 対象時間軸
- bool initialized_; // 初期化済みフラグ
- public:
- //--- コンストラクタ(Init()前はダミーサイズ)
- CHyrIQueue(bool handleInherited=true)
- : queue_(1), handle_(INVALID_HANDLE), bufferIndex_(0), shiftIndex_(0),
- lastTime_(0), initialized_(false), handleInherited_(handleInherited) {}
- //--- デストラクタ
- ~CHyrIQueue()
- {
- if(handleInherited_) {
- if(handle_ != INVALID_HANDLE)
- IndicatorRelease(handle_);
- }
- }
- //-------------------------------------------------------------------
- // 基底クラスの初期化
- // 派生クラスの Init() が iMA/iATR 等でハンドルを作り、
- // このメソッドを呼び出す。
- //
- // handle : 派生クラスが作った指標ハンドル
- // symbol : 対象シンボル
- // period : 対象時間軸
- // queueSize : キューに保持するバー数
- // bufferIndex : CopyBuffer のバッファ番号(省略時=0)
- //-------------------------------------------------------------------
- bool Init(int handle, string symbol, ENUM_TIMEFRAMES period,
- int queueSize, int bufferIndex = 0, int shiftIndex = -1)
- {
- if(handle == INVALID_HANDLE) {
- PrintMessage("handle の値が不正","CHyrIQueue::Init()");
- return false;
- }
- handle_ = handle;
- symbol_ = symbol;
- period_ = period;
- bufferIndex_ = bufferIndex;
- //--- 過去バーを一括投入
- int si = shiftIndex<0 ? shiftIndex_ : shiftIndex ;
- if(!LoadHistory_(queueSize,si)) return false;
- shiftIndex_ = si;
- initialized_ = true;
- return true;
- }
- //-------------------------------------------------------------------
- // OnTick() から毎回呼ぶ
- // lastTime_ 以降の新バー分だけ値を取得してキューに追加する
- //-------------------------------------------------------------------
- bool Update()
- {
- if(!initialized_) return false;
- datetime currentTime = iTime(symbol_, period_, shiftIndex_);
- if(currentTime == 0) return false;
- //if(currentTime == lastTime_) return true; // 新バーなし ← これはマズイ
- //--- 差分バー数を計算
- int rdBars = Bars(symbol_, period_, lastTime_, currentTime) + (queue_.empty()?-1:0) ;
- if(rdBars <= 0) return true;
- //--- 新バー分を取得
- double buf[];
- ArraySetAsSeries(buf, true);
- if(CopyBuffer(handle_, bufferIndex_, shiftIndex_, rdBars, buf) != rdBars) {
- PrintMessage("CopyBuffer 失敗: "+IntegerToString(GetLastError())
- ,"CHyrIQueue::Update()");
- return false;
- }
- //--- 新バーがなくても、最新値を常に更新するように追加修正 by hyrolean
- if(!queue_.empty()&&rdBars>0) {
- queue_.set(0,buf[rdBars-1]);
- rdBars--; // この分は減らしておく
- }
- //--- 古い順(末尾から)キューに追加、溢れた分は pop
- for(int i = rdBars - 1; i >= 0; i--) {
- if(queue_.full()) queue_.pop();
- queue_.push(buf[i]);
- }
- lastTime_ = currentTime;
- return true;
- }
- // 履歴開始の起点シフト位置の更新 ( by hyrolean )
- bool UpdateShift(int newShiftIndex) {
- if(newShiftIndex<0) return false ;
- if(!initialized_) {
- shiftIndex_ = newShiftIndex; // シフト位置の事前設定
- return true;
- }
- datetime currentTime = iTime(symbol_, period_, shiftIndex_);
- if(currentTime!=lastTime_) {
- if(!Update()) // タイム値を正確にするため一旦更新しておく
- return false ;
- }
- if(newShiftIndex<shiftIndex_) { // 後方を起点に更新
- int nShift = shiftIndex_-newShiftIndex;
- if(nShift>=queue_.capacity()) { // 現行キューのキャパオーバー位置にシフト
- // 履歴のリロード処理
- int numBars = iBars(symbol_, period_);
- int nHistory = MathMin(numBars-newShiftIndex,queue_.capacity());
- if(!LoadHistory_(nHistory,newShiftIndex)) return false ;
- }
- shiftIndex_ = newShiftIndex ; // Ok
- }else { // 前方を起点に更新
- int nShift = newShiftIndex-shiftIndex_;
- if(size()>=nShift) { // 現行キューの範囲内に収まる
- for(int i=0;i<nShift;i++) queue_.pop(); // シフトした分だけ排除
- }else { // 現行キューの範囲外
- // 履歴のリロード処理
- int numBars = iBars(symbol_, period_);
- if(numBars<=newShiftIndex) return false ; // バー限界数を超えている
- int nHistory = MathMin(numBars-newShiftIndex,queue_.capacity());
- if(!LoadHistory_(nHistory,newShiftIndex)) return false ;
- }
- shiftIndex_ = newShiftIndex; // Ok
- }
- // 最後に更新
- return Update();
- }
- //-------------------------------------------------------------------
- // アクセサ
- //-------------------------------------------------------------------
- //--- 相対位置の値(0=最新相対位置、1=1本前、…)
- double operator[](int index) const
- {
- int i = queue_.size() - 1 - index ;
- if(i < 0 || i >= queue_.size()) {
- PrintMessage("range error. index="+IntegerToString(index)
- ,"CHyrIQueue::operator[]");
- return 0.0;
- }
- return queue_[i];
- }
- //--- 絶対位置の値(0=最新絶対位置、1=1本前、…)
- double sv(int shifted_index) // shifted value
- {
- if(!is_range(shifted_index)) UpdateShift(shifted_index);
- return operator[](shifted_index-shiftIndex_) ;
- }
- int capacity() const { return queue_.capacity(); }
- int size() const { return queue_.size(); }
- bool empty() const { return queue_.empty(); }
- bool initialized() const { return initialized_; }
- //--- 範囲チェック
- bool is_range(int shifted_index) const
- { return shiftIndex_+size()>shifted_index && shifted_index>=shiftIndex_; }
- //--- 最新値([0]の糖衣構文)
- double latest() const { return operator[](0); }
- //--- 1本前の値([1]の糖衣構文)
- double prev() const { return operator[](1); }
- //--- 遷移 shift_index / last_time
- int shift_index() const { return shiftIndex_ ; }
- datetime last_time() const { return lastTime_ ; }
- private:
- //-------------------------------------------------------------------
- // 過去バーを一括投入(Init() 内部から呼ぶ)
- //-------------------------------------------------------------------
- bool LoadHistory_(int queueSize,int si=0)
- {
- //--- データが揃うまでリトライ
- double tmp[];
- int retry = 0;
- while(CopyBuffer(handle_, bufferIndex_, si, queueSize, tmp) != queueSize) {
- if(++retry > 50) {
- PrintMessage("データ取得タイムアウト"
- ,"CHyrIQueue::LoadHistory_()");
- return false;
- }
- Sleep(100);
- }
- /*
- //--- 古い順にキューへ push
- ArraySetAsSeries(tmp, true); // tmp[0]=最新
- for(int i = queueSize - 1; i >= 0; i--)
- queue_.push(tmp[i]);
- */
- //--- キューを入れ替える(modified by hyrolean)
- ArraySetAsSeries(tmp, false); // 最初のデータが一番古い順に並べ替え
- fixed_queue<double> queue_tmp(tmp,true/*入れ替えx1*/);
- queue_.swap(queue_tmp) ; // 入れ替えx2
- lastTime_ = iTime(symbol_, period_, si);
- return true;
- }
- };
- //+------------------------------------------------------------------+
- //| CHyrIQueueMA |
- //| iMA ハンドルを作って CHyrIQueue::Init() に渡す派生クラス。 |
- //+------------------------------------------------------------------+
- class CHyrIQueueMA : public CHyrIQueue
- {
- public:
- //-------------------------------------------------------------------
- // 初期化
- // symbol : 通貨ペア
- // period : 時間軸
- // maPeriod : MAの期間
- // maMethod : MODE_SMA / MODE_EMA / MODE_SMMA / MODE_LWMA
- // appliedPrice : PRICE_CLOSE 等
- // queueSize : キューに保持するバー数
- //-------------------------------------------------------------------
- bool Init(string symbol,
- ENUM_TIMEFRAMES period,
- int maPeriod,
- ENUM_MA_METHOD maMethod,
- ENUM_APPLIED_PRICE appliedPrice,
- int queueSize)
- {
- int handle = iMA(symbol, period, maPeriod, 0, maMethod, appliedPrice);
- if(handle == INVALID_HANDLE) {
- PrintMessage("CHyrIQueueMA::Init() - iMA handle 作成失敗: "
- + IntegerToString(GetLastError()));
- return false;
- }
- return CHyrIQueue::Init(handle, symbol, period, queueSize);
- }
- };
- //+------------------------------------------------------------------+
- //| CHyrIQueueATR |
- //| iATR ハンドルを作って CHyrIQueue::Init() に渡す派生クラス。 |
- //+------------------------------------------------------------------+
- class CHyrIQueueATR : public CHyrIQueue
- {
- public:
- //-------------------------------------------------------------------
- // 初期化
- // symbol : 通貨ペア
- // period : 時間軸
- // atrPeriod : ATRの期間
- // queueSize : キューに保持するバー数
- //-------------------------------------------------------------------
- bool Init(string symbol,
- ENUM_TIMEFRAMES period,
- int atrPeriod,
- int queueSize)
- {
- int handle = iATR(symbol, period, atrPeriod);
- if(handle == INVALID_HANDLE) {
- Print("CHyrIQueueATR::Init() - iATR handle 作成失敗: "
- + IntegerToString(GetLastError()));
- return false;
- }
- return CHyrIQueue::Init(handle, symbol, period, queueSize);
- }
- };
- // CHyrIQueueRSI (追加 by hyrolean)
- class CHyrIQueueRSI : public CHyrIQueue
- {
- public:
- bool Init(string symbol, ENUM_TIMEFRAMES period,
- int rsiPeriod, ENUM_APPLIED_PRICE price, int queueSize) {
- int handle = iRSI(symbol, period, rsiPeriod, price);
- if(handle == INVALID_HANDLE) {
- Print("CHyrIQueueRSI::Init() - iRSI handle 作成失敗: "
- + IntegerToString(GetLastError()));
- return false;
- }
- return CHyrIQueue::Init(handle, symbol, period, queueSize);
- }
- };
- #endif // HYR_I_QUEUE_MQH
- //+------------------------------------------------------------------+
- //| 使用例 |
- //+------------------------------------------------------------------+
- /*
- #include <User/hyrIQueue.mqh>
- CHyrIQueueMA gFastMA, gMediumMA, gSlowMA;
- CHyrIQueueATR gATR;
- int OnInit()
- {
- int qsize = 50;
- if(!gFastMA.Init (_Symbol, PERIOD_CURRENT, 10, MODE_EMA, PRICE_CLOSE, qsize)) return INIT_FAILED;
- if(!gMediumMA.Init(_Symbol, PERIOD_CURRENT, 20, MODE_EMA, PRICE_CLOSE, qsize)) return INIT_FAILED;
- if(!gSlowMA.Init (_Symbol, PERIOD_CURRENT, 50, MODE_EMA, PRICE_CLOSE, qsize)) return INIT_FAILED;
- if(!gATR.Init (_Symbol, PERIOD_CURRENT, 14, qsize)) return INIT_FAILED;
- return INIT_SUCCEEDED;
- }
- void OnTick()
- {
- gFastMA.Update();
- gMediumMA.Update();
- gSlowMA.Update();
- gATR.Update();
- double fastMA = gFastMA[0]; // 最新 Fast MA
- double mediumMA = gMediumMA[0]; // 最新 Medium MA
- double slowMA = gSlowMA[0]; // 最新 Slow MA
- double atr14 = gATR[0]; // 最新 ATR(14)
- double atrPrev = gATR[1]; // 1本前 ATR(14)
- }
- // 将来の拡張例(RSI):
- //
- // class CHyrIQueueRSI : public CHyrIQueue {
- // public:
- // bool Init(string symbol, ENUM_TIMEFRAMES period,
- // int rsiPeriod, ENUM_APPLIED_PRICE price, int queueSize) {
- // int handle = iRSI(symbol, period, rsiPeriod, price);
- // if(handle == INVALID_HANDLE) return false;
- // return CHyrIQueue::Init(handle, symbol, period, queueSize);
- // }
- // };
- */
- //+------------------------------------------------------------------+
Advertisement
Add Comment
Please, Sign In to add comment