Обсуждение статьи "Возможности SQLite в MQL5: Пример интерактивной панели с торговой статистикой в разрезе символов и магиков"

 

Опубликована статья Возможности SQLite в MQL5: Пример интерактивной панели с торговой статистикой в разрезе символов и магиков:

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

Функция предназначена для рисования итоговой таблицы статистики по выбранному символу, магику, или полностью по счёту. В функцию передаётся тип таблицы статистики и наименования символа, или строковое значение магика, или номера счёта. По тексту определяется индекс символа, магика или аккаунта в соответствующем массиве структур статистических данных. Из требуемой структуры по полученному индексу получаем в структуру все статистические данные, а далее располагаем их в нарисованной таблице по координатам расположения её ячеек. При этом смещения выводимого текста по горизонтали рассчитываются таким образом, чтобы заголовок данных был привязан к левому краю ячейки таблицы, а текст значения этих данных был привязан к правому краю своей ячейки таблицы. Все данные выводятся в четыре столбца таким образом, чтобы визуально они были сгруппированы на панели в два столбца в виде "заголовок -- значение".

Давайте скомпилируем индикатор и посмотрим воочию, что мы получили:

Ну что ж, видим, что весь заявленный функционал работает как предполагалось. Да, заметны небольшие "моргания" текста в таблицах при перемещении курсора и прокрутке таблиц. Но это результат неоптимальной схемы перерисовки — вся видимая часть таблицы постоянно перерисовывается. Этого можно избежать более сложной логикой обработки строк таблиц под курсором, что не входит в планы этой статьи.

Автор: Artyom Trishkin

 

Не хватает инструментария, который позволял бы работать с большой историей торговли.

К сожалению, данный инструментарий просто зависает при запросе истории, как и многие другие.



Пять минут на получение истории. Далее что-либо делать с окном невозможно - полная нагрузка CPU.

 
fxsaber #:

Не хватает инструментария, который позволял бы работать с большой историей торговли.

К сожалению, данный инструментарий просто зависает при запросе истории, как и многие другие.



Пять минут на получение истории. Далее что-либо делать с окном невозможно - полная нагрузка CPU.

Можно в личку инвесторский доступ к счëту? 
 
Artyom Trishkin #:
Можно в личку инвесторский доступ к счëту? 

К сожалению, нет такой возможности. Но Вы можете сами создать нечто подобное: на демо-счете скриптом за час асинхронным OrderSend открыть/закрыть нужное количество позиций по разным символам/мэджикам.

 

На московской бирже работать не хочет



 
Konstantin Seredkin #:

На московской бирже работать не хочет

Естественно. Всё, что связано с позицией, кроме суммарной, при неттинге бесполезно, если работает больше одного робота на одном символе (или робот плюс ручная торговля).

 
fxsaber #:

Не хватает инструментов, которые позволили бы работать с обширной историей торговли.

К сожалению, этот набор инструментов, как и многие другие, просто зависает при запросе истории.



Получение истории занимает пять минут. После этого с окном невозможно ничего сделать — процессор полностью загружен.

Возможно, не обязательно каждый раз загружать всю историю: достаточно возобновить загрузку с момента последней зарегистрированной сделки, а базу данных, расположенную на отдельном сервере, периодически обновлять. Запрашивать следует только те данные, которые необходимы для индикатора на панели мониторинга.
 
fxsaber #:

Не хватает инструментария, который позволял бы работать с большой историей торговли.

К сожалению, данный инструментарий просто зависает при запросе истории, как и многие другие.



Пять минут на получение истории. Далее что-либо делать с окном невозможно - полная нагрузка CPU.

Не не не
SQLite вообще не годится для ресурсоемких задач. 
Для меня загадка - зачем эту игрушку для студентов прикрутили к MQL5. Намного лучше было прикрутить PostgreSQL. Там хоть есть высокопроизводительный JsonB.
А вообще нет ничего лучше сохранение/чтение массива структур в виде бинарника. И не нужна никакая база данных. Тем более у Вас уже все наработки есть.
 
Nikolai Semko #:
Нет, нет, нет
SQLite совершенно не подходит для ресурсоёмких задач.
Для меня остаётся загадкой, почему они привязали этот студенческий проект к MQL5. Было бы гораздо лучше интегрировать PostgreSQL. По крайней мере, в нём есть высокопроизводительный JsonB.
На самом деле нет ничего лучше, чем сохранять и считывать массив структур в виде двоичного файла. И база данных при этом вообще не нужна. Тем более что у вас уже есть весь необходимый код.

Возможно, PostgreSWL подошёл бы лучше. Однако автор статьи не использует индексы в таблицах, и если посмотреть на запросы, становится понятно, почему система будет работать отзывчиво только с очень небольшим набором данных. Если же применить индексы и адаптировать запросы под них, то система без проблем справится и с большим набором данных.

Сохранение структуры имеет смысл только в том случае, если вам не нужно выполнять запросы к данным, а требуется лишь их загрузка. Если же вам нужно выполнять запросы к данным, ничто не превосходит SQL.

 
Nikolai Semko #:
Не не не
SQLite вообще не годится для ресурсоемких задач. 
Для меня загадка - зачем эту игрушку для студентов прикрутили к MQL5. Намного лучше было прикрутить PostgreSQL. Там хоть есть высокопроизводительный JsonB.
А вообще нет ничего лучше сохранение/чтение массива структур в виде бинарника. И не нужна никакая база данных. Тем более у Вас уже все наработки есть.

В наших весях (когда у тебя не 100500 клиентов) SQLite кроет Постгре как бык овцу. Другое дело что ТС вообще не DBA и с базами не работал :-) Всё что в статье не тормозить не может

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

ps/ чтобы не спорить, спросите на профильных ресурсах что не так в запросе

//--- получим торговую статистику в разрезе советников по Magic Number
   request=DatabasePrepare(db, "SELECT r.*,"
                           "   (case when r.trades != 0 then (r.gross_profit+r.gross_loss)/r.trades else 0 end) as expected_payoff,"
                           "   (case when r.trades != 0 then r.win_trades*100.0/r.trades else 0 end) as win_percent,"
                           "   (case when r.trades != 0 then r.loss_trades*100.0/r.trades else 0 end) as loss_percent,"
                           "   r.gross_profit/r.win_trades as average_profit,"
                           "   r.gross_loss/r.loss_trades as average_loss,"
                           "   (case when r.gross_loss!=0.0 then r.gross_profit/(-r.gross_loss) else 0 end) as profit_factor "
                           "FROM "
                           "   ("
                           "   SELECT MAGIC,"
                           "   sum(case when entry =1 then 1 else 0 end) as trades,"
                           "   sum(case when profit > 0 then profit else 0 end) as gross_profit,"
                           "   sum(case when profit < 0 then profit else 0 end) as gross_loss,"
                           "   sum(swap) as total_swap,"
                           "   sum(commission) as total_commission,"
                           "   sum(profit) as total_profit,"
                           "   sum(profit+swap+commission) as net_profit,"
                           "   sum(case when profit > 0 then 1 else 0 end) as win_trades,"
                           "   sum(case when profit < 0 then 1 else 0 end) as loss_trades "
                           "   FROM DEALS "
                           "   WHERE SYMBOL <> '' and SYMBOL is not NULL "
                           "   GROUP BY MAGIC"
                           "   ) as r");
 

вкратце, по быстрому чтобы не говорили что придираюсь:

SYMBOL должен иметь тип TEXT NOT NULL. В SQLite типов данных всего ничего: int,real,text,blob (да и они опциональны, можно не указывать). NOT NULL избавит от бессмысленных проверок WHERE SYMBOL NOT NULL в каждом запросе

ID, TRADE_ID и подобные они не просто KEY, они PRIMARY KEY

поля которые часто используются в выражениях WHERE , GROUP BY полезно индексировать. Индексов в схеме не хватает, запросы тормозят. См.ниже про EXPLAIN

базу лучше заполнять "пачками". На каждую сделку INSERT это очень-очень долго. Когда можно отсылать по 100 записей в запросе. (по хорошему вообще синхронизировать при каждом запуске, а не просто заполнять при создании)

в выборках много дублированных вычислений и того что можно/нужно перекладывать на приклад. Сами по себе вложенные SELECT это нехороший звоночек, если уж иначе никак то отдельно мучить EXPLAIN и оптимизировать базу и запросы. 

для реального использования и большого числа сделок конечно нужен pagination, virtual tables (когда данные в свои view подгружаешь по мере необходимости, и не держишь бешенный массив структур)  но это наверное выходит за рамки статьи.

---

по большому счёту просто схема базы недопродумана, поэтому у fxsaber всё затормозило. Разумно выправить+дополнить схему, оптимизировать запросы и с минимальными правками должно заработать.