101 (2022-12-06 17:58:56 отредактировано dark184)

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

Принципиально это тоже самое что и первая таблица

settings = {
    [common] =        {    
        [_KIND]             = 2,                -- для демо счета 0
                                                -- для реальных торгов 2
        [TRADE_ACC]            = "0123456789",    -- торговый счет
        [CLIENT_CODE]        = "0123456",        -- код клиента
            }
    [individual] =    {
        [SEC] =        {
            "RUAL",
            "AFKS",
            }
        [CLASS] =    {
            "TQBR",
            "TQBR",
            }
        [uniq_trans_id] = {
            0x20000
            0x21000
            }
    }
}

Хотя это мой косяк, в самом вопросе содержалась ошибка...
Здесь к общим настройкам я обращаюсь как settings.common... Вроде все гладко.
А вот элемент [individual] таблицы settings уже необходимо индексировать.

settings = {
    [common] =        {    
        [_KIND]             = 2,                -- для демо счета 0
                                                -- для реальных торгов 2
        [TRADE_ACC]            = "0123456789",    -- торговый счет
        [CLIENT_CODE]        = "0123456",        -- код клиента
            }
    [individual.RUAL] =    {
        [CLASS] = "TQBR", 
        [trigger_1]           = 0
        [trigger_2]           = 0    
        [percent]             = 0    
        [portfolio]           = 0    
        [Block_sell_Case] = 0
        [uniq_trans_id] = 0x20000
           }
    [individual.AFKS] =    {
        [CLASS] = "TQBR", 
        [trigger_1]           = 1
        [trigger_2]           = 1    
        [percent]             = 1    
        [portfolio]           = 1    
        [Block_sell_Case] = 0
        [uniq_trans_id] = 0x21000
           }
}

Массив задан неверно, но это я для наглядности, т.е. наборы имен полей для обоих индексов в массиве одинаковый, а вот их значения могут быть разные. Т.е. нужное значение из общих параметров выдергиваем settings.common, и пока все должно работать как задумано, а вот из поля individual значения надо дергать примерно как то settings.individual["AFKS"].uniq_trans_id или что тоже самое settings.individual[dlimit.sec_code].uniq_trans_id, если конечно же принять во внимание, что колбэк OnDepoLimit(dlimit) вернул в этом поле строку "AFKS".

102

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

А вот элемент [individual] таблицы settings уже необходимо индексировать.

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

settings = {
    [common] =        {    
        [_KIND]             = 2,                -- для демо счета 0
                                                -- для реальных торгов 2
        [TRADE_ACC]            = "0123456789",    -- торговый счет
        [CLIENT_CODE]        = "0123456",        -- код клиента
            }
    [RUAL] =    {
        [CLASS] = "TQBR", 
        [trigger_1]           = 0
        [trigger_2]           = 0    
        [percent]             = 0    
        [portfolio]           = 0    
        [Block_sell_Case] = 0
        [uniq_trans_id] = 0x20000
           }
    [AFKS] =    {
        [CLASS] = "TQBR", 
        [trigger_1]           = 1
        [trigger_2]           = 1    
        [percent]             = 1    
        [portfolio]           = 1    
        [Block_sell_Case] = 0
        [uniq_trans_id] = 0x21000
           }
}

И в колбэке OnDepoLimit(dlimit) выдергивать значения из полей массива AFKS в массиве settings

settings[dlimit.sec_code].uniq_trans_id

Все что nil это не мое smile

103

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

dark184 пишет:

А вот элемент [individual] таблицы settings уже необходимо индексировать.

Все уже проиндексировано, переживать не о чем.

104

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

Не совсем понял честно говоря. Ладно, надо до завтра оставить, покубатурить, переварить... smile

105 (2022-12-06 20:12:41 отредактировано swerg)

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

Я про то, что в Lua весьма эффективно организован поиск по ключу в таблице (не зависимо от типа ключа), дополнительных усилий со стороны программиста на Lua не требуется.

106 (2022-12-07 11:57:40 отредактировано dark184)

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

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

settings = {
    common =    {    
        _KIND                = 0,
        TRADE_ACC            = "NL0011100043",
        CLIENT_CODE            = "11053",
        }
    SPBE =    {
        SEC                    = "SPBE",
        CLASS                = "QJSIM",
        trigger_CCI            = -150,
        trigger_RSI            = 25,
        percent                = 0.6,
        portfolio            = 1,
        uniq_trans_id        = 0x10000,
        Block_sell_Case        = 0,
        }
    [FLOT] =    {
        [SEC]                = "FLOT",
        [CLASS]                = "QJSIM",
        [trigger_CCI]        = -150,
        [trigger_RSI]        = 25,
        [percent]            = 0.6,
        [portfolio]            = 1,
        [uniq_trans_id]        = 0x11000,
        [Block_sell_Case]    = 0,
        }
}

И получаю синтаксическую ошибку Settings_demo.lua:8: '}' expected (to close '{' at line 1) near 'SPBE'. SPBE и есть 8 строка... Здесь в common и SPBE квадратные скобки убрал для проверки.
Если же оставляю так

settings = {
    common =    {    
        _KIND                = 0,
        TRADE_ACC            = "NL0011100043",
        CLIENT_CODE            = "11053",
        }
}

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

107 (2022-12-07 12:29:38 отредактировано swerg)

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

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

Документации и примеров же море на Lua в гугле, методом подбора - зачем?

[+]Spoiler
settings = {
    common =    {    
        _KIND                = 0,
        TRADE_ACC            = "NL0011100043",
        CLIENT_CODE            = "11053",
        },
    SPBE =    {
        SEC                    = "SPBE",
        CLASS                = "QJSIM",
        trigger_CCI            = -150,
        trigger_RSI            = 25,
        percent                = 0.6,
        portfolio            = 1,
        uniq_trans_id        = 0x10000,
        Block_sell_Case        = 0,
        },
    FLOT =    {
        SEC                = "FLOT",
        CLASS                = "QJSIM",
        trigger_CCI        = -150,
        trigger_RSI        = 25,
        percent            = 0.6,
        portfolio            = 1,
        uniq_trans_id        = 0x11000,
        Block_sell_Case    = 0,
        }
}

108 (2022-12-07 14:55:11 отредактировано dark184)

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

Надо запятые добавить между элементами

Ну как обычно, слона то я и не увидел ;( Спасибо. Сейчас вроде все заработало.

Документации и примеров же море на Lua в гугле, методом подбора - зачем?

Действительно есть, и даже на форуме здесь же тоже есть. Все это я просматривал и только еще больше запутался. Проблема в том, что много правильной, неправильной и не относящейся к делу информации. И вот поди разберись кому верить smile Попробовал так, не работает, попробовал эдак, вроде работает, но не так...
Из лучшего что у меня в закладках это [url]https://smart-lab.ru/blog/291666.php[/url] и это [url]https://articles.opexflow.com/wp-content/uploads/2022/02/lua.pdf[/url]

И вот, где то читал, что индексы могут быть как числовыми так и строковыми. И почему то я был уверен, раз по дефолту индексы числовые, то даже если задать строковые, то и числовые работать будут. Ан нет. Не работают

    message("OnInit(): " .. tostring(#settings))
    message("OnInit(): " .. tostring(settings.common["TRADE_ACC"]))
    message("OnInit(): " .. tostring(settings["SPBE"].CLASS))
    message("OnInit(): " .. tostring(settings[2].CLASS))

Вот теперь не могу понять, почему первым сообщением длина уже этого массива выдается 0? Массив проинициализирован значениями... Насколько я знаю, что для # признаком конца массива является значение nil, но здесь то не nil, что подтверждают последующие сообщения... Да и у меня уже работает такая таблица и корректно определяется ее длина...
Второе сообщение выдает правильное значение поля с индексом "TRADE_ACC"
Третье сообщение опять выдает правильное значение из поля CLASS вложенного в settings массива с индексом "SPBE"
А вот четвертое сообщение выдает ошибку attempt to index a nil value (field 'integer index'), и это понятно, индекс должен быть "SPBE". Где то я читал как создавать массив, чтобы обращаться к нему как по строковому индексу, так и по числовому, а где найти не могу.

109

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

Вобщем полдня рылся, нашел что в моем случае оператор # не работает, он исключительно для массивов. Так что вопрос снимается.
А вот по второму вопросу я так решения и не нашел к сожалению. Смысл в том, что

settings = {
    common =    {    
        _KIND                = 0,
        TRADE_ACC            = "NL0011100043",
        CLIENT_CODE            = "11053",
        },
    SPBE =    {
        SEC                    = "SPBE",
        CLASS                = "QJSIM",
        trigger_CCI            = -150,
        trigger_RSI            = 25,
        percent                = 0.6,
        portfolio            = 1,
        uniq_trans_id        = 0x10000,
        Block_sell_Case        = 0,
        },
    FLOT =    {
        SEC                = "FLOT",
        CLASS                = "QJSIM",
        trigger_CCI        = -150,
        trigger_RSI        = 25,
        percent            = 0.6,
        portfolio            = 1,
        uniq_trans_id        = 0x11000,
        Block_sell_Case    = 0,
        }
}

из этой таблицы мне надо прочитать таблицы SPBE и FLOT по числовому индексу, ибо робот не знает ни длины таблицы, ни имен этих таблиц при запуске. Если читать так

settings["SPBE"].CLASS

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

settings[2].CLASS

читать так, но судя по всему это нереально. Ну не нашел я как это можно сделать...
Как компромисс можно добавить еще и массив

Indx = {
    "common",
    "SPBE",
    "FLOT",
}

И тогда читать

settings[Indx[2]].CLASS

Но выглядит это немного топорно. Может есть более элегантное решение?
Напомню, что числовые индексы нужны только для запуска робота. В дальнейшем будут использоваться исключительно строковые индексы. Впрочем именно для этого все и затевается. Задача, объединить все роботы в один поток.

110 (2022-12-08 11:47:57 отредактировано swerg)

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

dark184

из этой таблицы мне надо прочитать таблицы SPBE и FLOT по числовому индексу,

Сомневаюсь, что вам в самом деле требуется именно индекс.
Скорее задача - перебрать все элементы массива и для каждого элемента массива сделать нужное. Тогда это делается так:

t = {}
t["SBER"] = "-SBER-"
t["LKOH"] = "-LKOH-"
t["AFLT"] = "-AFLT-"

for k, v in pairs(t) do
  print(k, " -> ", v)
end

Выведет:

SBER -> -SBER-
AFLT -> -AFLT-
LKOH -> -LKOH-

Заметьте: выведены все элементы массива, но не в том порядке, в каком они добавлялись в массив! Это всегда так, итерируются на основании внутренних правил хеша для данной таблицы.

111 (2022-12-08 12:06:39 отредактировано dark184)

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

Что то в этом есть smile Надо переварить

settings = {
    common =    {    
        _KIND            = 0,
        TRADE_ACC        = "NL0011100043",
        CLIENT_CODE        = "11053",
        },
    SPBE =        {
        SEC            = "SPBE",
        CLASS            = "QJSIM",
        trigger_1        = -150,
        trigger_2        = 25,
        portfolio        = 10,
        uniq_trans_id        = 0x10000,
        Block_sell_Case        = 0,
        },
    FLOT =        {
        SEC            = "FLOT",
        CLASS            = "QJSIM",
        trigger_1        = -150,
        trigger_2        = 25,
        portfolio        = 10,
        uniq_trans_id        = 0x11000,
        Block_sell_Case        = 0,
        },
}
for k in pairs(settings) do
  print(k)
end

common
FLOT
SPBE

v мне не нужен, только ключ... Красиво, элегантно получается, вместо числового ключа получаю сразу строковый, именно то, что нужно. Единственное, пришлось перенести common в конец. И при встрече с этим ключем надо прервать цикл. Спасибо.

112

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

dark184 пишет:

v мне не нужен, только ключ...

Т.е. вы получите ключ, а потом слова будете запрашивать в таблице его значение? зачем, когда есть готовое значение в v, полученное при итерировании.

113

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

Не совсем. Мне надо сначала получить строковый индекс SPBE, FLOT. Но это уже сама по себе таблица и в значении я получу только адрес таблицы. А затем уже по этому индексу из уже вложенной таблицы я смогу заполнить переменные, значениями. Принципиально можно точно также использовать pairs, но это уже будет вложенный цикл в вышеописанный. Как то так. Но смысла большого я в этом не вижу, ибо выложенная таблица это всего лишь константы, а робот заполняет подобную структуру, но там переменные и к настроечным константам они не имеют вообще никакого отношения.
А что бы было возможно получить доступ к нужной таблице по коду инструмента (не забываем что все колбэки возвращают в том или ином виде код и класс инструмента в виде строки), мне нужно заполнять подобную константам структуру, а к вложенным таблицам мне необходимо обращаться по строковому индексу, например "SPBE". Таким образом, например в

OnQuote(class_code, sec_code)
end

я получаю доступ ко всем переменным, константам так: tool[sec_code].NAME и settings[sec_code].uniq_trans_id соответственно. Таблицы одинаковы по структуре, но совершенно разные по набору и количеству полей. Когда у робота один инструмент, все проще. А когда их несколько, например 23, то надо как то быстро получить доступ к нужной переменной. Вот именно для этого я все и делаю. Таким образом я сразу упрощаю себе жизнь, вместо 23 копий настроечных параметра для каждого отдельного робота, у меня будет всего один файл, который на новый инструмент настраивается тупо копипастом, все роботы будут работать в одном единственном потоке, а не в 23 сразу

114 (2022-12-08 20:11:03 отредактировано dark184)

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

Вот сижу, думаю... Откровенно говоря я был абсолютно уверен что в моем случае вернется значение nil. Ан нет, отваливаюсь в ошибку attempt to index a nil value (field '?'). Ну нельзя, так нельзя.
А ошибку вызывает вот это tool[sec_code].NAME. Если sec_code в качестве индекса, нет в моей таблице, то отваливаемся в ошибку просто потому, что нет такого индекса. На данный момент ничего лучшего, чем тупой перебор не придумал

function OnQuote(class_code, sec_code)

    for k in pairs(settings) do
        if k == sec_code then
            message("OnQuote: " .. tool[sec_code].NAME)    
        end
    end

end

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

115

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

Сейчас почти объединил все свои роботы в один поток. Потихоньку отлавливаю баги, ну как обычно, тут не тот индекс вписал, там не на ту таблицу сослался, где то втискивается левый индекс ну и прочее прочее. Ну не бывает так чтобы программу взять и написать с первого раза smile
И во время отладки заметил любопытный толи баг, толи особенность работы pairs(). Вобщем она выдает индексы(ключи) в рандомном порядке, все индексы(ключи) правильные. Но порядок рандомный. Если вбить сюда [url]https://qlua.ru/demo/[/url] вот эту программу и запустить несколько раз, ключи действительно чередуются рандомно.

settings = {
    common =    {    
        _KIND            = 0,
        TRADE_ACC        = "NL0011100043",
        CLIENT_CODE        = "11053",
        },
    SPBE =        {
        SEC            = "SPBE",
        CLASS            = "QJSIM",
        trigger_CCI        = -150,
        trigger_RSI        = 25,
        percent            = 0.6,
        portfolio        = 10,
        uniq_trans_id        = 0x10000,
        Block_sell_Case        = 0,
        },
    FLOT =        {
        SEC            = "FLOT",
        CLASS            = "QJSIM",
        trigger_CCI        = -150,
        trigger_RSI        = 25,
        percent            = 0.6,
        portfolio        = 10,
        uniq_trans_id        = 0x11000,
        Block_sell_Case        = 0,
        },
}
for k in pairs(settings) do
  print(k)
end

Не то чтобы это критично, на работу робота вроде бы не влияет, но список инструментов в пользовательской таблице также составляется рандомно, что не особенно удобно sad Возможно ли от этого избавиться, что бы список ключей был в том порядке, в каком прописан в файле?

116 (2022-12-11 11:48:31 отредактировано swerg)

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

dark184 пишет:

ключи действительно чередуются рандомно.

Я вам уже писал про это:

swerg пишет:

Заметьте: выведены все элементы массива, но не в том порядке, в каком они добавлялись в массив! Это всегда так, итерируются на основании внутренних правил хеша для данной таблицы.

По документации явно сказано, что для таких таблиц "порядок не определен", т.е. делаем как хотим.

117 (2022-12-11 12:08:01 отредактировано dark184)

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

Я вам уже писал про это:

Спасибо, видимо запамятвовал. Тем не менее, в любом случае это именно то, что нужно, все работает. А как отсортировать я уже придумал. У меня trans_id выглядит так 0х12000(ну люблю я использовать hex, все просто, компактно и наглядно), где старшие восемь бит однозначно опознают робота. Остается только обнулить на всякий случай младшие 24 бита(хотя надо глянуть, если сдвиг с потерей битов то и обнулять не надо) и сдвинуть вправо на 24 бита(ну или поделить на 0хFFF, что тоже самое в общем то), получившееся число использовать в качестве номера строки для вывода уже в пользовательскую таблицу. А в каком порядке они будут в памяти, мне вообще без разницы, роботу в принципе тоже smile

118

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

dark184 пишет:

Возможно ли от этого избавиться, что бы список ключей был в том порядке, в каком прописан в файле?

Загугливание подсказывает нам хитрый код решения этой "проблемы"
[url]https://stackoverflow.com/questions/30970034/lua-in-pairs-with-same-order-as-its-written[/url]

ordered_table = {}
function ordered_table.insert(t, k, v)
  if not rawget(t._values, k) then -- new key
    t._keys[#t._keys + 1] = k
  end
  if v == nil then -- delete key too.
    ordered_table.remove(t, k)
  else -- update/store value
    t._values[k] = v
  end
end
local function find(t, value)
  for i,v in ipairs(t) do
    if v == value then
      return i
    end
  end
end
function ordered_table.remove(t, k)
  local v = t._values[k]
  if v ~= nil then
    table.remove(t._keys, find(t._keys, k))
    t._values[k] = nil
  end
  return v
end
function ordered_table.index(t, k)
    return rawget(t._values, k)
end
function ordered_table.pairs(t)
  local i = 0
  return function()
    i = i + 1
    local key = t._keys[i]
    if key ~= nil then
      return key, t._values[key]
    end
  end
end
function ordered_table.new(init)
  init = init or {}
  local t = {_keys={}, _values={}}
  local n = #init
  if n % 2 ~= 0 then
    error"in ordered_table initialization: key is missing value"
  end
  for i=1,n/2 do
    local k = init[i * 2 - 1]
    local v = init[i * 2]
    if t._values[k] ~= nil then
      error("duplicate key:"..k)
    end
    t._keys[#t._keys + 1]  = k
    t._values[k] = v
  end
  return setmetatable(t,
    {__newindex=ordered_table.insert,
    __len=function(t) return #t._keys end,
    __pairs=ordered_table.pairs,
    __index=t._values
    })
end


--- Создаем заполненную таблицу
local t = ordered_table.new{
  "hello", 1,  -- key, value pairs
  199, 199,
  2, 2,
  50, 3,
  "bye", 4,
  200, 5
}

-- Таблица через pair выводится в порядке описания ее элементов
for k, v in pairs(t) do
  print(k, v)
end

119

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

Да, это я тоже видел, но сразу отказался, ибо нерационально. сделал проще. Так как uniq_trans_id однозначно указывает мне на номер робота старшими 8 битами и имеет вид 0х01ХХХ где 01 это номер робота, а Х для служебного использования в самом роботе.

tool[temp].num_row        = settings[temp].uniq_trans_id >> 12

А num_row мне все равно нужна, чтобы робот знал в какую строку делать вывод. Теперь вывод из таблицы полностью упорядочен, хотя надо бы еще проверочку воткнуть на корректность, на всякий случай smile

120

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

Народ, подскажите, вот этот пример для отправки сообщений из квик в телеграмм работает?
[url]https://smart-lab.ru/blog/686034.php[/url]
Лично у меня нифига не отправляет, вот и думаю, толи ручки кривые, толи не работает. От сторонних приложений, тем более exe я отказался, ибо фиг знает что там вообще накомпилировано.

121 (2022-12-12 13:33:56 отредактировано swerg)

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

Там же внешний exe-шник используется curl 

Попробуйте вот это решение
[url]https://quik2dde.ru/viewtopic.php?id=307[/url]

В любом случае без внешних библиотек не обойтись

122

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

Не, тогда придется отказаться.
Еще такой вопрос, я могу из скрипта временно отключить колбэки? Проблема в том, что при запуске робота сразу начинают вызываться колбэки, но пока таблица не сформирована именно коллбэки приводят робот в ступор с попыткой проиндексировать nil значение...

123

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

Отключить callback-функции можно вставив в начало каждой из них:

if флаг_работать_еще_нельзя then
     return
end

Изначально внутри тела скрипта присвоить флагу true, а как "уже можно" - присвоить false и callback'и начнут работать.
Другого пути нет

124

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

Почитал мануал к lua [url]https://articles.opexflow.com/wp-content/uploads/2022/02/lua.pdf[/url] относительно некоторых моментов, чтобы понять, но так и не совсем понял.
Например, касательно CreateDataSource.
Из нее дергаем данные ds, Error = CreateDataSource (CLASS, SEC, INTERVAL_M5); и получаем например количество свечей
numPrice = ds:Size()
Здесь как я понимаю Size() это функция с аргументом ds?
Т.е. в принципе numPrice = Size(ds) полностью идентична, только разная форма записи?
В принципе получается что и Open = ds:O(numPrice) я могу переписать как Open = O(ds,numPrice)
И для полного понимания, вообще как выглядит таблица ds? Не представляю до конца.

ds = {
        Size()
        O(i)
        H(i)
        L(i)
        C(i)
        .....
}

125 (2022-12-16 10:38:17 отредактировано dark184)

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

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