Интересное и Юмор - страница 5751

 

Задачу нужно тщательно формулировать.

 
Vitaly Murlenko #:

Скачал Cursor. Установил, авторизовался. Скормил ему папку с кодами. Он их увидел. Попытался дать команду на проверку корректности кода индикатора. Он мне ответил что я абзац как ошибся, и работать у меня он не будет. Предложил мне скопировать какой-то ключ.

Прошёлся по интерфейсу этой среды разработки. Всё на английском. Русского изначально не было. Непонятно вообще ни чего. Потыкался как слепой котёнок, да и удалил с компьютера. Ненавижу английский язык. Со школы у меня к нему глубокое отвращение. Для решения своих задач обойдусь без Курсора.

Юрий, забудьте о моих вопросах - не тратьте на меня время - буду работать по старинке. Не буду я учить иностранный язык - всё моё существо противится этому. У меня жена также само нос воротит от математических формул, зато Иняз закончила с успехом. А мне логика и математика нравится.

-- Виталий , понимаю!
Просто чуток информации может уже не для тебя , может кому то интересно.


Тут простой пример промта, где я пробую «вскормить» модель примерами. Я уже проделывал это ранее; сейчас лишь показываю как пример начального этапа.

У меня Cursor с оплаченной подпиской за 20 $ в месяц, поэтому лимитов нет.

---

Ты видишь мой проект D:\AI\MQL5 - тут лежат коды на моем любимом язфке MQL5 на котором создаются программы для Терминала MetaTrader5

мне нужно что бы посмотрел синтаксис и изучил его - читай все примеры из папки что бы понимать как правильно писать коды

язфке - такие опечатки ему не страшны - он понимает -по контексту )


 
Пишем промт

Напиши простой индикатор на MQL5 он должен брать брать последние 30 дневных свечей

вычислять средний дневной ход от лова до хая свечи и выводить это вверху экрана

обязательно подробнейшим образом закоментируй каждую строчку кода - каждый вызов внутренних функций MQL5

ты должна правильно найти нужные и правильный функции именно MQL5 для вычисления LOW HIGHT каждого дня

и взять среднюю дневного хода за последние 30 дней - включая 0-й бар тоже - я хочу видеть информацию в динамике


* что важно - обязательно используй

- учедник MQL5 который я положил D:\AI\MQL5\MQL5_RUSSIAN\mql5_russian.pdf

- активно пользуйся вот этой ссылкой https://www.mql5.com/ru/code/mt5 там можно найти примеры

- используй D:\AI\MQL5\MQL5_Syntax_Reference.md куда ты собрала описание синтаксиса

- https://www.mql5.com/ru/docs тут описание всех функций в понятном виде

----


итак прошло минуты 3-4



смотрим код:

//+------------------------------------------------------------------+
//|                                        YZ_AvgDailyRange30.mq5    |
//|                                  Автор: YuraZ                    |
//|  Средний дневной ход (High-Low) за последние N дневных свечей.   |
//|  Справка: https://www.mql5.com/ru/docs                           |
//|  Примеры: https://www.mql5.com/ru/code/mt5                       |
//|  Учебник: D:\\AI\\MQL5\\MQL5_RUSSIAN\\mql5_russian.pdf           |
//|  Синтаксис: MQL5_Syntax_Reference.md                             |
//+------------------------------------------------------------------+
#property copyright "YuraZ"
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- Описание индикатора (отображается в окне свойств при наведеении)
#property description "Средний дневной ход (High-Low) за последние N дней."
#property description "Данные берутся с таймфрейма D1. 0-й бар = текущий день (в динамике)."

//--- Индикатор рисуется в главном окне графика (не в отдельном подокне)
#property indicator_chart_window
//--- Индикатор не использует буферы для рисования линий — только текстовая метка вверху
#property indicator_buffers 0
#property indicator_plots   0

//--- Входной параметр: количество дневных свечей для расчёта среднего
//    Включая 0-й бар (текущий день) — значение обновляется в реальном времени
input int InpDays = 30;  // Количество дневных свечей (включая текущий день)

//--- Имя объекта-метки на графике (уникальное для каждого экземпляра индикатора)
//    ChartID() возвращает ID текущего графика — см. https://www.mql5.com/ru/docs/objects
string LabelName;
//--- Фактическое число дней для расчёта (защита от InpDays < 1)
int ExtDays;

//+------------------------------------------------------------------+
//| Функция инициализации пользовательского индикатора               |
//| Вызывается один раз при загрузке индикатора на график.          |
//| См. документацию: Программы MQL5 -> Пользовательские индикаторы  |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Проверка входного параметра (должно быть хотя бы 1 свеча)
   //    См. Основы языка -> Операторы условия if; тернарный оператор ? :
   ExtDays = (InpDays < 1) ? 30 : InpDays;
   if(InpDays < 1)
      Print("InpDays должно быть >= 1. Используется ", ExtDays, " дней.");

   //--- Формируем уникальное имя метки: префикс + ID графика
   //    IntegerToString() преобразует число в строку (см. Преобразование данных)
   LabelName = "YZ_ADR30_" + IntegerToString(ChartID());

   //--- ObjectCreate — создаёт графический объект на графике
   //    Сигнатура: ObjectCreate(chart_id, name, type, subwindow, x, y)
   //    chart_id = 0 — текущий график (см. https://www.mql5.com/ru/docs/objects/objectcreate)
   //    name     — уникальное имя объекта (используется в ObjectSetString, ObjectDelete и т.д.)
   //    OBJ_LABEL — тип "текстовая метка" (рисуется в координатах экрана, не привязана к бару/цене)
   //    subwindow = 0 — главное окно графика (подокно индикатора 0)
   //    x, y = 0 — для OBJ_LABEL позиция задаётся через OBJPROP_XDISTANCE/OBJPROP_YDISTANCE
   if(!ObjectCreate(0, LabelName, OBJ_LABEL, 0, 0, 0))
     {
      //--- GetLastError() возвращает код последней ошибки (см. Проверка состояния)
      Print("Ошибка создания метки: ", GetLastError());
      return(INIT_FAILED);
     }

   //--- ObjectSetInteger — устанавливает свойство объекта типа integer
   //    OBJPROP_CORNER — угол привязки метки (см. Графические объекты)
   //    CORNER_LEFT_UPPER = 0 — левый верхний угол графика (метка будет "вверху экрана")
   ObjectSetInteger(0, LabelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);

   //--- OBJPROP_XDISTANCE — смещение по горизонтали от угла в пикселях
   ObjectSetInteger(0, LabelName, OBJPROP_XDISTANCE, 10);

   //--- OBJPROP_YDISTANCE — смещение по вертикали от угла в пикселях (отступ сверху)
   ObjectSetInteger(0, LabelName, OBJPROP_YDISTANCE, 20);

   //--- OBJPROP_ANCHOR — точка привязки самого объекта (ANCHOR_LEFT_UPPER = 0 — левый верхний угол текста)
   ObjectSetInteger(0, LabelName, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);

   //--- ObjectSetString — устанавливает строковое свойство объекта
   //    OBJPROP_FONT — шрифт (см. Графические объекты -> Общие свойства объектов)
   ObjectSetString(0, LabelName, OBJPROP_FONT, "Arial");

   //--- OBJPROP_FONTSIZE — размер шрифта в пунктах
   ObjectSetInteger(0, LabelName, OBJPROP_FONTSIZE, 12);

   //--- OBJPROP_COLOR — цвет текста (clrWhite — белый, предопределённая константа)
   ObjectSetInteger(0, LabelName, OBJPROP_COLOR, clrWhite);

   //--- Временно задаём текст (полное значение будет в OnCalculate)
   ObjectSetString(0, LabelName, OBJPROP_TEXT, "ADR30: ...");

   //--- OBJPROP_SELECTABLE — можно ли выделять объект мышью (false = не мешать кликам по графику)
   ObjectSetInteger(0, LabelName, OBJPROP_SELECTABLE, false);

   //--- OBJPROP_BACK — рисовать ли объект в фоне (false = поверх графика)
   ObjectSetInteger(0, LabelName, OBJPROP_BACK, false);

   //--- INIT_SUCCEEDED — константа успешной инициализации (советники/индикаторы)
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Функция деинициализации индикатора                               |
//| Вызывается при снятии индикатора с графика.                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   //--- ObjectDelete — удаляет объект с графика по имени
   //    Необходимо, чтобы при снятии индикатора метка исчезла (см. https://www.mql5.com/ru/docs/objects/objectdelete)
   ObjectDelete(0, LabelName);
  }

//+------------------------------------------------------------------+
//| Основная функция расчёта индикатора                               |
//| Вызывается при каждом новом тике и при перерисовке графика.       |
//| Сигнатура с полным набором таймсерий (time, OHLC, volume, spread)|
//| см. https://www.mql5.com/ru/docs/indicators/oncalculate&nbsp;          |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   //--- Запрашиваем ровно InpDays дневных свечей с текущего момента в прошлое
   //    MqlRates — структура одной свечи: time, open, high, low, close, tick_volume, spread, real_volume
   //    См. Константы, перечисления и структуры -> Структуры данных
   MqlRates daily[];

   //--- CopyRates — копирует массив свечей указанного символа и таймфрейма
   //    Сигнатура: CopyRates(symbol, timeframe, start_pos, count, rates_array)
   //    symbol   — Symbol() возвращает символ графика, на котором запущен индикатор (предопределённая переменная)
   //    PERIOD_D1 — константа дневного таймфрейма (см. Предопределённые переменные, таймфреймы)
   //    start_pos = 0 — начать с текущего (последнего) бара; 0 = текущий день, 1 = вчера и т.д.
   //    count = ExtDays — сколько баров скопировать (30 = последние 30 дневных свечей, включая 0-й бар)
   //    daily[] — массив, в который копируются данные (индексы 0..ExtDays-1; 0 — текущий день, в динамике)
   //    Возвращает: количество скопированных баров или -1 при ошибке (см. Доступ к таймсериям и индикаторам)
   int copied = CopyRates(Symbol(), PERIOD_D1, 0, ExtDays, daily);

   //--- Если копирование не удалось (ошибка или нет данных) — не обновляем метку
   //    При неполной истории (copied < ExtDays) считаем среднее по доступным барам и показываем фактическое число дней
   if(copied <= 0)
     {
      //--- GetLastError() — код ошибки (например, нет истории по D1 для этого символа)
      if(copied == -1)
         Print("CopyRates ошибка: ", GetLastError());
      return(rates_total);
     }

   //--- Сумма дневных ходов (High - Low) по каждой из скопированных свечей
   double sum_range = 0.0;

   //--- Цикл по всем скопированным дневным барам (включая 0-й = текущий день)
   for(int i = 0; i < copied && !IsStopped(); i++)
     {
      //--- IsStopped() — true, если пользователь остановил индикатор (рекомендуется проверять в долгих циклах)
      //    См. Проверка состояния -> IsStopped

      //--- daily[i].high — максимальная цена дневной свечи (см. структура MqlRates)
      //--- daily[i].low  — минимальная цена дневной свечи
      //    Дневной ход (range) = разница между High и Low одной свечи
      double bar_range = daily[i].high - daily[i].low;

      //--- Накапливаем сумму ходов для последующего усреднения
      sum_range += bar_range;
     }

   //--- Средний дневной ход = сумма ходов / количество баров
   //    (copied может быть меньше InpDays при нехватке истории — используем фактическое число)
   double avg_range = (copied > 0) ? (sum_range / (double)copied) : 0.0;

   //--- Количество знаков после запятой для вывода — берём у текущего символа
   //    _Digits — предопределённая переменная: число знаков после запятой в цене (см. Предопределённые переменные)
   int digits = (int)SymbolInfoInteger(Symbol(), SYMBOL_DIGITS);
   //    SymbolInfoInteger — возвращает свойство символа (SYMBOL_DIGITS = точность цены), см. Получение рыночной информации

   //--- DoubleToString — преобразует число типа double в строку с заданной точностью
   //    (см. Преобразование данных -> DoubleToString)
   string avg_str = DoubleToString(avg_range, digits);

   //--- Формируем итоговый текст метки: понятная подпись + значение
   string label_text = "Средний дневной ход (" + IntegerToString(copied) + " дн.): " + avg_str;

   //--- Обновляем текст метки на графике (при каждом вызове OnCalculate — т.е. в динамике при новом тике)
   ObjectSetString(0, LabelName, OBJPROP_TEXT, label_text);

   //--- ChartRedraw(0) — принудительная перерисовка текущего графика (0 = текущий)
   //    Чтобы метка обновилась сразу (см. Операции с графиками)
   ChartRedraw(0);

   //--- Для пользовательского индикатора возвращаем rates_total — количество баров, доступных на графике
   //    Это значение сохраняется в prev_calculated при следующем вызове OnCalculate
   return(rates_total);
  }
//+------------------------------------------------------------------+

Я ещё не проверил.
Но визуально выглядит достаточно неплохо.

Интересно, как был назван индикатор: эта «железная кошка» порылась и заметила, что я люблю называть свои коды с приставкой YZ_ — так легче отличить то, что сделал я, — и решила назвать файл в соответствии с моими правилами.

p.s.
итак проверяем!

О прекрасно!  - даже нет ошибок - неплохо для писанины за 3 минуты времени.



Скажите себе честно, сколько нужно времени ,  что бы набрать руками даже такой простой код ? 
С подробными комментариями разумеется.

MQL5 Code Base
MQL5 Code Base
  • www.mql5.com
Библиотека исходных кодов на языке MQL5 для MetaTrader 5
 

Те, кто трудился много лет, имеют собственные наработанные библиотеки и шаблоны.
Используя ИИ, можно быстро соединять эти наработки в готовые модули — вероятно, с последующим рефакторингом.

Однако многое будет зависеть от качества поданного на вход материала. Крайне важно корректно и подробно формулировать задание, идеально максимально подробно , как для ДЖУНА с первого курса ИТ факультета.
Пример неудачного или недостаточно качественного промта — самый первый, с Умаиром: в сети на 2 марта информации было немного, и по первому заданию поиск фактически в сети не был выполнен. По второму — результат появился сразу.

Для создания кода на MQL5, подал на вход стандартные учебники и заставил «кошку» пробежать по моим наработкам, сформировать синтаксическую базу.
Код был создан с первой попытки. Если этого не сделать и не подать на вход сам проект, ИИ выдаст не качественный  результат.

 

Спасибо, Юра. Очень показательный пример. Есть даже фишки, которые следует взять на заметку для общения с ИИ.

На MQl4 наберу руками код вывода на экран среднестатистического расстояния 30 последних дневных свеч минут, скажем, за 10-15. Ну может ещё покопаюсь минут 5-10 с позиционированием лейбы на экране. Отладка может занять неопределённое (пусть не большое) время. В целом, при старте с нуля и "под ключ", ну, скажем, час уйдёт. Но ни как не три минуты! Экономия времени на лицо.

Подобное Вашему задание (промпт) я могу отдать тому же deepseek или qwen. Они работают с сайта и для подобных нужд бесплатны. Эти 2 ИИ сделают тоже всё минуты за 2-3. И при этом у меня нет геморроя с иностранным языком, с покупкой памяти, и прочими сопутствующими делами!

Это честная оценка.

 

Есть тонкость: ИИ написала код неграмотно с точки зрения архитектурного решения. Опытные программисты с сайта MQL5 будут критиковать такой код — и обоснованно. Для ИИ необходимо формулировать подробное техническое задание, как для студента с первого курса.
Расчёт среднего хода выполняется за 30 дней на каждом тике, не надо пересчитывать на каждом тике историю, которая уже не изменится.

Именно так обычно пишут коды  для Windows индусы, без учёта оптимизации — поэтому windows работает  медленно.

---
Техническое задание

Тема: Оптимизация функции OnCalculate индикатора MQL5

1. Цель

Необходимо оптимизировать реализацию функции OnCalculate , исключив избыточный пересчёт исторических данных на каждом тике.

2. Проблема текущей реализации

В существующем варианте на каждом тике выполняется повторный пересчёт истории за 30 дней. Такой подход приводит к:

  • избыточной нагрузке на процессор;

  • неоправданному повторному анализу уже рассчитанных данных;

  • снижению производительности терминала.

Пересчёт полной истории на каждом тике является неэффективным и должен быть устранён.

3. Требуемая логика работы

  1. При запуске индикатора:

    • однократно загрузить 30 дневных свечей из истории;

    • включить в расчёт текущий (нулевой) бар;

    • выполнить полный расчёт только один раз.

  2. В процессе работы (OnCalculate):

    • не выполнять повторный пересчёт 30-дневной истории на каждом тике;

    • на тиках обновлять только текущий формирующийся бар;

    • пересчитывать историю повторно только при смене дневного бара.

  3. Определение смены дневного бара:

    • реализовать корректный механизм определения появления нового дневного бара;

    • использовать надёжный способ определения смены даты бара на таймфрейме D1.

4. Архитектурные требования

  1. Логику загрузки истории вынести в отдельную функцию.

  2. Эта функция должна вызываться:

    • при старте индикатора;

    • из OnCalculate только в случае смены дневного бара.

  3. Исключить лишние вычисления и повторные обращения к историческим данным без необходимости.

5. Ожидаемый результат

  • История за 30 дней загружается и пересчитывается однократно при инициализации.

  • Повторный пересчёт выполняется только при появлении нового дневного бара.

  • На каждом тике обновляется исключительно текущий бар без перерасчёта всей истории.

  • Код должен быть оптимизирован по производительности и структурирован логически корректно.
    ---

переделай это индикатор YZ_AvgDailyRange30.mq5 но назови его aiYZ_Z_AvgDailyRange30_V2.mq5

этот YZ_AvgDailyRange30.mq5 оставь как пример неправильного архитектурного решения.

//+------------------------------------------------------------------+
//|                                   aiYZ_Z_AvgDailyRange30_V2.mq5  |
//|                                  Автор: YuraZ                    |
//|  Оптимизированная версия: полный пересчёт только при смене D1.   |
//|  На каждом тике обновляется только текущий (0-й) бар.            |
//|  Справка: https://www.mql5.com/ru/docs&nbsp;                          |
//|  Примеры: https://www.mql5.com/ru/code/mt5&nbsp;                      |
//+------------------------------------------------------------------+
#property copyright "YuraZ"
#property link      "https://www.mql5.com"
#property version   "2.00"
#property description "Средний дневной ход (High-Low) за N дней. Оптимизация: пересчёт истории только при смене дневного бара."
#property description "На тике обновляется только формирующийся бар — без полного CopyRates."

#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots   0

input int InpDays = 30;  // Количество дневных свечей (включая текущий день)

//--- Уникальное имя метки на графике
string LabelName;
//--- Фактическое число дней (защита от InpDays < 1)
int ExtDays;

//--- Кэш для оптимизации: не пересчитываем 30 дней на каждом тике
//    Сумма ходов (High-Low) по барам с индексами 1..(N-1); бар 0 обновляется на тике
double   ExtSumBars1ToN = 0.0;
//    Фактическое количество скопированных дневных баров (30 или меньше при неполной истории)
int      ExtCopiedCount = 0;
//    Время открытия текущего дневного бара (0 = формирующийся бар); для определения смены дня
//    iTime(Symbol(), PERIOD_D1, 0) возвращает время начала текущего D1-бара (см. Доступ к таймсериям)
datetime ExtLastD1BarTime = 0;

//+------------------------------------------------------------------+
//| Загрузка дневной истории и расчёт суммы ходов по барам 1..(N-1)  |
//| Вызывается: при первом запуске и только при смене дневного бара. |
//| Возвращает true при успехе, false при ошибке CopyRates.           |
//+------------------------------------------------------------------+
bool LoadDailyHistoryAndCalc()
  {
   MqlRates daily[];

   //--- CopyRates — единственное обращение к истории за 30 дней в этом цикле вызова
   int copied = CopyRates(Symbol(), PERIOD_D1, 0, ExtDays, daily);

   if(copied <= 0)
     {
      if(copied == -1)
         Print("LoadDailyHistoryAndCalc: CopyRates ошибка ", GetLastError());
      return false;
     }

   //--- Сумма ходов только по барам 1..(copied-1); бар 0 не включаем — он обновляется на каждом тике
   double sum1ToN = 0.0;
   for(int i = 1; i < copied && !IsStopped(); i++)
      sum1ToN += (daily[i].high - daily[i].low);

   ExtSumBars1ToN   = sum1ToN;
   ExtCopiedCount   = copied;
   //--- Время открытия текущего D1-бара — по нему определяем смену дня в OnCalculate
   ExtLastD1BarTime = daily[0].time;

   return true;
  }

//+------------------------------------------------------------------+
//| Обновление текста метки на графике                               |
//+------------------------------------------------------------------+
void UpdateLabel(double avg_range, int bars_count)
  {
   int digits = (int)SymbolInfoInteger(Symbol(), SYMBOL_DIGITS);
   string avg_str = DoubleToString(avg_range, digits);
   string label_text = "Средний дневной ход (" + IntegerToString(bars_count) + " дн.): " + avg_str;
   ObjectSetString(0, LabelName, OBJPROP_TEXT, label_text);
   ChartRedraw(0);
  }

//+------------------------------------------------------------------+
//| Инициализация индикатора                                          |
//+------------------------------------------------------------------+
int OnInit()
  {
   ExtDays = (InpDays < 1) ? 30 : InpDays;
   if(InpDays < 1)
      Print("InpDays должно быть >= 1. Используется ", ExtDays, " дней.");

   LabelName = "aiYZ_ADR30_V2_" + IntegerToString(ChartID());

   if(!ObjectCreate(0, LabelName, OBJ_LABEL, 0, 0, 0))
     {
      Print("Ошибка создания метки: ", GetLastError());
      return(INIT_FAILED);
     }

   ObjectSetInteger(0, LabelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
   ObjectSetInteger(0, LabelName, OBJPROP_XDISTANCE, 10);
   ObjectSetInteger(0, LabelName, OBJPROP_YDISTANCE, 20);
   ObjectSetInteger(0, LabelName, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER);
   ObjectSetString(0, LabelName, OBJPROP_FONT, "Arial");
   ObjectSetInteger(0, LabelName, OBJPROP_FONTSIZE, 12);
   ObjectSetInteger(0, LabelName, OBJPROP_COLOR, clrWhite);
   ObjectSetString(0, LabelName, OBJPROP_TEXT, "ADR30 V2: ...");
   ObjectSetInteger(0, LabelName, OBJPROP_SELECTABLE, false);
   ObjectSetInteger(0, LabelName, OBJPROP_BACK, false);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Деинициализация                                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ObjectDelete(0, LabelName);
  }

//+------------------------------------------------------------------+
//| OnCalculate: оптимизированная логика                              |
//| — Полный пересчёт истории только при первом запуске и смене D1.  |
//| — На каждом тике обновляется только ход текущего (0-го) бара.     |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   //--- 1) Первый запуск или кэш ещё не заполнен — однократная полная загрузка истории
   if(prev_calculated == 0 || ExtLastD1BarTime == 0)
     {
      if(!LoadDailyHistoryAndCalc())
         return(rates_total);
     }

   //--- 2) Определение смены дневного бара
   //    iTime(symbol, timeframe, shift) — время открытия бара (см. Доступ к таймсериям и индикаторам)
   //    shift=0 — текущий (формирующийся) бар на D1; при смене дня это время меняется
   datetime current_d1_bar_time = iTime(Symbol(), PERIOD_D1, 0);

   if(current_d1_bar_time != ExtLastD1BarTime)
     {
      //--- Новый дневной бар: повторная загрузка истории и пересчёт суммы по барам 1..(N-1)
      if(!LoadDailyHistoryAndCalc())
         return(rates_total);
     }

   //--- 3) Текущий бар (0): ход обновляется на каждом тике без CopyRates за 30 дней
   //    iHigh / iLow(symbol, timeframe, shift) — High/Low бара (shift=0 — текущий бар)
   double range_bar0 = iHigh(Symbol(), PERIOD_D1, 0) - iLow(Symbol(), PERIOD_D1, 0);

   //--- Среднее = (сумма по барам 1..N-1 + ход текущего бара) / N
   double avg_range = (ExtCopiedCount > 0)
                      ? (ExtSumBars1ToN + range_bar0) / (double)ExtCopiedCount
                      : 0.0;

   UpdateLabel(avg_range, ExtCopiedCount);

   return(rates_total);
  }
//+------------------------------------------------------------------+
 
Vitaly Murlenko #:

Спасибо, Юра. Очень показательный пример. Есть даже фишки, которые следует взять на заметку для общения с ИИ.

На MQl4 наберу руками код вывода на экран среднестатистического расстояния 30 последних дневных свеч минут, скажем, за 10-15. Ну может ещё покопаюсь минут 5-10 с позиционированием лейбы на экране. Отладка может занять неопределённое (пусть не большое) время. В целом, при старте с нуля и "под ключ", ну, скажем, час уйдёт. Но ни как не три минуты! Экономия времени на лицо.

Подобное Вашему задание (промпт) я могу отдать тому же deepseek или qwen. Они работают с сайта и для подобных нужд бесплатны. Эти 2 ИИ сделают тоже всё минуты за 2-3. И при этом у меня нет геморроя с иностранным языком, с покупкой памяти, и прочими сопутствующими делами!

Это честная оценка.

Виталий, всё так!
Уже есть много бесплатных и вполне рабочих вариантов, правда, честно, не знаю, как DeepSeek кормить данными - учебниками и примерами, в Cursor это легко.
Что касается времени — думаю, да: если с нуля писать даже такой код, это точно не 3 минуты. А еще и с комментариями.
Промты я часто пишу в виде тезисов — потом даю промт «на съедение» в ChatGPT (у меня он тоже платный — платный всё же чуть более качественно работает), а затем кидаю в Cursor. Можно и в курсор но там токены жалко, более дорогие.
Чуть выше я кинул пример задания, где попросил ИИ оптимизацию, как пишут хорошие программисты с MQL5.
Вот уверен: ты бы с первого раза написала правильно, а не «индусский» вариант с итерацией на каждом тике.

К чему это я: за ИИ ещё надо выносить горшки и утирать сопли, подносить ей чай и кофе.
Синьоров эта штука ещё не потеснила. Джунов — да, практически уже уничтожила. 

 

Конечно все можно в deepseek, только чуть больше усилий.




 
Упс. Возникло желание сделать эксперимент и снять видео о том, как это всё работает. В том смысле, что запустить секундомер и посмотреть, за сколько времени 2 вышеупомянутых ИИ справятся с поставленной задачей. Я попробую это сделать, но чуть позже - нужно дела разгрести. Обновил в мобиле Госуслуги и теперь не могу авторизоваться от слова совсем. Нужно топать с паспортом в "Мои документы". Печальный сервис Госуслуги :(
 
Yuriy Zaytsev #:

Задачу нужно тщательно формулировать.

А это как ?