Подскажите, как заставить эту машину работать?
Каждый когда приходит тик, необходимо сдвигать весь буфер на 1 назад и в первый элемент ставить значение Bid+size*_Point
То есть это должна быть кривая линия которая обновляется на каждом тике
Но рисуется непонятно что, такое чувство что это работает на каждый бар, а не тик
Ниже пример кода
Код неверный, нельзя задавать размер индикаторного буфера, это прерогатива рантайма МТ4/5. Посмотрите, как устроены стандартные индикаторы.
ArrayResize(buff, 50); // ошибка ArrayInitialize(buff, 0);
**
Спасибо за ссылку. Первая мысль у меня была попробовать решить эту задачу с помощью ArrayCopy. плохая мысль.
Это единственно правильная мысль.
Мало того, что PLOT_SHIFT не документирован, так еще и представленный индикатор будет создавать видимость рабочего только некоторое время.
Это единственно правильная мысль.
Мало того, что PLOT_SHIFT не документирован, так еще и представленный индикатор будет создавать видимость рабочего только некоторое время.
Когда и если будет необходимость, проверю оба варианта. Спасибо за мнение.
На мой взгляд, копирование массива на каждом тике - неверное направление.
В теории-то все правильно, но слишком медленно.
Я бы сделал указатель, и на каждом тике бы наращивал его, с добавлением значения. А доступ к значениям - сделал бы "обратным". Ну и обернул бы все в класс, чтобы "снаружи" это выглядело, как буффер со сдвигом на каждом тике.
На мой взгляд, копирование массива на каждом тике - неверное направление.
В теории-то все правильно, но слишком медленно.
Я бы сделал указатель, и на каждом тике бы наращивал его, с добавлением значения. А доступ к значениям - сделал бы "обратным". Ну и обернул бы все в класс, чтобы "снаружи" это выглядело, как буффер со сдвигом на каждом тике.
Попробуйте сделать. Результат будет интересен даже без ООП.
Попробуйте сделать. Результат будет интересен даже без ООП.
Да чего там делать ? Есть у меня все это.
Вот, пожалуйста, .MQH:
/* CQueueT - класс-шаблон, представляющий собой очередь Элементы добавляются в хвост очереди, и могут быть удалены с головы очереди. Если при добавлении происходит переполнение, то элемент с головы исчезает. */ #include <MyLib\Common\MyObject.mqh> template <typename T> class CQueueT:public CMyObject { protected: T m_atObjects[]; uint m_uiMaxQueueSize; uint m_uiDataSize; int m_iTailPointer; // Указатель на "хвост" очереди (на последний,самый новый элемент). Число со знаком, поскольку при расчете индекса оно может быть меньше нуля. public: CQueueT(); ~CQueueT() {}; // Функция выделяет память для очереди, и подготавливает ее к принятию первого значения. bool Init(uint uiMaxQueueSize); uint GetQueueSize() { return(m_uiDataSize); }; // Доступ к объектам очереди T GetObjectFromHead(uint uiIdxFromHead = 0) const; // Возврат объекта, находящегося в очереди по индексу uiIdxFromHead от "головы" очереди (от самого старого элемента), сам объект не удаляется T GetObjectFromTail(uint uiIdxFromTail = 0) const; // Возврат объекта с хвоста очереди, сам объект не удаляется // Добавление объекта в "хвост" очереди со смещением всех предыдущих со смещением всех предыдущих к "голове" очереди. // Объект, для которого не оказывается места удаляется. // Если размер очереди увеличился - функция возвращает true. Если размер не изменился (самый старый объект был удален) - false. // NOTE !!! // Передача просто объекта - в темплейтах не выходит, потому, в общем случае - структуры не могут передаваться по значению. // Поэтому - приходится передавать по ссылке, в том числе и для простых типов. bool AddToTail(T & tObject); // Удалени объекта, находящегося на голове очереди (самого старого). // Если это возможно - возвращается true, и удаленный объект передается в параметр tObject // Если это невозможно - возвращается false. bool RemoveFromHead(T & tObject); };
К нему - еще и .MQ5 файл:
#property library #include <MyLib\DebugOrRelease\DebugSupport.mqh> #include <MyLib\Arrays\QueueT.mqh> template<typename T> CQueueT::CQueueT() { SetMyObjectType(MOT_QUEUE_T); m_uiMaxQueueSize = 0; m_uiDataSize = 0; m_iTailPointer = INT_MAX; }; template<typename T> bool CQueueT::Init(uint uiMaxQueueSize) { ASSERT(uiMaxQueueSize > 0); int iResSize = ArrayResize(m_atObjects,uiMaxQueueSize); if(iResSize != uiMaxQueueSize) return(false); m_uiMaxQueueSize = uiMaxQueueSize; m_uiDataSize = 0; m_iTailPointer = INT_MAX; return(true); }; template<typename T> bool CQueueT::AddToTail(T & tObject) { ASSERT(m_uiMaxQueueSize > 0); ASSERT(ArraySize(m_atObjects) == m_uiMaxQueueSize); if(m_uiDataSize == 0) { m_iTailPointer = 0; m_atObjects[0] = tObject; m_uiDataSize = 1; return(true); }; ASSERT(m_uiDataSize <= m_uiMaxQueueSize); ASSERT(m_iTailPointer < (int)m_uiMaxQueueSize); bool bRes = false; ++m_iTailPointer; if(m_iTailPointer == (int)m_uiMaxQueueSize) m_iTailPointer = 0; if(m_uiDataSize<m_uiMaxQueueSize) { ++m_uiDataSize; bRes = true; }; m_atObjects[m_iTailPointer] = tObject; return(bRes); }; template<typename T> T CQueueT::GetObjectFromHead(uint uiIdxFromHead) const { ASSERT(m_uiDataSize > 0); ASSERT(uiIdxFromHead < m_uiDataSize); ASSERT(m_uiDataSize <= m_uiMaxQueueSize); ASSERT(m_iTailPointer < (int)m_uiMaxQueueSize); int iResPointer = m_iTailPointer-(int)m_uiDataSize+(int)uiIdxFromHead+1; if(iResPointer<0) iResPointer += (int)m_uiDataSize; else if(iResPointer >= (int)m_uiDataSize) iResPointer -= (int)m_uiDataSize; return(m_atObjects[iResPointer]); }; template<typename T> T CQueueT::GetObjectFromTail(uint uiIdxFromTail) const { ASSERT(m_uiDataSize > 0); ASSERT(uiIdxFromTail < m_uiDataSize); ASSERT(m_uiDataSize <= m_uiMaxQueueSize); ASSERT(m_iTailPointer < (int)m_uiMaxQueueSize); int iResPointer = m_iTailPointer-(int)uiIdxFromTail; if(iResPointer<0) iResPointer += (int)m_uiDataSize; return(m_atObjects[iResPointer]); }; template<typename T> bool CQueueT::RemoveFromHead(T & tObject) { ASSERT(m_uiDataSize <= m_uiMaxQueueSize); ASSERT(m_iTailPointer < (int)m_uiMaxQueueSize); if(m_uiDataSize == 0) return(false); int iHeadPointer = m_iTailPointer-(int)m_uiDataSize+1; if(iHeadPointer<0) iHeadPointer += (int)m_uiDataSize; tObject = m_atObjects[iHeadPointer]; --m_uiDataSize; if(m_uiDataSize == 0) m_iTailPointer = INT_MAX; return(true); };
Это очередь.
Все работает - именно так, как я и предлагаю. Добавляем в хвост очереди тики (можно прямо структуру MQLTickInfo), берем данные с головы очереди. Причем, если очередь переполняется, то исчезает элемент "с головы" (на его место просто записывается новый "хвостовой" элемент. Формально, мы добавляем в хвост элементы, и весь массив "сдвигаем вверх", к "голове". Но физически - мы дописываем лишь только новый "хвостовой" элемент, копирование всего массива при этом - не происходит.
Этот код не очень оттестирован, но работает вроде нормально. Думаю, можно рекомендовать к использованию (удалив несколько специфичных для моей библиотеки строк)
Все работает - именно так, как я и предлагаю.
Где тиковый индикатор?
Я про индикатор ничего не говорил. Я говорил, что копировать весь массив для сдвига представляется неразумным. Куда правильнее дописывать данные, а сдвиг осуществлять с помощью указателей. Мой класс CQueueT это и делает.
Чтобы получить индкатор - надо последнее значение из очереди (или сколько там будет надо, в зависимости от параметра prev_calculated - копировать в индикаторный массив.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Подскажите, как заставить эту машину работать?
Каждый когда приходит тик, необходимо сдвигать весь буфер на 1 назад и в первый элемент ставить значение Bid+size*_Point
То есть это должна быть кривая линия которая обновляется на каждом тике
Но рисуется непонятно что, такое чувство что это работает на каждый бар, а не тик
Ниже пример кода