Владислав написал: Добрый день! При попытке снять заявку возникла ошибка: Ошибка снятия заявки. [GW][3] "Сейчас эта сессия не идет." При этом ни OnOrder, ни OnTransReply небыли вызваны. Как роботу понять что произошла ошибка снятия конкретной заявки, если колбеки не вызываются?
простой вариант решения проблемы - проверка наличия активных заявок по таблице заявок. ------------------------- Я для этого формирую специально таблицу активных заявок. В этой таблице отмечаю состояние заявки. 1) активная 2) отправлена транзакция на снятие ------------------------ Пассивная заявка удаляется из таблицы.
edw написал: в заявке поле Цена редактируемое, т.е. я могу при покупке ниже тек.цены указать нужную мне цену, т.е. выставить лимитную заявку на покупку?
Т е в каком стеке Вы вызовите сборщик, тот стек он и будет чистить.
Динамическая память - это не стек. Или имелся ввиду поток? Ну мы же можем передавать объекты между потоками. Не может быть разделения по потокам для сборки мусора.
Цитата
Each Lua state has one or more threads, which correspond to independent, cooperative lines of execution. The type lua_State (despite its name) refers to a thread. (Indirectly, through the thread, it also refers to the Lua state associated to the thread.)
Возможно путаница в терминологии. Глобальным стеком я называю lua_State. ----------------------- VM Lua - это стековая машина. Когда мы создаем VM Lua, то для нее выделяется область State -------------------------- Т е для нее из кучи выделяется кусок, в котором все размещается. Если вызвать функцию библиотечную, то этой функции на СИ передается всего один параметр. Это указатель на State VM Lua. --------------------------- Все функции и все переменные как глобальные так и локальные размещаются в этом State. Т е этот State и есть та динамическая память, с которой работает сборщик мусора. --------------------------- когда создаем корутину, то для нее из области State VMLua выделяется кусок памяти, который будет State корутины. ----------------------- "coroutine.create (f)Создает новый сопроцесс, с телом f. fдолжен быть функцией. Возвращает этот новый сопроцесс, как объект с типом "thread". ----------------------
lua_State *lua_newthread (lua_State *L);
Создает новый поток, ложит его на стек и возвращает указатель на lua_State, который представляет этот новый поток.
Новый поток использует одно глобальное окружение с оригинальным потоком, но имеет независимый стек исполнения.
Не существует явной функции для закрытия или уничтожения потока. Потоки это субъект для сборки мусора, как и любой Lua объект
-----------------------------
Если посмотреть внутри основной программы и внутри main, то увидим, что в вызываемые в них функции передается различный указатель на State.
Посмотрите на вызов функций в API C В качестве параметра в функцию передается указатель на стек. Когда Вы вызываете сборщик мусора в main, то сборщику будет передан указатель на локальный стек корутины. Когда вы вызываете сборщик мусора в колбеке, то сборщику передается указатель на глобальный стек основной VM Lua. ---------------- Т е в каком стеке Вы вызовите сборщик, тот стек он и будет чистить.
Сборщик мусора - это функция и она одна. Но запускать ее можно с различными стеками VMLua. ------------- Все функции выполняются в одном стеке. ------------------ Корутина main отличается тем, что для нее выделяется отдельный стенк из стека основной VM. ------------------ Если функцию например колбек вызвать, то ее переменные будут в глобальном стеке основной VMLua. -------------- Если Вы вызываете функцию в Main, то ее переменные будут в стеке корутины. ------------------------ сборщик мусора собирает мусор в в стеке основном VM. но при этом он не видит стек коррутины, так как это один объект в основном стеке. --------------- Но тогда кто освобождает пространство от переменных внутри main? Я полагаю что делается запуск сборщика для области стека корутины main. ---------------------
TGB, В качестве гипотезы, могу предположить следующее: Возможно это связано с тем, что Вы проверяете сборщик в main. Дело в том, что main - это корутина. В корутине свое адресное пространство для локальных переменных. Колбек это основная VM там свое. По логике должны действовать два различных сборщика мусора. -------------------- Если мое предположение верно, то Вы пытаетесь останавливать один, а проверять другой. --------------------- Но я не поверял эту гипотезу, так как меня пока не волнует как работает сборщик в скрипте.
Ander написал: после дробления акций ( например, Полюс; Норникель) из-зи большой разницы цены график на 1Д превращается в полоску. Подскажите как убрать график до дробления акций, что бы его значения он не учитывались при построении графика? или есть какой то другой способ ?
В параметрах графика на вкладке Диаграмма есть фильтр по дате и по времени Установите их как Вам надо
Михаил Горбатский написал: Как использовать getParamEx для создания индикатора? Написано что функция возвращает таблицу, но мне нужно только одно значение и с какими аргументами её вызывать? Будет ли корректной запись "local C = getParamEx ( , , PREVLEGALCLOSEPR)"? Как мне использовать его чтобы он показывал для инструмента который я выбрал из таблицы текущих торгов и нужно ли мне добавлять в таблицу значение чтобы его можно было использовать? В моем случае цена закрытия предыдущего дня.
Не в обиду, но Ваше непонимание в первую очередь вызвано незнанием языка lua. Поясняю Функция луа может возвращать либо скаляр, либо таблицу. В данном случае возвращается таблица ее формат указан в документации к библиотеке QLua:
Функция возвращает таблицу Lua с параметрами:
Параметр
Тип
Описание
param_type
STRING
Тип данных параметра, используемый в таблице «Текущие торги». Возможные значения:
«1» - DOUBLE;
«2» - LONG;
«3» - CHAR;
«4» - перечислимый тип;
«5» - время;
«6» - дата
param_value
STRING
Значение параметра. Для param_type = 3 значение параметра равно «0», в остальных случаях – числовое представление. Для перечислимых типов значение равно порядковому значению перечисления
param_image
STRING
Строковое значение параметра, аналогичное его представлению в таблице. В строковом представлении учитываются разделители разрядов, разделители целой и дробной части. Для перечислимых типов выводятся соответствующие им строковые значения
result
STRING
Результат выполнения операции. Возможные значения:
«0» - ошибка;
«1» - параметр найден
================ при вызове этой функции надо указать три параметра class_code --код класса инструмента sec_code --код инструмента param_name -- название параметра инструмента. Это параметры таблицы TTT (название столбца на англ яз) --------------- class_code и sec_code при написании индикатора можно получать с графика (см функции в док QLUA)
Функция предназначена для получения значений всех параметров биржевой информации из Таблицы текущих торгов с возможностью в дальнейшем отказаться от получения определенных параметров, заказанных с помощью функции ParamRequest. Для отказа от получения какого-либо параметра воспользуйтесь функцией CancelParamRequest.
Nikolay написал: Ну стоит всегда проверять что получено в ответ. Это же метод, запрашивающий данные на сервере (условно). А значит может приехать и nil.
данные запрашиваются не на сервер, а из ТТП, т е из архива терминала. nil может быть если этого параметра нет в таблице. Там и проверить можно есть или нет.
Stivins написал: С помощью CreateDataSource выгружаем свечи по инструменту Но как запросить не все, а только к примеру 20 последних свечей
Если невозможно то как можно урезать полученный массив со свечами, оставив 20 последних.
CreateDataSource - это подписка, а не выгрузка, на сервере для получения свечей После подписки в терминал будут приходить все новые свечи. Принимаемые свечи помещаются в архив терминала ------------------------ Прочитать из архива можно с помощью : ------------------------- getCandlesByIndex Функция предназначена для получения информации о свечках по идентификатору (заказ данных для построения графика плагин не осуществляет, поэтому для успешного доступа нужный график должен быть открыт). Формат вызова: TABLE t, NUMBER n, STRING l getCandlesByIndex (STRING tag, NUMBER line, NUMBER first_candle, NUMBER count)
Вот уже нужен график обязательно открытый. Как тогда принятый через CreateDataSource массив уменьшить до последних 20 свечей?
CreateDataSource эквивалентен открытому графику Архив , который приходит с сервера всегда будет максимальным и запишется в файл на диск. Зачем Вам уменьшать архив до 20 свечей? Напишите подробнее что хотите и зачем сделать.
Stivins написал: С помощью CreateDataSource выгружаем свечи по инструменту Но как запросить не все, а только к примеру 20 последних свечей
Если невозможно то как можно урезать полученный массив со свечами, оставив 20 последних.
CreateDataSource - это подписка, а не выгрузка, на сервере для получения свечей После подписки в терминал будут приходить все новые свечи. Принимаемые свечи помещаются в архив терминала ------------------------ Прочитать из архива можно с помощью : ------------------------- getCandlesByIndex
Функция предназначена для получения информации о свечках по идентификатору (заказ данных для построения графика плагин не осуществляет, поэтому для успешного доступа нужный график должен быть открыт).
Формат вызова:
TABLE t, NUMBER n, STRING l getCandlesByIndex (STRING tag, NUMBER line, NUMBER first_candle, NUMBER count)
ЭД написал: Спасибо. Нет у вас хорошего примера под рукой OnTransReply) ?
У меня этот колбек реализован так:
Код
local t_mes={
"отправлена серверу",
"получена на сервер QUIK от клиента",
"ошибка при передаче транзакции в торговую систему. Так как отсутствует подключение шлюза Московской Биржи",
"выполнена",
"не выполнена торговой системой. Более подробное описание ошибки отражается в поле «Сообщение»",
"не прошла проверку сервера QUIK по каким-либо критериям. Например, проверку на наличие прав у пользователя на отправку транзакции данного типа",
"не прошла проверку лимитов сервера QUIK",
"не поддерживается торговой системой",
"не прошла проверку правильности электронной цифровой подписи",
"не удалось дождаться ответа на транзакцию, т.к. истек таймаут ожидания",
"отвергнута, так как ее выполнение могло привести к кросс-сделке",
"не прошла контроль дополнительных ограничений, установленных брокером",
"принята после нарушения дополнительных ограничений, установленных брокером",
"отменена пользователем в ходе проверки дополнительных ограничений, установленных брокером" }
function OnTransReply(t)
local x=t.status
if Log then Log:write("status="..x..": транзакция "..t_mes[x+1]..">"..msg.."\n"); Log:flush();end
if x==3 or 2>x or x==15 then return end
---удаляем ошибочные транзакции сделок
local _id=t.trans_id; local e,j,M;
for n=1,2 do
e=tor[n]; j=0; M=#e; while M>j do j=j+1; u=e[j];
if u[1]==id_ then if M>j then e[j]=e[M]; end e[M]=nil; e[0]=e[0]-1
if Log then Log:write("transReply "..",e[0]="..e[0]..",#e="..#e.."\n");Log:flush(); end
return; end --отменяем выставление заявки
if #u==3 and u[3]==id_ then u[3]=nil ;e[0]=e[0]-1
if Log then Log:write("transReply "..",e[0]="..e[0]..",#e="..#e.."\n");Log:flush(); end
return; end -- отменяем удаление
end
end
end
for i=0,(tonumber(getNumberOf("stop_orders"))-1) do bs=getItem("stop_orders",i) if bit.band(bs.flags, 1)~=0 and bs.trans_id == p_trans_id then message('Send drop stop-order trans_id='..bs.trans_id); local Transaction={ ["TRANS_ID"] = tostring(bs.trans_id), ["ACTION"] = "KILL_STOP_ORDER", ["CLASSCODE"] = 'SPBFUT', ["SECCODE"] = 'SiH5', -- инструмент ["STOP_ORDER_KEY"] = tostring(bs.ordernum), ["ACCOUNT"] = 'SPBFUTxxx' } -- Если функция вернула строку диагностики ошибки, то значит транзакция не прошла local Result = sendTransaction(Transaction); if Result ~= "" then message("Drop stop-order error!\nОШИБКА: "..tostring(Result)); end
end end end
В терминале сообщения: Begin drop_stop_order trans_id=142604 Send drop stop-order trans_id=142604 и в обход скрипта насколько понял сообщение: Не удается снять стоп-заявку N [1217138444]
То есть сообщения "Drop stop-order error!\nОШИБКА: "..tostring(Result) нет, а должно судя по документации. Почему sendTransaction не вернула ошибку??
sendTransaction возвращает ошибки обнаруженные терминалом, а полученную Вами ошибку прислала биржа. Вы ее получите в колбеке.
ЮрийК написал: --------------------------------------------------------------------- local size = Size(I) ------------------- Size не имеет параметров:. local size = Size() --------------------------------------------------------------------- Lua прощает такую ошибку
--------------------------------------------------------------------------------------------------------- У пустой свечи нет объема, нет параметров. =================== При старте скрипта он исполняется два раза от 1 до Size() -------------------------------------------------------------------------------------------------------- Это понятно.
Если выполнить условия п. 2, то вывалится целый период из расчётов!
local size = Size(I) ------------------- Size не имеет параметров:. local size = Size() ==========================
И как его отличить от пустых свечей при включенной опции "Показывать пустые интервалы"? ------------------- У пустой свечи нет объема, нет параметров. =================== При старте скрипта он исполняется два раза от 1 до Size()
Максим Трейдер написал: Добрый день. Я новичок в программировании роботов. Прошу простить за, наверное, дилетантский вопрос. 18 марта во время высокой волатильности в ответ на мои транзакции на снятие заявок QUIK стал присылать ответы "Вы не можете снять данную заявку", "Транзакция не прошла проверку лимитов сервера QUIK". Раньше подобные ответы приходили только, если заявка уже снята, но в этот раз заявки продолжали стоять в стакане. Почему такое происходит и есть ли какая-то рекомендация, как определить, снята всё-таки заявка или нет?
В данном сообщении указана причина, Транзакция не прошла проверку лимитов сервера QUIK". Вот это и является главным. Но сделать анализ невозможно, так как нет содержимого транзакции.
Для этого надо установить пакет luasocket. ------------------- Пример скрипта получить данные по Сбер для тайма 10 минут
Код
p2 = "D:/luasocket/";
package.cpath =package.cpath ..";"..p2.."?.dll";
package.path =package.path..";"..p2.."?.lua;"
local http = require("socket.http")
local header="http://iss.moex.com/iss/"
local sec="SBER"
local Date="2025-03-10"
local interval="10"
Data=http.request(header..eng..sec.."/candles.csv?from="..Date.."&interval="..interval) --не более 500 значений
print(Data)
VPM написал: Не стоит питать иллюзий: рынок — это не место для легких денег! --------------------------------------------------------------------------------------------- 1) Открывая график в терминале, мы видим отражение цены во времени (массив), и это колебательный процесс, что в свою очередь равносильно волновой процесс. Волновой процесс можно описать с помощь фазово - частотной характеристики.
Без обид, но не стоит нести в массы отсебятину и чушь. -------------- Все это можно найти в интернете. ----------------- Если хотите просвещать, то дайте просто ссылку, а не пытайтесь своими словами пересказывать то, в чем сами не разбираетесь. ===================== Фазо-частотная характеристика применяется к линейным системам, а не к сигналам. ------------------------------------
Фа́зочасто́тная характери́стика (ФЧХ) — зависимость разности фаз между выходным и входным сигналами некоторой системы от частоты сигнала, функция, аналитически выражающая (описывающая) эту зависимость, также — график этой функции.
================== Применительно к сигналам получают не характеристику , а спектр. ================ Волна́ — изменение некоторой совокупности физических величин (характеристик некоторого физического поля или материальной среды), которое способно перемещаться, удаляясь от места своего возникновения, или колебаться внутри ограниченных областей пространства[ Многообразие волновых процессов приводит к тому, что никаких абсолютных общих свойств волн выделить не удаётся
VPM написал: Предложенный подход paluke, t[I-3] = nil (в место limit_table_size), разложений по полочкам Nikolay,
Если просто обнулять элементы таблицы, например, t[I-3] = nil, это приведет к тому, что в таблице появятся "дыры" (nil-значения). Да, не требуется сдвигать элементы, что может быть быстрее для больших таблиц. Но при этом таблица будет содержать "дыры", что может привести к ошибкам при использовании функций, ожидающих последовательности. "В Lua таблицы с nil-значениями могут вести себя неожиданно, особенно при использовании функций, которые работают с последовательностями (например, #t, table.concat, ipairs). Память не освобождается сразу, так как в этом варианте Lua использует сборщик мусора для удаления nil-элементов. Это может привести к увеличению потребления памяти".
Из выше всего сказанного, делаем выводы. 1) limit_table_size подходит для небольших размеров таблиц 2) Подход таблица содержащая "дыры", подходит для конечных вычислений, не требующий передачи таблиц дальше для использования, как это показал нам Nikolay. 3) В подходе с выводом таблиц и функции, как это предложилNikolay, на мой не профессиональный взгляд, лучше использовать альтернативный метод как это предлагают разработчики, использовать кольцевой буфер (circular buffer). В этом случае таблица имеет фиксированный размер, и новые элементы записываются поверх старых. Вариант, избежать использования limit_table_size, но при этом не хотите сталкиваться с проблемами nil-значений, в случае дальнейшего использования таблиц. Это наиболее эффективный способ управления памятью для задач, где требуется хранить только последние N элементов.
Если nil элемент не таблица, то никакой памяти сборщик мусора не удаляет. ===========
Расскажу про свой способ, который самый быстродействующий для обработки событий колбеков , не имеет дыр, не требует работы сборщика, имеет ограниченный размер таблицы и не требует дополнительной синхронизации потоков. -----------------. 1) Создаем очередь с двумя указателями для записи и чтения 2) колбеки помещают в эту очередь данные и ключ, если в очереди на данный момент нет данных от данного колбека для одноименного инструмента 3) Если колбек обнаруживает что очередь пустая, то устанавливает указатели на ноль. Если есть желание сэкономить 1...10 Кбайт, то можно снова переопределить таблицу очереди. ----------------- Максимальная длина массива определяется максимальным числом необработанных вызовов колбеков, которые будут записаны в очередь.
VPM написал: В терминале от Сбер весит сообщение, надеюсь глюки связаны с этим: "С 11 по 23 марта планируется техническое обновление QUIK.Это необходимо для дальнейшей корректной работы терминала". А версию предпочитаю ту которую брокер рекомендует, как наиболее адаптированную к серверу. Вообще работали последнее время стабильно.
Поэтому сообщению и обновлял. И потом снес. Все работает как и раньше нормально без обновления.
VPM написал: nikolz, Сбер "глючит" второй день! Вчера просто без предупреждений отключали от сервера, сегодня не соединяют, от поддержки огромный ноль или даже нил. Так и хочется сменить лексику на не цензурную ::
у меня сегодня сбер работает отлично. Даже соединился быстрее , чем обычно. Но версия QUIK 8.7.1.3
окно можно свернуть. Если графики и стаканы в большом количестве не открывать, то загрузка процессора составит не более 10%. Много памяти жрет не терминал, а подписка на данные и инструменты. Особенно, если строите графики по параметрам инструментов.
Andrey Golik написал: nikolz, дополним, что архив с копией терминала требуется выложить на удобный для Вас файлообменник и прислать нам ссылку для скачивания (либо здесь, либо в рамках письма на quiksupport@arqatech.com ).
Благодарю за ответ. -------------------- Вчера сбер вдруг неожиданно отключился и при подключении сообщал об ошибке. Решил, что причина в новой версии и снес ее. Оказалось, что причины были у сбера. Сейчас снова на версии 8.Поэтому проблемы нет . Пока ставить версию 11 подожду. -----------------------
Сбер перешел на версию 11.4.0.54. По их предложению установил. И сразу появились временами задержки при передвижении позиции мышкой. Т е двигаешь, ничего не меняется, но через секунд 20-60 позиция перемещается. Эффект проявляется не всегда, возможно при активном движении рынка. До этого работал на версии 8 как самой устойчивой и надежной. Возможно придется обратно откатиться. Что скажут разработчики. Что не так?
Сбер перешел на версию 11.4.0.54. По их предложению установил. И сразу появились временами задержки при передвижении позиции мышкой. Т е двигаешь, ничего не меняется, но через секунд 20-60 позиция перемещается. Эффект проявляется не всегда, возможно при активном движении рынка. До этого работал на версии 8 как самой устойчивой и надежной. Возможно придется обратно откатиться. Что скажут разработчики. Что не так?
nikolz написал: Вы ошибаетесь. Ваш пример не соответствует Вашему t3[i=3]=nil ---------------- В Вашем тесте есть оператор tt1=nil (стр 21) Именно этот оператор освободит память так как он обнуляет ссылку на таблицу , т е массив из кучи становится без ссылки. Его и удаляет сборщик. --- если закомментировать tt1=nil. то результат: ------------- 1. mem 285.5576171875 2. mem 284.5439453125 3. mem 284.751953125 4. mem 284.6689453125 ------------ никакой очистки нет, как я Вам и написал.
Я знаю, что без удаления ссылки самой таблицы, расстановка nil по элементам массива ничего не даст. Пример говорит о другом. Очистка всей таблицы собирает её всю, да. Но он добавлен для того, чтобы видеть какой объём занимает вся таблица, заполненная значениями double.
Второй пример показывает какой размер забирает скрипт при работе с таблицей с дырками. Именно такие и используются при расчёте по индексам ряда. Спорить желания нет, т.к. это эмпирически проверено, даже просто по наблюдаемому объёму занимаемой памяти в окне доступные скрипты.
Хорошо, что признали. ------------------ Не увидел в вашем примере этого. ------------------ Что не так в этих данных. 1. mem 285.5576171875 2. mem 284.5439453125 3. mem 284.751953125 4. mem 284.6689453125 ----------------- Где Ваши доказательства? Можете, не перескакивая, конкретно показать , что и как Вы сокращаете?
VPM написал: Нашел, кому как и мне нужно более подробно!
"В Lua таблицы представляют собой ассоциативные массивы, которые могут хранить значения различных типов. Каждый элемент таблицы в Lua может быть представлен структурой TValue, которая содержит два основных поля: Value value_ — это поле, которое хранит значение элемента. В зависимости от типа, это может быть число, строка, указатель на другую структуру и т.д. int tt_ — это поле, которое хранит тип значения (например, LUA_TNIL, LUA_TNUMBER, LUA_TSTRING и т.д.). Когда вы выполняете операцию t[i-1] = nil, это означает, что вы удаляете элемент из таблицы по индексу i-1. Внутри Lua это приводит к тому, что значение элемента устанавливается в nil, а тип (tt_) устанавливается в LUA_TNIL (который обычно соответствует значению 0). Таким образом, операция t[i-1] = nil эквивалентна следующему: Установка value_ в какое-то "пустое" значение (в случае nil это может быть просто 0 или NULL). Установка tt_ в 0 (что соответствует типу LUA_TNIL). Это означает, что элемент таблицы больше не содержит полезного значения и считается "удаленным" или "пустым"."
Вы очевидно не поняли, то что цитируете. ----------------- Внутри Lua это приводит к тому, что значение элемента устанавливается в nil, а тип (tt_) устанавливается в LUA_TNIL (который обычно соответствует значению 0). ---------------- Поясняю. Т е это означает лишь то, что тип элемента стал равный нулю. Но само значение если это не указатель на таблицу или функцию хранится тоже в TValue. Поэтому ничего не освобождается, Если это указатель таблицу, то место в памяти освободится лишь при условии, что эта таблица больше нигде не используется.
Nikolay написал: local last = os.clock() print = _G.message or print
local sleep = sleep or function(ms) last = os.clock()*1000 while (os.clock()*1000 - last) < ms do end end
local tt1 = {} local tt2 = {}
local test = function()
for n = 1,10000 do tt1[n] = 100.12345 end
print('1. mem '..collectgarbage('count'))
tt1 = nil
collectgarbage() sleep(10)
print('2. mem '..collectgarbage('count'))
for n = 1,10000 do tt2[n] = 100.12345 tt2[n-3] = nil end
print('3. mem '..collectgarbage('count'))
collectgarbage()
sleep(10)
print('4. mem '..collectgarbage('count')) end
function main() test() sleep(1000) end
-- main()
Вы ошибаетесь. Ваш пример не соответствует Вашему t3[i=3]=nil ---------------- В Вашем тесте есть оператор tt1=nil (стр 21) Именно этот оператор освободит память так как он обнуляет ссылку на таблицу , т е массив из кучи становится без ссылки. Его и удаляет сборщик. --- если закомментировать tt1=nil. то результат: ------------- 1. mem 285.5576171875 2. mem 284.5439453125 3. mem 284.751953125 4. mem 284.6689453125 ------------ никакой очистки нет, как я Вам и написал.
Saturn, Второй способ На смартфоне ставите приложение отправки SMS на URL На ПК делаете сервер-приложение (на Autoit или любом другом языке), который будет запускать КВИК и передавать в него код. ---------------------- Третий способ На смартфоне ставите приложение отправки SMS в telegram На ПК делаете сервер-приложение (на Autoit или любом другом языке), который будет запускать КВИК и передавать в него код. В telegram ставите бот, который запускает приложение на ПК --------------------- Успехов
Igor_User написал: Возникла такая проблема. Может кто подскажет. Мой скрипт стал эпизодически останавливаться с ошибкой "attempt to perform arithmetic on a nil value". Сама ошибка понятна, но проблема заключается в том, что в этом сообщении не указывается номер строки, в которой эта ошибка произошла. Обычно при появлении таких ошибок в сообщении указывается и номер строки, благодаря чему можно найти ошибку и устранить. Я первый раз с таким сталкиваюсь. Есть ли какие-нибудь ещё способы определить строку, из-за которой эта ошибка произошла?
VPM написал: nikolz, Учебник мало прочитать, его еще необходимо понять. В моем "опусе", лишь краткие выдержки и не только из этого учебника, на что бы следовало обратить внимание по моему скромному мнению, начиная собирать торговую программу.
Цитата
VPM написал: Этот небольшой опус — попытка поделиться своим опытом и, возможно, помочь другим избежать ошибок или оптимизировать свой подход.
Если бы мне, еще пару - тройку лет назад сказали, обрати внимание на Метатаблицы и объектно-ориентированное программирование, я бы наверно "пальцем у виска покрутил" :: , сегодня это мой основной подход, леплю туда где можно и без него обойтись. А если бы прислушался к совету, сегодня бы не переписывал код, а использовал годами проверенный модуль. За ссылку спасибо, но лично у меня книга сохранена на компе, возможно кому понадобиться. Я лишь сделал пролог, к обсуждению универсальных модулей торговой системы, способной щелкать любые стратегии без изменений, ну или с минимальными изменениями в модулях.
Не в обиду будет сказано, но сначала изучают учебник. А Вы как я понял сначала начали писать что-то, а потом спустя 3 года начали читать. и о чудо, Вы наконец-то поняли то, что в учебниках про луа написано уже лет тридцать назад.
Александр Васильев написал: Доброго ! Пользуюсь скриптом QPILE , вывод по DDE в эксель , после расчётов выставляется и исполняется заявка . После 10.00.00 мск проблем нет . А до 10 . 00 учитывая раннее пробуждение ммвб ( 07.00 ) скрипт выдаёт не корректное время . Пример : 4 заявки в 09.55.11. и далее . 4 заявки после 10.00 мск всё поехало норм .В скрипте ошибок нет . Буду очень благодарен за мысли !!!
Вы неправильно преобразуете время число позиций до 10 часов на 1 меньше. Вы это не учитываете поэтому у вас выделяются не только цифры но и ":"
nikolz написал: При этом транслируется стакан, но не цена аукциона. Цена аукциона появляется когда ее сформируют. --------------------- Мое мнение: Цены аукциона в период аукциона еще нет, поэтому ноль. Когда она сформируется, тогда и появится в этом поле. Все верно? -------------------- Никакой ошибки в трансляции данного параметра нет.
Всё верно, только для акций и валют всё совсем не так. Почему-то именно для фьючерсов сделали иную трансляцию параметров, например, дисбаланс аукциона, объём аукциона, кол-во аукциона и пр. связанные параметры для валют и акций транслируются, а для фьючерсов их НЕТ, совсем нет - ни по итогам аукциона, ни во время, ни после. Почему так - мне никто не может ответить ни здесь ни на бирже.
Для акций аукцион давно, а для фьючерсов с этого года. Нигде не указано, что это должно быть. Возможно и для фьючерсов сделают. Но это не ошибка.
Анекдот: Вечер. Чел ищет что-то под фонарем. Прохожий - потеряли что-то? Чел - да, зажигалку потерял в подъезде дома. Прохожий - а почему ищите под столбом , а не в подъезде? Чел- там- темно, а здесь-светло. -------------------- Вы какой ответ хотите здесь получить? Брокер не хочет давать бесплатно - это его право. Вы не хотите платить - это ваше право. -------------
VPM написал: Собирая новую автоматическую систему, я поднимаю старые наработки, и довожу их до современного уровня понимания написания скриптов на Lua. Этот небольшой опус — попытка поделиться своим опытом и, возможно, помочь другим избежать ошибок или оптимизировать свой подход.
1) Основы Lua: таблицы как основа всего. Основная структура Lua — это таблицы. Именно из таблиц строятся все остальные конструкции языка. Таблицы в Lua — это не просто массивы или словари, а универсальный инструмент, который можно использовать для создания сложных структур данных. Если представить таблицу как отдельный модуль, то система становится четко структурированной. Например, можно создать таблицу, которая будет содержать данные и методы для работы с ними. Это позволяет разделять логику и данные, что делает код более читаемым и поддерживаемым.
2) Универсальные модули. Написав универсальный функциональный модуль, его можно использовать в разных скриптах. Например, модуль для работы с математическими расчетами или модуль для обработки данных можно легко интегрировать в различные проекты. Это экономит время и уменьшает количество ошибок, так как модуль уже протестирован и отлажен.
Код
Пример простого модуля: Модуль для математических расчетов
local MathUtils = {}
function MathUtils.add (a, b)
return a + b
end
function MathUtils.multiply (a, b)
return a * b
end
return MathUtils
Как можно использовать в других скриптах:
local MathUtils = require "MathUtils"
local result = MathUtils.add ( 5 , 3 )
print (result) -- Вывод: 8
3) Метатаблицы и объектно-ориентированное программирование. В Lua нет классов в классическом понимании, но есть метатаблицы, которые творят чудеса, позволяют создавать объектно-ориентированные структуры. Метатаблицы — это мощный инструмент, который позволяет определять поведение таблиц, например, перегрузку операторов или наследование. С помощью метатаблиц можно создавать объекты с методами и свойствами. Такой класс инкапсулирует всю логику, связанную с определенной задачей. Это позволяет изолировать код, упрощает его тестирование и повторное использование. Например, в торговой системе, можно выделить логику управления позициями, расчетов и генерации сигналов в отдельные классы.
Код
Пример класса для торговой системы:
local TradingSystem = {}
TradingSystem.__index = TradingSystem
function TradingSystem.new (params)
local self = setmetatable({}, TradingSystem)
self.length = params.length or 20
self.frac = params.frac or 5
self.pt_stop = params.pt_stop or 3
self.price = {}
self.smooth = {}
self.coef = {}
self.distance2 = {}
self.market_position = 0
self.entry_price = 0
return self
end
function TradingSystem:process_bar (index, high, low, open_price)
-- Логика обработки бара
end
-- Использование
local params = { length = 20 , frac = 5 , pt_stop = 3 }
local system = TradingSystem.new (params)
Делаем выводы по написанию скриптов на Lua. Lua — это мощный и гибкий язык, который отлично подходит для создания автоматических систем: 1. Используйте модули. Разделяйте код на модули по функциональности, чтобы упростить его повторное использование и тестирование. 2. Применяйте метатаблицы. Создавайте объектно-ориентированные структуры для инкапсуляции логики. 3. Документируйте код. Добавляйте комментарии и описание функций, чтобы код был понятен не только вам но и другим разработчикам. 4. Тестируйте. Проверяйте каждый модуль и класс отдельно, чтобы убедиться в их корректности. 5. Оптимизируйте. Убедитесь, что ваш код эффективен и не содержит лишних вычислений. Используя таблицы, модули и метатаблицы, можно создавать четко структурированные и легко поддерживаемые решения.
Надеюсь, этот небольшой опус поможет при создании новых проектов. Удачи!
Не в обиду будет сказано, но зачем рассказывать то, что лучше уже рассказано в учебниках. ------------------- Вот ссылка на хороший учебник по Луа. В нем на 400 страницах излагается подробно, что такое Lua и как на нем программировать. -------------------- https://eligovision.ru/media/upload/lua.pdf
При этом транслируется стакан, но не цена аукциона. Цена аукциона появляется когда ее сформируют. --------------------- Мое мнение: Цены аукциона в период аукциона еще нет, поэтому ноль. Когда она сформируется, тогда и появится в этом поле. Все верно? -------------------- Никакой ошибки в трансляции данного параметра нет.