Нужные функции

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

math_round() -- Округляет число до указанной точности
GetClassBySec() -- Возвращает код класса по коду бумаги
WaitUpdateDataAfterReconnect() -- Ждет подключения к серверу, после чего ждет еще UpdateDataSecQty секунд подгрузки пропущенных данных с сервера
GetServerDateTime() -- Возвращает текущую дату/время сервера в виде таблицы datetime
StrToTime() -- Приводит время из строкового формата ЧЧ:ММ к формату datetime
CheckDemo() -- Узнать является ли терминал демо от компании Arqa, или демо брокера Открытие
GetTotalnet() -- Получает текущую чистую позицию по инструменту
GetFreeMoney() -- Возвращает доступные средства
GetCorrectPrice() -- Приводит переданную цену к требуемому для транзакции по инструменту виду
GetPriceForMarketOrder() -- Возвращает корректную цену для рыночной заявки по текущему инструменту
SetOrder() -- Выставляет обычную лимитную заявку
SetMarketOrder() -- Выставляет рыночную (по сути) заявку
GetOrderAverTradesPrice() -- Возвращает среднюю цену сделок по заявке
CheckOrder() -- Проверяет наличие в системе заявки с определенным ID транзакции
GetOrderNum() -- Возвращает номер заявки по ее ID транзакции
WaitOrderComplete () -- Ожидает исполнения заявки по ID транзакции
Set_SL() -- Выставляет 'Стоп лимит' заявку
SetTP() -- Выставляет 'Тейк профит' заявку
SetTP_SL() -- Выставляет 'Тейк профит и Стоп лимит' заявку
CheckStopOrder() -- Проверяет наличие в системе стоп-заявки с определенным ID транзакции
GetStopOrderNum() -- Возвращает номер стоп-заявки по ее ID транзакции
CheckStopOrderActive() -- Проверяет по номеру активна ли стоп-заявка
KillOrder() -- Снимает заявку
Kill_SO() -- Снимает стоп-заявку
StackFIFO() -- Создает объект стека FIFO(Первым вошел, первым вышел)
StaticVar.dll -- Обмен данными между Lua-скриптами в QUIK
СОХРАНЕНИЕ ПАРАМЕТРОВ СКРИПТА QLUA(LUA) МЕЖДУ ЗАПУСКАМИ

Добавить комментарий

Нужные функции: 144 комментария

  1. Подскажите пожалуйста, есть такие функции в квике и если нет возможно как то это реализовать?
    1. Поиск и (или) открытие окна графика в квике через Lua по идентификатору или как то еще

      1. Не за что,
        я пользую 'lua_multilist' для установки соединения(автологин) и обработки системных сообщений (ошибки всякие, типа - нельзя установить соединение).
        Графики не открываю програмно - нет нужды, и не будет точно, достаточно 1 графика для торговли(визуализации), который связан якорем с "таблицей текущих торгов" и одного стакана.
        Если вам для стратегии нужно больше графиков и бот от них зависит - это нужно выкинуть бота в помойку и продумать алгоритм, который не зависит от открытых графиков или стаканов или еще чего.
        Робот не должен завязываться на всякую хрень.
        Задача робота - бабло, чем меньше прослойка, между "бабло" и необходимой для этого функциональностью, тем надёжнее будет бабло.
        Иначе, с вероятностью в 100% будет минус бабло. Как то так.

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

          1. Индикаторы основываются на исторических данных - было, да былью поросло.
            Да еще и обезличенные сделки (и не только), по которым строятся графики, переписывают каждый клиринг, что бы скрыть крупных ММ и что бы графики были "красивыми" для всяких там индикаторов.
            Пользоваться графиками и индикаторами в принципе плохая затея. Это вроде гадания на кофейной гуще.
            Невозможно определить куда двинет цена с никакой вероятностью.
            Будет "отбой" от уровня или будет "пробой" уровня - не знают даже те, кто сейчас двигает цену.
            Проще прогноз погоды послушать - более достоверная информация.
            Ну или заняться фундаментальным анализом, покататься по предприятиям, посмотреть, чем они дышат.

            1. А на что тогда ориентироваться если все не подходит, графики и индикаторы дают хоть какую то вероятность дальнейшего движения. Закономерности индикаторов существуют все равно и они работают, да может быть вход будет не по идеальным ценам но вероятность продолжения движения все равно есть. Если без них то работать придется либо с вероятностью 50-50 либо в обще без ее учета, что в принципе одно и тоже что 50-50. Ну и соответственно на комиссии прогоришь в итоге

            2. Простому смертному трейдеру который торгует через квик остается лишь следовать за рынком то есть за ценой и объемами которая и формирует значения индикаторов, а цена как известно учитывает всю существую на данный момент информацию и ожидание информации в будущем, или какое то текущее событие или которое должно произойти в будущем. Рынок живет ожиданиями. И если появился сигнал это значит что вероятность уже сместилась в большую сторону, а на сколько уйдет цена это уже вопрос статистики.

              1. С какой вероятностью будет 1 или 2 из [1; 2]? 50х50 или как то иначе?
                Например, 2 не будет никогда и это нормально с точки зрения вероятности.
                Строить прогнозы 50х50 или вообще говорить о смещении вероятности в какую-то сторону - полная чушь, как и ожидания.
                Вероятности вообще пофик до людишек с их прогнозами.
                А рынок - да, живет ожиданиями, только оправдываются ожидания у 1-2% трейдеров.

                  1. А счет у него растет? или так, просто про арифметику?
                    Если человек пишет книгу о трединге, скорее всего, в трейдинге у него не срослось, иначе не писал бы.
                    Т.к. на трейдинг можно потратить много времени и ничего более не уметь или не хотеть, то писанина - самое то.
                    Интернет пестрит всякими гуру-бумагомараками и с докторскими степенями хватает тоже гуру, которые слили пару раз депо и учат других, как не сливать.

            3. Вот это что серьезно так делают ?
              "Да еще и обезличенные сделки (и не только), по которым строятся графики, переписывают каждый клиринг, что бы скрыть крупных ММ и что бы графики были "красивыми" для всяких там индикаторов."
              Знаю что есть заявки типа айсберг, которые и так размазывают объемы но чтобы переписывать сделки, интересно у какого брокера это происходит?

  2. быстрый поиск информации по инструменту

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    local function SecuritiesInfo(sec_code)
    	local function cb(code)
        if code == sec_code then return true end
        return false
      end
    	local res = SearchItems("securities", 0, getNumberOf("securities")-1, cb, "code")
    	for i=1, #res do
    		res[i] = getItem("securities", res[i])
    	end
    	return res
    end
    function main()
    	local t1 = SecuritiesInfo("SBER")
    	table.msg(t1, 2000)
    	local t2 = SecuritiesInfo("RIZ0")
    	table.msg(t2, 2000)
    	local t3 = SecuritiesInfo("Si74000BX0B")
    	table.msg(t3, 1)
    end
  3. Перешел на Quik 8.5+ и столкнулся, как раз с проблемой, что ["PRICE"] = tostring(price), передает строку 5600.0 т.е. есть потребность менять ''.' на ','. Попробовал функцию GetCorrectPrice() . Она выдает ошибку Syntax error while compiling ... invalid escape sequence near ''[\.' Это в строке:
    string.gsub(tostring(price),'[\.]+', ',')
    Т.е. как я понимаю, надо "заэкранировать" точку каким-то образом? Может в луа 5.3 этот вариант не работает?

  4. Для отладки добавил функции: arr_to_str и msg

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    
    function table.val_to_str (v)
      if "string" == type( v ) then
        v = string.gsub( v, "\n", "\\n" )
        if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
          return "'" .. v .. "'"
        end
        return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
      end
      return "table" == type( v ) and table.tab_to_str( v ) or tostring( v )
    end
     
    function table.key_to_str (k)
      if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
        return k
      end
      return "[" .. table.val_to_str( k ) .. "]"
    end
     
    function table.tab_to_str(tbl)
      if type(tbl)~='table' then return table.val_to_str(tbl) end
      local result, done = {}, {}
      for k, v in ipairs( tbl ) do
        table.insert( result, table.val_to_str( v ) )
        done[ k ] = true
      end
      for k, v in pairs( tbl ) do
        if not done[ k ] then
          table.insert( result, table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
        end
      end
      return "{" .. table.concat( result, "," ) .. "}"
    end
     
    function table.arr_to_str(tbl, s)
    	local result, done= {"{"}, {}
    	for i = 1, #tbl do
    		if type(tbl[i]) == "table" then
    			local str = table.concat(table.arr_to_str(tbl[i], s.." "), ",\n")
    			result[#result+1] = s..table.key_to_str(i).."= "..str:gsub("{,", "{")
    		else
    			result[#result+1] = s..table.key_to_str(i).."= "..table.val_to_str(tbl[i])
    		end
    		done[i] = true
    	end
     
    	local rnum = {}
    	for k, v in pairs(tbl) do
    		if not done[k] and tonumber(k) then
    			rnum[#rnum+1] = k
    			done[k] = true
    		end
    	end
    	if #rnum > 0 then
    		table.sort(rnum, function (a, b) return tonumber(a)  0 then
    		table.sort(rstr, function (a, b) return a < b end)
    		for i=1, #rstr do
    			local k = rstr[i]
    			if type(tbl[k]) == "table" then
    				local str = table.concat(table.arr_to_str(tbl[k], s.." "), ",\n")
    				result[#result+1]= s..table.key_to_str(k).."= "..str:gsub("{,", "{")
    			else
    				result[#result+1]= s..table.key_to_str(k).."= "..table.val_to_str(tbl[k])
    			end
    		end
    	end
     
    	result[#result + 1] = s:sub(1, #s-1).."}"
     
    	return result
    end
     
    function table.save_to_read(directory, tbl)
    	if type(tbl) ~= "table" then return end
    	local f= io.open(directory, 'w'); if not f then return end
     
    	local r = table.arr_to_str(tbl, "")
    	table.remove(r, 1); table.remove(r, #r)
     
    	f:write(table.concat(r,",\n")); f:flush(); f:close()
    end
     
    function table.save_to_load(directory, tbl)
    	if type(tbl) ~= "table" then return end
    	local f= io.open(directory, 'w'); if not f then return end
     
    	local r = table.arr_to_str(tbl, "")
    	table.remove(r, 1)
     
    	f:write("{\n"..table.concat(r,",\n")); f:flush(); f:close()
    end
     
    function table.read(directory)
      --преобразует строку: "key=val," в таблицу
    	local f = io.open(directory, "r")
      if not f then
    		sleep(1)
    		f = io.open(directory, "r")
    		if not f then return end
    	end
     
      local str = "{"..f:read("*a").."}"; f:close()
     
      local fn = loadstring("return "..str)
      if type(fn) == "function" then
        return fn()
      end
    end
     
    function table.load(directory)
      --преобразует строку: "{key=val,}" в таблицу
    	local f = io.open(directory, "r")
    	if not f then
    		sleep(1)
    		f = io.open(directory, "r")
    		if not f then return end
    	end
     
      local str = f:read("*a"); f:close()
     
    	local fn = loadstring("return "..str)
      if type(fn) == "function" then
        return fn()
      end
    end
     
    function table.msg(tbl, slp)
    	if type(tbl) ~= "table" then
    		tbl = {tostring(tbl)}
    	end
    	local p = getScriptPath().."\\logmsg.txt"
    	table.save_to_read(p, tbl)
    	os.execute("start /I "..p)
     
    	local slp = slp or 5000
    	sleep(slp)
    end
     
    function main()
    -- в цикле table.msg вызывать 1 раз в 5 секунд
     
    local t = nil
    table.msg(t, 1000)
     
    t= "Hi"
    table.msg(t, 1000)
     
    t= 123
    table.msg(t, 1000)
     
    t = {
    	"X", "Y", "Z",
    	X = 1,
    	["543"] = 22,
    	["1"] = 7,
    	[54] = "CCC",
    	[9] = "AAA",
    	B = {
    		"x", "y", "z",
    		c = 2,
    		[240] = {
    			10,20,30,
    			x = 3,
    			tab = {
    				["500"] = 22,
    				["20"] = 7,
    				[50] = "ccc",
    				[30] = "aaa",
    			}
    		},
    	},
    }
     
    table.msg(t, 1000)
     
    local t1 = table.read(getScriptPath().."\\logmsg.txt")
    if type(t1) == "table" then
    	message("t1.B[240].x= "..t1.B[240].x, 1)
    else
    	message("t1= nil", 3)
    end
     
    table.save_to_load(getScriptPath().."\\logmsg1.txt", t1)
     
    local t2 = table.load(getScriptPath().."\\logmsg1.txt")
    if type(t2) == "table" then
    	message("t2.B[240].tab[50]= "..t2.B[240].tab[50], 1)
    else
    	message("t2= nil", 3)
    end
     
    end
    1. увидел, что как то сохранилось криво или не там скопировал)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      
      function table.arr_to_str(tbl, s)
      	local result, done= {"{"}, {}
      	for i = 1, #tbl do
      		if type(tbl[i]) == "table" then
      			local str = table.concat(table.arr_to_str(tbl[i], s.." "), ",\n")
      			result[#result+1] = s..table.key_to_str(i).."= "..str:gsub("{,", "{")
      		else
      			result[#result+1] = s..table.key_to_str(i).."= "..table.val_to_str(tbl[i])
      		end
      		done[i] = true
      	end
       
      	local rnum = {}
      	for k, v in pairs(tbl) do
      		if not done[k] and tonumber(k) then
      			rnum[#rnum+1] = k
      			done[k] = true
      		end
      	end
      	if #rnum > 0 then
      		table.sort(rnum, function (a, b) return tonumber(a)  0 then
      		for i=1, #rstr do
      			local k = rstr[i]
      			if type(tbl[k]) == "table" then
      				local str = table.concat(table.arr_to_str(tbl[k], s.." "), ",\n")
      				result[#result+1]= s..table.key_to_str(k).."= "..str:gsub("{,", "{")
      			else
      				result[#result+1]= s..table.key_to_str(k).."= "..table.val_to_str(tbl[k])
      			end
      		end
      	end
       
      	result[#result + 1] = s:sub(1, #s-1).."}"
       
      	return result
      end
  5. 1
    2
    3
    4
    5
    6
    7
    8
    9
    
     function GetClassBySec(code) -- Функция возвращает код класса по коду инструмента
       --------------------------------------------------------------------------------------------------------------------------
       for class in string_gmatch("STOCK_USA,SPBXM,FQBR,TQBR,QJSIM,SPBFUT,", "(%P*),") do
          for sec in string_gmatch(getClassSecurities(class), "(%P*_*%P*_*%P*),") do
             if sec == code then return class end
          end
       end
       --------------------------------------------------------------------------------------------------------------------------
    end

    Здравствуйте. Функция не возвращает код класса: "STOCK_USA" и "FQBR" ("SPBXM" - не проверял). В чем подвох?

      1. Привет, все проще
        local function getClassCode(ticker) -- Функция возвращает код класса по коду инструмента
        for i= 0, getNumberOf("securities")-1 do
        local item = getItem("securities", i)
        if item.code == ticker then
        -- message("getClassCode: "..tostring(item.class_code).." "..ticker,2)
        return item.class_code
        end
        end
        return ""
        end

        1. Спасибо, Дмитрию, с его помощью так написал

          1
          2
          3
          4
          5
          6
          7
          8
          9
          
          function GetClassBySec(code) -- Функция возвращает код класса по коду инструмента
             --------------------------------------------------------------------------------------------------------------------------
             for class in string_gmatch("STOCK_USA,SPBXM,FQBR,TQBR,QJSIM,SPBFUT,", "(%P*_*%P*),") do
                for sec in string_gmatch(getClassSecurities(class), "(%P*%.*%P*-*%P*),") do
                   if sec == code then return class end
                end
             end
             --------------------------------------------------------------------------------------------------------------------------
          end
            1. kalikazandr ваш код элегантнее и эффективнее, но тикер может быть в нескольких классах.
              Поэтому можно предложить небольшую модификацию вашего кода:

              1
              2
              3
              4
              5
              6
              7
              8
              9
              10
              11
              12
              
              local function getClassCode (ticker) -- Функция возвращает таблицу кодов классов по тикеру инструмента
                local tbl = {}
                ---  !!! Некоторые тикеры попадают в несколько классов ---
                ----   !!  Таблица securities не  отсортирована по тикерам . Поэтому полный перебор ----
                 for i= 0, getNumberOf("securities") - 1 do
                      local item = getItem("securities", i)
                      if item.code == ticker then
                          tbl [#tbl +1]  = item.class_code
                      end
                end
                return tbl
              end
              1. согласен, ваша правда, но список классов по тикеру ничего особо не даст, т.к. нет параметра, который будет уточнять правило поиска, например, что бы различить акции от неполных лотов этих акций

                1. Костя, вот так тебе пойдет

                  1
                  2
                  3
                  4
                  5
                  6
                  7
                  8
                  9
                  10
                  11
                  12
                  13
                  14
                  15
                  16
                  17
                  18
                  19
                  20
                  21
                  22
                  
                  local ClassCodes =
                  {
                    STOCK_USA = true,
                    SPBXM = true,
                    FQBR = true,
                    TQBR = true,
                    QJSIM = true,
                    SPBFUT = true
                  }
                  local function getClassCode (ticker) -- Функция возвращает класс по тикеру инструмента
                     local class_code = ClassCodes[ticker]
                     if class_code then return class_code end
                   
                     for i= 0, getNumberOf("securities") - 1 do
                          local item = getItem("securities", i)
                          if item.code == ticker and ClassCodes[item.class_code] then
                              ClassCodes[ticker] = item.class_code --для повторного обращения
                              return item.class_code
                          end
                    end
                    return ""
                  end