226

Re: Общие вопросы по написанию скриптов LUA.

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

full_table={
   "indx1"={
      var1
      var2
      var3
      var4
      ....
}
   "indx2"={
      var1
      var2
      var3
      var4
      ....
}
   "indx3"={
      var1
      var2
      var3
      var4
      ....
}
}

Но у меня есть функция, которая использует только часть этой таблицы.

partial_table={
   "indx1"={
      var1
      var2
}
   "indx2"={
      var1
      var2
}
   "indx3"={
      var1
      var2
}
}

Могу ли я на луа сделать так, чтобы вторая таблица фактически была первой, но вторая таблица не видела бы "лишних переменных". Т.е. по факту, если я обращаюсь к таблице full_table, вижу весь набор переменных. А если обращаюсь к partial_table то вижу все теже самые переменные с теми же самыми значениями, но в ограниченном виде. Создавать копию не вариант, т.к. необходимо чтобы все значения всегда были актуальными.
Не сказал бы что это проблема, просто вопрос комфорта и "читабельности" кода. Пользовательских типов данных в lua я не нашел, да и вообще каких либо возможностей...
Возможно ли на qlua сделать такой финт?

227

Re: Общие вопросы по написанию скриптов LUA.

dark184, я не знаю такого способа

228 (2023-06-04 20:37:03 отредактировано s_mike)

Re: Общие вопросы по написанию скриптов LUA.

Метаметод __index вам в помощь.

Делаете таблицу full_table и наполняйте ее только(!) скрытыми значениями, и partial_table со видимыми общими для обеих таблиц значениями.

Таблице full_table задайте метаметод __index и в нем проверяйте наличие нужного значения в таблице partial_table.

229 (2023-06-18 14:31:05 отредактировано dark184)

Re: Общие вопросы по написанию скриптов LUA.

Снова всем привет.
Возникла необходимость во время исполнения скрипта Lua добавлять в таблицу новые таблицы. Как я понял ничего кроме table.insert это не сможет сделать прямо на ходу. И как обычно, то ли функция не позволяет сделать так, как мне надо, толи я с синтаксисом нифига не разбираюсь. Вобщем по сути.
Есть пустой массив calculate = {}. Далее я запускаю скрипт, который должен прочитать таблицу trades в квике и на каждой итерации возвращает таблицу trade

trade = getItem("trades", y)

Привожу только часть, ибо это не относится к теме. Это все работает, данные я получаю.
Теперь полученные данные мне надо распихать по таблице calculate. Структура таблицы примерно такая

calculate = {
"код инструмента 1" = {lots = trade.qty, ... , price = trade.price}
...
"код инструмента 9" = {lots = trade.qty, ... , price = trade.price}
"код инструмента n" = {lots = trade.qty, ... , price = trade.price}

Проблема заключается в следующем. Я заранее не знаю какие инструменты я получу, т.к. торги веду в том числе и вручную. Отсюда возникает дилемма и как я вижу два выхода:
1. Создавать прямо во время исполнения скрипта новый строковый индекс "код инструмента n" и заполнять его. Красиво и экономит память. Неоспоримое преимущество такого метода является так же и то, что массив будет автоматически дополняться независимо ни от чего. Даже если добавится новый инструмент и я решу поторговать на нем вручную.
2. Создать массив заранее, еще до запуска тела скрипта со всеми возможными инструментами. Но тогда в случае добавления нового инструмента на бирже придется корректировать сам скрипт. При этом таблица будет отжирать часть оперативы, пусть совсем чуть чуть, но будет.
2 вариант я вообще не рассматриваю, поэтому вариант 1.
Сейчас я учусь применять table.insert, выходит примерно так

        if calculate[trade.sec_code] == nil then
            table.insert(calculate, trade.sec_code = {lots = trade.qty})
            message("Количество: " .. tostring(calculate[trade.sec_code].lots))
        end

И получаю ошибку

 ')' expected near '='

что скорее всего намекает на ошибку в синтаксисе, либо функция не принимает такую запись, либо я сам ошибся в записи...
Попробовал сделать так

        if calculate[trade.sec_code] == nil then
            table.insert(calculate, {trade.qty, trade.price})
            message("Количество: " .. tostring(calculate[trade.sec_code].lots))
        end

функция запись проглотила, вместе с вложенным массивом. Да, месседж выдал ошибку и это естественно...
Неужели эта функция действительно не может разом все сделать?
Попробовал сделать и так

        if calculate[trade.sec_code] == nil then
            table.insert(calculate, trade.sec_code)
            table.insert(calculate[trade.sec_code],  "lots")
            calculate[trade.sec_code].lots = trade.qty
            message("Количество: " .. tostring(calculate[trade.sec_code].lots))
        end

нарываюсь на

bad argument #1 to 'insert' (table expected, got nil)

в строке table.insert(calculate[trade.sec_code],  "lots") и понимаю что предыдущая строка делает совсем не то что я ожидаю, а добавляет в конец массива значение из trade.sec_code...
Также попробовал и так

        if calculate[trade.sec_code] == nil then
            table.insert(calculate, trade.sec_code, trade)
        end

И опять нарвался на bad argument #2 to 'insert' (number expected, got string) и понимаю что второй аргумент должен быть числом, а мне нужна именно строка...

Подскажите как тогда создать строковый индекс(если он конечно же не существует) в таблице во время работы скрипта??? Так сказать на ходу. Как я понял метатаблицы и метод _index меня здесь тоже не спасут, ибо столкнусь с той же самой проблемой создания строкового индекса.

230 (2023-06-18 15:08:07 отредактировано swerg)

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:
table.insert(calculate, trade.sec_code = {lots = trade.qty})

Добавить проще всего так:

calculate[trade.sec_code] = {lots = trade.qty}

Насколько я понимаю, через table.insert нельзя вставить значение с имеем ключа.

231

Re: Общие вопросы по написанию скриптов LUA.

Ну да, вроде заработало, спасибо.
Только я пока сделал так

calculate[trade.sec_code] = trade

Когда будет четкое понимание что понадобится из этой кучи... Хотя я и так знаю что понадобится, но предусмотреть все...
И снова вопрос, а нафига нужны эти функции, если их функционал все равно ограничен??? Ну назвали table ну и пусть работает именно с таблицами. Насколько я понимаю в приложении к Lua массивами называются исключительно таблицы с цифровыми индексами, но если есть строковый индекс, это уже таблица... Опять же, если уж и те и те называются таблицами, то таблицы со строковыми индексами какие то особенные??? Неполноценные? Раз с ними не работают встроенные функции? Или это бредовая какая то терминология или я чего то не понимаю в этой жизни...
Я так понимаю что и table.sort в приложении к моей таблице тоже работать не будет?

232

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:

Я так понимаю что и table.sort в приложении к моей таблице тоже работать не будет?

А что будет порядком элементов после сортировки? ну вот в самом деле: в каком порядке перебрать элементы таблицы, если у нее ключ строковый?
Т.е. я бы скорее сказал, что смысла в такой сортировке нет, если ключ строковый

233 (2023-06-18 19:18:44 отредактировано dark184)

Re: Общие вопросы по написанию скриптов LUA.

Ну например по алфавиту от А до Я или от A до Z... К тому же в строковом ключе могут и цифры присутствовать в виде строки.

234 (2023-06-18 19:40:35 отредактировано dark184)

Re: Общие вопросы по написанию скриптов LUA.

Есть еще вопрос.
К примеру есть у меня три условия:

1. Var == 0
2. Var > 0
3. Var < 0

Все их надо проверить и выполнить три разных действия. Само собой самое очевидное что можно сделать это использовать

if then end 

или же его полный вариант. Но это занимает время, ибо всегда проверяются все три условия в случае сокращенного написания или могут проверяться до трех условий.
А можно ли на Lua придумать что то, чтобы не проверять условия, а сразу уходить туда, куда надо?
Для примера можно привести swith-case из того же Си. Правда он тоже не умеет так, но это самый близкий по смыслу оператор...
Да и некое подобие Switch можно относительно легко построить с помощью таблицы(только для default уже скорее всего придется использовать метатаблицу и метод _index), а вот именно для условий ничего в голову не приходит.

235 (2023-06-18 20:51:15 отредактировано swerg)

Re: Общие вопросы по написанию скриптов LUA.

Все равно надо проверить все три условия в любом языке, иначе как узнать "куда надо"?

Так что спокойно пишите 2 условия - и все будет хорошо и максимально быстро:

if Var == 0 then
....
elseif Var > 0 then
....
else
  -- здесь точно Var < 0
....
end

236

Re: Общие вопросы по написанию скриптов LUA.

Всем привет. Возникла необходимость разобрать строку по шаблону и чтобы не плодить if задумался, а может ли string.match или какая другая функция, искать подстроку одновременно по двум шаблонам? Первое же совпадение необходимо вернуть.
Если более подробно. Есть строка с разделителями ";", в которой есть набор символов "Купля", "Продажа" или вообще не попасться совпадения. В любом случае возможен только один из трех вариантов, в первом надо вернуть "Купля", во втором "Продажа", в третьем nil. Именно этим функция и занимается, но как правильно составить шаблон и возможно ли это?

237 (2023-06-25 19:37:08 отредактировано dark184)

Re: Общие вопросы по написанию скриптов LUA.

Есть еще один вопрос... Помогите модифицировать такой шаблон в

string.gmatch(str, "[^;]+")

Проблема в том, например, есть строка

30.08.2021 13:01;374158285;22180842523;;Купля;1

Если в ней встречаются подряд два символа ";", то есть в формате csv одна ячейка пустая, функция не возвращает ни пустую строку, ни значение nil. Я ожидаю получить значение "Купля", а получаю следующее значение за ней "1".
Пока забил туда такой костыль

str = string.gsub(str,";;",";0;")

238

Re: Общие вопросы по написанию скриптов LUA.

Всем доброго времени суток. Есть пара вопросов по индикаторам. Бегло почитал и увидел некоторые странности.
1. Зачем индикатору функция sendTransaction()??? Индикатор тоже может выставлять заявки? Если да, то я очень сильно удивлен...
2. Судя по описанию, есть также функции для получения данных с любых графиков по идентификаторам. Т.е. скрипт индикатора тоже это умеет?
3. Неужели скрипт индикатора умеет работать и со стаканом???
4. А вот функции CreateDataSource() я не нашел. Принципиально мне понятно почему, ибо как я понял для индикатора источником данных является сам график цены в котором он и открыт. Но все же, есть возможность создать второй источник данных с другого инструмента??? Т.е. например так, открываю график цены и объема на один инструмент, затем в настройках графика добавляю новый инструмент с графиком price. В итоге имеем два графика Price в одном окне, добавляю сюда же свой индикатор. Смогу ли я в индикаторе работать сразу с двумя графиками? Или с 10, а то и с 50?

239 (2023-09-18 23:36:44 отредактировано swerg)

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:

1. Зачем индикатору функция sendTransaction()??? Индикатор тоже может выставлять заявки?

Да, может.
Если по какой-то причине это удобнее - то можно и в индикаторе.

dark184 пишет:

2. Судя по описанию, есть также функции для получения данных с любых графиков по идентификаторам. Т.е. скрипт индикатора тоже это умеет?

Да. Это способ строить синтетические графики.

dark184 пишет:

3. Неужели скрипт индикатора умеет работать и со стаканом???
4. А вот функции CreateDataSource() я не нашел.

Из справки:

Список функций, доступных из скрипта индикатора:
  • getWorkingFolder  – возвращает путь, по которому находится файл info.exe, исполняющий скрипт,

  • getScriptPath  – возвращает путь, по которому находится запускаемый скрипт

  • getNumberOf  – возвращает количество записей в таблице «TableName»

  • getItem  – возвращает таблицу Lua, содержащую информацию о данных из строки с номером «Index» из таблицы с именем «TableName»

  • getParamEx  – получает значения всех параметров биржевой информации из Таблицы текущих торгов

  • message  – отображает сообщения в терминале QUIK

  • isConnected  – определяет состояние подключения клиентского места к серверу

  • getTradeDate  – получает дату торговой сессии

  • getInfoParam  – позволяет получить параметры для информационного окна (Связь/Информационное окно)

  • getClassSecurities  – получает список кодов инструментов для списка классов, заданного списком кодов

  • getClassInfo  – получает информацию о классе

  • getClassesList  – получает список кодов классов, полученных с сервера в ходе сеанса связи

  • getSecurityInfo  – получает информацию по инструменту

  • getQuoteLevel2  – получает стакан по указанному классу и инструменту

  • getMoney  – получает информацию по денежным позициям

  • getDepo  – получает позиции по инструментам

  • sendTransaction  – функция для работы с заявками

  • SearchItems  – позволяет реализовать быструю выборку элементов из хранилища терминала и возвращает таблицу с индексами элементов, удовлетворяющих условию поиска

  • getPortfolioInfo  – получает значения параметров таблицы «Клиентский портфель»

  • getBuySellInfo  – получает параметры таблицы «Купить/Продать»

  • getPortfolioInfoEx  – получает значения параметров таблицы «Клиентский портфель» с учетом срока расчётов

  • getBuySellInfoEx  – получает параметры таблицы «Купить/Продать» с учетом срока расчётов

  • getOrderByNumber  –возвращает таблицу Lua, содержащую описание параметров Таблицы заявок и индекс заявки в хранилище терминала

  • RGB – преобразовывает компоненты RGB (red, green, blue) в одно число

  • AddLabel - добавляет метку с заданными параметрами

  • DelLabel - удаляет метку с заданными параметрами

  • DelAllLabels - удаляет все метки на диаграмме с указанным графиком

  • GetLabelParams - получает параметры метки

  • SetLabelParams - задает параметры для метки с указанным идентификатором

  • SetValue - устанавливает указанное значение на выбранной линии определенной свечи индикатора

  • GetValue - получает значение, установленное на выбранной линии указанной свечи индикатора

  • SetRangeValue - устанавливает указанное значение на выбранной линии для определенного интервала индексов свечей индикатора

  • isDarkTheme - позволяет получить информацию о том, в какой теме оформления интерфейса в настоящий момент работает терминал: стандартной или тёмной

240

Re: Общие вопросы по написанию скриптов LUA.

А вот насчет коллбэков, индикатор их тоже может отрабатывать? Просто в справке я не нашел ни слова об этом.

241

Re: Общие вопросы по написанию скриптов LUA.

У индикатора свои колбеки. Про это написано в документации.

  • Init

  • OnCalculate

  • OnDestroy

  • OnChangeSettings

242

Re: Общие вопросы по написанию скриптов LUA.

Я имел ввиду кроме этих, например тот же OnDepoLimit() индикатор не отработает?

243 (2023-09-19 11:09:46 отредактировано swerg)

Re: Общие вопросы по написанию скриптов LUA.

dark184 пишет:

кроме этих, например тот же OnDepoLimit() индикатор не отработает?

Нет, только указанные выше в индикаторе работают.

244

Re: Общие вопросы по написанию скриптов LUA.

Блин, жаль.

245 (2023-10-10 19:43:39 отредактировано dark184)

Re: Общие вопросы по написанию скриптов LUA.

Всем привет. Возник такой вопрос. Мне в индикаторе нужны два источника данных с двух инструментов. Тестовый вариант индикатора написал. Добавил в график два графика Price. Оба нужны для расчета. Как я понимаю с первого графика я могу получать данные как обычный индикатор, со второго графика получаю данные по идентификатору функцией getCandlesByIndex().
Получается какой то бред, с первого графика я получаю чушь, со второго получаю в OnCalculate() все исторические данные, начиная с первой до последней строки. Более данный коллбэк не срабатывает вообще

function OnCalculate(i)
      local C1=C(i)
      local t=getCandlesByIndex(Settings.sec,0,i,1);  t=t[#t];
      if t  then
         local C2=t.close;
         if C2  and C1 then
            x=C1
            х1=C2
         end
      end
   return x,х1
end

По задумке в С1 должна быть цена закрытия текущей свечи первого (верхнего инструмента), Но по факту оказывается цена закрытия свечи толи предыдущей, толи следующей за текущей(т.к. почему то коллбэк просматривает всю историю и замолкает, а должен отрабатывать при изменении цены насколько я понял), НО! нижнего графика.
В С2 должна быть цена закрытия текущей свечи уже нижнего графика, где sec это идентификатор второго (нижнего) графика.
Что я делаю не так?

246

Re: Общие вопросы по написанию скриптов LUA.

Построить синтетические индикаторы от нескольких графиков - это шаманство и колдунство, т.к. данные приходят несинхронно.

247

Re: Общие вопросы по написанию скриптов LUA.

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

248 (2023-10-11 16:14:53 отредактировано swerg)

Re: Общие вопросы по написанию скриптов LUA.

Понимаю то, что вам требуется.
Но нормальных штатных средств для этого нет.

Особенно вот этого:

dark184 пишет:

дергать текущую свечу по ее изменению, желательно с обоих графиков.