Почему Tcl

почему именно tcl был выбран мной для встраивания в платформу MetaTrader.

обновляемая статья, по мотивам (и для) обсуждения на форуме MQL5 : https://www.mql5.com/en/forum/245700

материлы собираются и обобщаются из тетрадок, закладок броузера, а в основном по памяти :)

До того как приступить к проекту ATcl я для себя проделывал некоторые изыскания. И хотя tcl я знаю давно (очень давно) и довольно-таки глубоко, но окончательно не был убеждён в правильности своего решения до завершения анализа который представлю в статье. Конечно для себя я проделывал всё это не столь формально и не писал пространных документов, но всё упомянутое далее было выполнено еще до начала программировани ATcl.

Проект (встраивание/использование доп.языка в MT) видится довольно длительным и выбор в пользу tcl был не столь очевиден. Он в конце концов не самый известный язык. В программировании вокруг трейдинга популярны и используемы python, R. Программистам которые начинали с Web-технологий более знакомы JavaScript и Ruby. А классическое проф.образование подразумевает свободное владение С,Pascal,Lisp.

Кратко, для чего хочется внутри MQL использовать скриптовый язык:

  • упрощение и сокращение записи алгоритмов, быстрое прототипирование. На скриптовом языке высокого уровня алгоритмы записываются очень компактно и быстро разрабатываются.
  • преодоление «проблем» MQL. Язык платформы ориентирован в первую очередь на взаимодействие с торговым окружением и быстрые математические вычисления. При этом массивы не являются first-class сущностями, а динамические структуры довольно сложно программируются. Справедливости ради - это имеет обоснования и отчасти это решается «Стандартной библиотекой»
  • разделение кода. На рабочем месте трейдера (или на VDS) как правило запускается несколько экземпляров MetaTrader4 и MetaTrader5, при этом каждый из них имеет отдельную файловую иерархию и весь код дублируется. Хочется чтобы разрабатываемый софт находился в одном месте и был одинаково и сразу доступен из всех экземпляров MT не взирая на разрядность платформы (32-х или 64 бита)
  • повторное использование кода. Многое из разрабатываемого хотелось-бы использовать и вне MetaTrader, а MQL это исключительно язык торговой платформы
  • программирование GUI. Когда смотрю как программисты мучаются разрабатывая компоненты, которые могут отображаться только внутри графика и при этом программисты высчитывают пиксели, хочется плакать. 2018 год, 21 век, трейдинговая платформа! В любом языке есть 1-2-3 современных, полнофункциональных, стабильных фреймворка для интерфейсов пользователя.
  • Взаимодействие с «миром» - окружение трейдера включает в себя СУБД, таблицы, разные потоки данных, новостные ленты, аналитический софт и прочее. Нужны средства для взаимодействия с этим
  • Хотелось бы иметь «клей» для использования прочих средств. Чтобы 1 раз отладить в платформе одну DLL и один язык, а все прочие легко цеплялись уже к нему. Все современные языки имеют механизмы адаптации внешних модулей от других языков.

Конечно язык(интерпретатор) можно написать самому. Компилируемый язык платформы MQL достаточно развитый чтобы на нём это можно было сделать. Да многие наверное и пробовали :-) У такого решения есть несомненный плюс - из его скриптов могут быть доступны все функции платформы. Но и конечно-же минус - это будет язык внутри платформы и многие наши пожелания так и остануться в туне. К тому-же весьма непросто сделать такой интерпретатор который будет совместим с оригиналом на уровне языка, а если этого не добиться то получится просто «ещё один язык». Я не очень хочу писать интерпретатор на MQL, но дополнительно освещу эту возможность во второй части статьи .

Ещё один способ, достойный упоминания - это выделить пересечение языков. MQL (язык платформы) максимально похож на C++. В принципе можно выделить некоторое его подмножество, разработать «библиотеки совместимости» на самом MQL и на С++. Таким образом добиться возможности повторного использования кода внутри платформы и вне её. Хороший подход, некоторые программисты на MQL5.com его активно используют, но он решает только незначительную часть пожеланий.

И наконец - взять известный язык и его использовать. MQL предостаялет возможность вызова внешних функций из DLL, так что технологические проблемы тут минимальны. Использовать уже имеющийся язык можно несколькими способами:

  1. bath-mode или пакетный режим. Тут всё очень просто - записываем данные (или даже полный текст скрипта) в один файл, запускаем внешнее приложение и по его завершению читаем результат из другого файла. Так можно использовать практически любой язык, без существенных ограничений. Недостаток №1 - скорость. Надо форматировать и записывать данные, ожидать завершения и читать и разбирать результат. Недостаток №2 - потеря интерактивности. Запущенная программа будет выполнена до конца и не сохранит своё состояние для следующего вызова.
  2. консольный режим - запускаем интерпретатор как отдельное приложение и общаемся с ним по каналу (pipe). Передаём команду, ожидаем её завершения, читаем результат. Чуть лучше чем пакетный режим, потому-что всегда находимся в диалоге с интерпретатором. Но тоже передаваемые данные надо сериализовать, следить за состоянием интерпретатора, принимать и разбирать результат. Существенного выиграыша по скорости и гибкости мы не получим.
  3. клиент-сервер. Некоторые языки и многие мат.стат. системы позволяеют работать в качестве «клиента», используя сетевые соединения (например Rest-API). В крайнем случае для большинства языков можно написать такой локальный сервер. Не сильно отличается от консольного режима, но как правило протокол обмена и форматы данных чётко определены, меньше проблем с разбором данных. Стоит упомянуть про gtk-server (http://www.gtk-server.org/), несложно реализовать клиентскую часть и получить возможность полноценного GUI для своих приложений.
  4. исполнение скриптов внутри приложения. Непосредственное использование предоставляемого API языка. Такой подход позволяет максимально использовать возможности интерпретаторов и быстро обмениваться (или даже полностью разделять) данные. Именно это и предпочту. Другие решения попросту медленные и не дают значительных перспектив. Единственное упомяну что интерпретатор языка тоже может исполняться по разному:
    • Может исполняться в отдельном процессе, фактически в отдельном приложении. Равноценно клиент-сервер или консоле, разве что разработчики предоставили готовый API и взяли на себя весь труд по обмену данными и управлению исполнением.
    • Может исполняться в отдельной нити. Интерпретатор работает полностью параллельно основной программе, а для обмена данными требуется синхронизация (используются мутексы/спин-локи/семафоры). Требование синхронизации снижает скорость обмена данными и усложняет взаимодействие с интерпретатором. Зато долго исполняющийся или зацикленный скрипт не остановит основную программу.
    • исполняться в той-же нити что и основная программа. Максимально быстрый и простой обмен данными и потенциально большая гибкость. Можно в основной программе оперировать объектами интерпретатора и можем добиться «взаимности», чтобы скрипт мог взаимодействовать с объектами платформы. Кстати такой вариант и проще в реализации :-)

В итоге краткого рассмотрения, далее буду рассматривать и выбирать язык высокого уровня предоставляющий непосредственный API.

Конечно у решения будут очевидные ограничение и недостатки, это тоже надо сразу понимать и учитывать область применения:

  • новый язык надо будет изучить.
  • использование ещё одного языка влечёт за собой использование его инфраструктуры. Попросту говоря потребуется инсталляция этого языка с его библиотеками и средствами на компьютер.
  • программы использующие DLL:
    • не могут исполняться на популярных «VDS» MetaQuotes
    • не могут использоваться в «облаке оптимизатора»
    • не могут продаваться через «market mql5.com»

Известные особенности работы MetaTrader, которые существенно влияют на выбор языка для встраивания:

  • имеется три типа пользовательских программ:
    1. индикаторы
    2. скрипты
    3. эксперты
  • каждая программа является отдельной сущностью, работает с собственной памятью и не должна влиять на работу других
  • для исполнения программы платформы вызывает её методы (стандартные функции) которые должны отрабатывать до конца
  • при этом индикаторы одного чарта исполняются(вызываются) внутри одной системной нити ассоциированной с чартом
  • для скриптов и экспертов используется отдельная нить для каждого чарта
  • вызов функций MT из DLL невозможен.

из этого следует главное системное требование:

должна быть возможность запускать несколько независимых экземпляров интерпретатора (или виртуальной машины языка) на 1 системную нить.

и одно огромное пожелание (чтобы сделать невозможное возможным):

желательно чтобы язык/интепретатор имел «continuation» то есть позволял возврат промежуточного результата с сохранением собственного состояния

Изучить новый язык программирования это не столь сложно, тем более я имею предствление об их устройстве, и я последовательно рассматривал почти все. Конечно у меня были свои требования/пожелания к ним (с небольшими разъяснениями):

  1. это не должен быть экзотичный или очень новый/экспериментальный язык.
  2. должен иметь не слишком большой API
  3. API должен обеспечивать доступ непосредственно к языку и данным, а не просто его консоль или bath-режим
  4. сам язык должен быть довольно высокого уровня
  5. иметь хорошие прикладные библиотеки
  6. иметь подходящую лицензию интерпретатора и библиотек, которая позволяет использовать его во фрилансе или комерческих проектах не накладывая ограничений на заказчика

даже кратких тезисов набирается много, поэтому разбор языков,интерпретатров, API в следующей части.