Тезис №1
Поскольку при вызове OnCalculate в качестве параметров по ссылке приходят огромные open, close, high, low, ..., то сразу следует вывод, что они не строятся для каждого вызова\индикатора отдельно, а хранятся где-то в уже готовом виде. Группа функций CopyXXX очень неповоротливая в тех случаях, когда приходится синхронизировать разные символы. Можно ли из скриптов и экспертов получить прямой доступ "на чтение" к внутренним массивам OHLCV ?
Вот конкретные задачи, которые мне не удается решить эффективно:
- нужно получить "срез" значений нескольких десятков индикаторов разных TF+Symbol на определенный момент времени
- нужно синхронно пройти по барам разных символов
- нужно получить информацию о наличии\отсутствии бара для валидного DateTime (валидность можно описать для каждого брокера отдельно, например, - открытие недели пн 01:00, закрытие пт 23:59, нерабочий день 1 янв, ...)
- www.mql5.com
Задача №2
Индикатор выполняет расчеты своих буферов по правилам, которые хранятся во внешнем файле. Чтобы было более понятно, поясню - внешняя программа проводит обучение нейросети и периодически сохраняет обновленную структуру в файл.
Индикатор должен следить за обновлениями и полностью пересчитываться в этом случае.
Небольшой нюанс)) : количество индикаторных буферов в общем случае заранее не известно (но не больше, скажем, N=500, хотя реально <50)
Имеет ли право на жизнь вот такая реализация ?
#property indicator_separate_window #property indicator_buffers 500 // На всякий случай )) #property indicator_plots 500 // функция для проверки даты изменения файла (в МТ5 ничего подобного не нашел) #import "FilesDll.dll" int FileAge(string &aFileName); #import input string File="New21.xml"; // Файл в котором хранятся кол-во буферов и правила расчета input string Path="C:\\Program Files\\MetaTrader 5\\MQL5\\Files\\"; struct CBuffer { // Не смог по-другому объявить двумерный массив всех буферов double Data[]; // только через массив структур, внутри которых лежит один динамический массив }; CBuffer Buffers[500]; // Массив потенциальных буферов индикатора int Modified=NULL; // Дата изменения загруженного файла сети int RatesTotal=0; // Копия OnCalculat'овских значений для работы из OnTimer'a int PrevCalculated=0; // bool IsFileModified() { // Проверка "изменился ли файл нейросетей с момента последнего обновления индикатора?" string filename=Path+File; int m=FileAge(filename); //Время изменения файла return((Modified==NULL) || (m!=Modified)); } int Init() { string filename=Path+File; Modified=FileAge(filename); PrevCalculated=0; // Вычитываем файл filename и запоминаем структуру // Весь расчет будет в объекте NetPool - коллекция загруженных из файла нейросетей // NetPool.FNets - количество нейросетей в файле = количество буферов для отрисовки for (int i=0; i<ArraySize(NetPool.FNets); i++) { // проходим по всем НОВЫМ буферам и переинициализируем их ArrayInitialize(Buffers[i].Data,EMPTY_VALUE); SetIndexBuffer(i,Buffers[i].Data,INDICATOR_DATA); ArraySetAsSeries(Buffers[i].Data,true); PlotIndexSetDouble(i,PLOT_EMPTY_VALUE,EMPTY_VALUE); PlotIndexSetString(i,PLOT_LABEL,NetPool.FNets[i].Label); PlotIndexSetInteger(i,PLOT_DRAW_TYPE, DRAW_LINE); PlotIndexSetInteger(i,PLOT_LINE_COLOR,LightGray); PlotIndexSetInteger(i,PLOT_LINE_STYLE,STYLE_SOLID); PlotIndexSetInteger(i,PLOT_LINE_WIDTH,1); }; }; void CalcBar (int bar, datetime dt) { // Загружаем "срез" значений индикаторов на дату dt double d[]; IndPool.LoadData(dt,d); // это набор индикаторов, которые дают входные данные для всех нейросетей из NetPool // Проводим расчет буферов для одного бара c номером bar for (int j=0; j<ArraySize(NetPool.FNets); j++) { NetPool.FNets[j].Run(d); Buffers[j].Data[bar]=NetPool.FNets[j].FNeurons[<...>].FValue; }; }; void Calc() { // Выполняем расчет для всех необходимых баров int count=RatesTotal-PrevCalculated-1; if (count<0) count=1; datetime time[]; ArraySetAsSeries(time,true); CopyTime(Symbol(),Period(),0,count,time); for (int i=0; i<count; i++) CalcBar(i,time[i]); PrevCalculated=RatesTotal; }; int OnInit() { EventSetTimer(10); Init(); return(0); } int OnCalculate (const int rates_total, // размер массива price[] const int prev_calculated, // обработано баров на предыдущем вызове const int begin, // откуда начинаются значимые данные const double& price[] // массив для расчета ) { RatesTotal=rates_total; PrevCalculated=prev_calculated; Calc(); return(PrevCalculated); } void OnTimer() { if (IsFileModified()) { Print ("Modified:"); Init(); Calc(); }; };
Основная идея "в двух словах":
вычисления значений буферов могут проводиться при возникновении двух видов событий OnCalculate и OnTimer. Поэтому инициализация (и реинициализация! корректно ли это???) вынесены в Init(), а расчет - в Calc() .
Init() может вызываться как из OnInit(), так и из OnTimer()
Calc() может вызываться как из OnCalculate(), так и из OnTimer()
------------------------------------------------------------------------------------
Вопрос скорее к разработчикам, нежели к пользователям MQL5:
нет ли в этой схеме каких-либо архитектурных нарушений индикаторной подсистемы МТ5?
Не совсем понятны особенности буферных индикаторов, потому и возникает этот вопрос.
да уж... как всё сложно...
Я предпочитаю легкие пути))) ... У меня одна нейросеть заменяет 100 различных сетей, расчёт нейросети происходит постоянно и поэтому выходной индикатор постоянно обновляет "правила" вычисления буферов. Отрисовку стремлюсь свести к одной линии, несколько линий служат как вспомогательные, поэтому 500 линий не реально в нейросети.... Ну и дальше в таком духе...
да уж... как всё сложно...
В данном случае это лишь пример для того чтобы более детально разобраться в возможностях "индикаторной технологии"
Можно ли из скриптов и экспертов получить прямой доступ "на чтение" к внутренним массивам OHLCV?
Размышления вслух о своих же вопросах...
Поскольку расчет индикаторов производится в "потоке окна", а эксперты и скрипты работают в отдельных потоках (где-то встречал такую информацию), то прямой доступ к массивам OHLCV может иметь лишь "поток окна", а остальные должны использовать потокобезопасные CopyXXX
И как следствие, ответом на вопрос будет - "технически" можно, но для пользователей нельзя, чтобы обеспечить целостность данных
Комментарий разработчика см. #
Вопрос №3
Как получить информацию об отсутствии бара для заданной точки времени?
В следующем примере запрашивается значение Ма21 для точки времени, которая попадает в воскресенье
int h=iMA(_Symbol,_Period,21,0,MODE_SMA,PRICE_CLOSE); if (h != INVALID_HANDLE) { double v[]; int r=CopyBuffer(h,0,D'2010.04.18',1,v); // 2010.04.18 - воскресенье }
В результате возвращается значение Ма21 для последнего бара пятницы, т.е. ближайшего бара слева
А если это "провал" в истории?
Поскольку расчет индикаторов производится в "потоке окна", а эксперты и скрипты работают в отдельных потоках (где-то встречал такую информацию), то прямой доступ к массивам OHLCV может иметь лишь "поток окна", а остальные должны использовать потокобезопасные CopyXXX
Расчет индикаторов в МТ5 не происходит в интерфейсном потоке.
У каждого символа есть отдельный динамический (включается по необходимости и отключается по бездействию) поток выполнения, в котором просчитываются все индикаторы, повешенные на графики по этому символу. То есть, расчет индикаторов на EURUSD идет параллельно расчету индикаторов на USDJPY и тд. Тем самым расчеты большинства индикаторов при активной работе терминала распараллеливаются и частично снимается проблема слишком медленных индикаторов (они тормозят лишь поток своего символа).
с ново ведением основного тайм фрема как м1 уже визуально можно проследить как считает индикатор
а при достаточно сложных расчетов с задейсвием множества буферов как вы говарите более мин 50 и получение с нескольких таймфреймов
генерация данных с тайм фрейма перераспределение данных и в конце концов сами вычисления это уже не мт4 со своими правилами и установленными тф
для таких сетей нужен очень мощный модуль облегчения пересчета и возможно даже внешная база данных в которой будут так сказать хранить пережованные данные и обращаться уже к ним
потомучто каждый раз при пересчете индикатора в котором больше 10 буферов, визуально можно видеть как заполняеться индикатор. а если брать инфу с других ТФ а мало того ещё с других символов
так ваше во время активной паники на рынке просто машина не будет успевать высчитывать.
в данном случае мне кажеться такой вопрос будет легко решить путем создание базы данных в которой данные будут храниться в необходимом вам формате.
и уже получать данные от туда проводя синхронизацию с некой переодичностью или даже лучше 1 программа проводит сбор информации и нейро сеть уже цепляеться на бд
CoreWinTT ,
В реальной торговле даже при самом худшем раскладе (ТФ=м1, на входе в НС сотни индикаторов от разных ТФ и Symbol) ничего страшного не произойдет - за минуту (с момента закрытия предпоследней свечи до закрытия текущей) один бар прекрасно обсчитается. Эксперты анализируют только закрытые свечи - иначе и быть не может.
Индикатор, о котором я писал выше, нужен мне для визуального контроля и тюнинга процесса обучения сети(-ей). Он используется на первых порах, - до тех пор, пока не накопится достаточного опыта, чтобы работать "по приборам". Более того, он работает, но как-то кривовато.
Целью этой темы является скорее желание разобраться в том "как все это устроено", чтобы в дальнейшем чувствовать себя свободно при написании индикаторов.
Скажите пожалуйста, кто уже разобрался в тонкостях мкл5..
сейчас индикатор такого типа : у меня отрисовывается прямоугольничками. Происходит это довольно долго, да и множество объектов притормаживает терминал. Можно ли в МТ5 оптимизировать отрисовку такого типа? в плане как скорости, так и нагрузки. Если да,то как (в общих чертах).
Спасибо
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
В процессе построения "продвинутых" индикаторов возникает немало вопросов. Многие из них не удается решить с помощью документации. Приходится проводить эксперименты вслепую - не зная внутреннего устройства индикаторной подсистемы МТ5.
Чтобы сэкономить время и силы программистов, предлагаю в этой теме собрать ЧаВо, который совместными усилиями должен превратиться в хороший мануал.
Приветствуется размещение ссылок на другие материалы, которые прямо или косвенно помогут решить возникшие вопросы и проблемы.