Выглядит интересно, но у меня есть некоторые сомнения.
Если кто-то клонирует репозиторий Git с проектом/программой/пакетом MQL5, который должен управляться KnitPkg, он, скорее всего, получит некомпилируемые исходные коды, поскольку в репозитории отсутствуют автоматически сгенерированные файлы (такие как _flat). Не было бы целесообразно зафиксировать в Git весь необходимый автоматически сгенерированный исходный код, чтобы релиз компилировался независимо от того, как он был получен?
Не уверен, насколько удобно будет вносить изменения в зависимости, ведь мы фактически компилируем и отлаживаем автоматически сгенерированный код и не можем легко «перейти» к соответствующему источнику — может, я что-то упускаю? Например, вам нужно изменить пакет bar при работе над индикатором (если не над советником). Как бы вы это сделали?
Наконец, у меня возникают сомнения по поводу некоторых моментов в реализации примеров (вероятно, потому что это всего лишь примеры), таких как вызов new/delete при каждом тике/баре. Кроме того, например, вы делаете следующее:
int OnCalculate(const int32_t rates_total, const int32_t prev_calculated, const int32_t begin, const double &price[]) { ... douglasrechia::TimeSeriesArray<double> priceArray(price, prev_calculated - InpSMAPeriod - 1, rates_total-1, false); ... for (int shift=shiftStart; shift >= 0 && !IsStopped(); shift--) { SMABuffer[shift] = douglasrechia::SMA(priceArray, InpSMAPeriod, shift); } ... }
В чём смысл передавать массив цен в конструктор priceArray (где создаётся копия части массива), а затем передавать priceArray в SMA — почему бы не передать исходный массив цен по ссылке в SMA без копирования?
Не уверен, насколько удобно будет вносить изменения в зависимости, поскольку мы фактически компилируем и отлаживаем автоматически сгенерированный код и не можем легко «перейти» к соответствующему источнику — может, я что-то упускаю? Например, вам нужно изменить пакет bar при работе над индикатором (если не над советником). Как бы вы это сделали?
Наконец, у меня есть сомнения по поводу некоторых моментов в реализации примеров (вероятно, потому что это всего лишь примеры), таких как вызов new/delete на каждом тике/баре. Кроме того, например, вы делаете так:
В чём смысл передавать массив цен в конструктор priceArray (где создаётся копия части массива), а затем передавать priceArray в SMA — почему бы не передать исходный массив цен по ссылке в SMA без копирования?
Здравствуйте, Станислав,
спасибо, что нашли время прочитать статью и подняли эти вопросы.
Что касается фиксации сгенерированного кода: идея KnitPkg заключается в том, что автоматически сгенерированные артефакты (плоские заголовки, разрешённые включения и т. д.) не должны находиться в репозитории Git, поскольку в этом случае вы фактически дублируете код между репозиториями и рискуете, что он перестанет синхронизироваться. Если какая-то функциональность реализована в пакете/репозитории, это и является единственным достоверным источником; пользователи объявляют зависимость (используя диапазоны SemVer) и позволяют командам `kp install` или `kp autocomplete` перегенерировать производные файлы локально. Таким образом, когда зависимость обновляется в пределах допустимого диапазона SemVer, ваш проект может без проблем перейти на новую версию, вместо того чтобы «застрять» с устаревшим сгенерированным кодом, зафиксированным в собственном репозитории. Конкретный пример обновления версий зависимостей приведён в документации здесь.
Что касается вашего вопроса о том, «насколько удобно будет вносить изменения в зависимости»: я думал об этом при разработке инструмента. KnitPkg поддерживает использование локальных зависимостей, поэтому вы можете напрямую указать проекту пакет, находящийся в локальном каталоге, изменить этот пакет и протестировать изменения в реальном проекте-потребителе во время разработки. Этот рабочий процесс более подробно описан в разделе «Локальные зависимости» документации KnitPkg: https://docs.knitpkg.dev/user-guide/local-dependencies/
Что касается price → TimeSeriesArray → SMA: цель здесь не в том, чтобы показать наиболее эффективную микрооптимизацию, а в том, чтобы продемонстрировать стандартизированный интерфейс. SMA принимает ITimeSeries (а не непосредственно TimeSeriesArray) и обращает внимание только на то, что «самый последний элемент находится по индексу 0, следующий — по индексу 1 и т. д.». TimeSeriesArray — это всего лишь одна из реализаций, использованных в примере, которая, как оказалось, копирует фрагмент массива price. Кто-то другой мог бы реализовать другой ITimeSeries, использующий структуру, более подходящую для кэширования. Суть заключается в отделении вычислений от конкретной схемы хранения; насколько умной или эффективной будет реализация ITimeSeries, становится вопросом дизайна и творческого подхода.
Я всегда рад обсудить эти проектные решения, и с удовольствием приму отзывы о KnitPkg — будь то по рабочему процессу или по примеру кода, — поэтому не стесняйтесь оспаривать или развивать любые из этих идей.
- docs.knitpkg.dev
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Опубликована статья Пакетный подход к разработке на языке MQL5 с помощью KnitPkg:
Трейдеру-разработчику часто приходится сопровождать несколько проектов на языке MQL5 (советники, индикаторы, утилиты), в которых используется общий математический и служебный код. Сегодня код обычно используют повторно по старинке: копируют папки из проекта в проект и вручную редактируют директивы #include. С каждым обновлением возникает рассинхронизация версий: где-то уже есть новое исправление, а где-то остается старый файл. При этом результат сборки только средствами MetaTrader зависит от того, какие исправления уже были вручную внесены в данном терминале. На самом деле нужен способ один раз реализовать компонент в репозитории Git, управлять его версиями по SemVer и подключать к разным проектам так, чтобы установка и сборка были воспроизводимыми на любом компьютере: зависимости зафиксированы, артефакты генерируются автоматически (дерево заголовочных файлов или единый заголовочный файл), а перенос кода между проектами больше не требует редактирования путей или копирования файлов.
В этой статье представлен такой процесс разработки на языках MQL4/MQL5 с использованием пакетов KnitPkg: каждый функциональный блок оформляется как повторно используемый компонент с управлением версиями, а затем подключается к разным проектам через манифест, а не путем копирования кода. В статье мы увидим, как этот подход повышает надежность сборки, повторного использования кода в советниках и индикаторах, а также публикации, превращая разрозненные фрагменты кода в структурированные компоненты с управляемыми зависимостями.
Автор: Douglas Nascimento Rechia