Вопрос-ответ

Автор записи: Дмитрий (Admin)
1 звезда2 звезды3 звезды4 звезды5 звезд (Голосов 8, среднее: 5,00 из 5)
Загрузка...
LogoNew
Если Ваш вопрос не имеет отношения к какой-то определенной статье на данном сайте, то, пожалуйста, задавайте его в комментариях здесь.

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

Вопрос-ответ: 2 309 комментариев

  1. Добрый день. Подскажите как настроить DebugView ,перепробовал варианты в Опция-Фильтр в окне Incluide писал следующее : QLua, qlua, info.exe, info, брал это в "" ни чего не помогает. Работает только при значке * но тогда нет фильтрации выводиться вся инфа по действиям компа- не удобно получается. Как отсечь не нужное?

  2. Добрый день! У вас много интересной информации на сайте, но я не нашел статьи на тему потоков в Lua и Квик. А интересует меня тема как правильно или скажем грамотно организуется получение данных или параметров от функций обратного вызова, а точнее получение данных из функции OnAllTreid и передача в функцию main. Насколько я понял это два разных потока, но как обращаться из одного в другой при этом не мешая и не теряя информацию потока ??? . Напишите статью с примером и пояснениями, пожалуйста. Мне кажется что это будет интересно не только мне.
    С уважением Андрей А.

    1. Добрый вечер, особо расписывать нечего, средствами qlua, примерно так

      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
      
       --передача событий из основного потока в main
      --с использованием межпоточных функций sinsert, sremove
      --для получения событий OnAllTrade должна быть открыта таблица обезличенных сделок
       
      local exitflag = true --флаг остановки скрипта
      local last_tradenum = 0 --№ последней обезличенной сделки
       
      --смешанная таблица "cb" для обработки очереди событий
      --нужный message раскомментировать
      local cb = {}
      function cb.SPBFUT_atr(t)
      	local sec_code = t.sec_code
      	local price = t.price
       
      	if sec_code == "RIU0" then
      		--уникальная обработка события по инструменту
       
      	end
      	--после сообщения скрипт остановится
      	message("SPBFUT_atr "..sec_code.."\nprice= "..tostring(price), 2); exitflag = true
      end
      function cb.SPBFUT_ql2(t)
      	local sec_code = t.sec_code
      	local offer_count = tonumber(t.offer_count)
      	if offer_count == 0 then return end
       
      	local coll_offer = t.offer
      	local offer = coll_offer[offer_count]
       
      	if sec_code == "RIU0" then
       
      	end
      	--после сообщения скрипт остановится
      --	message("SPBFUT_ql2 "..sec_code.."\noffer= "..tostring(offer.price), 2); exitflag = true
      end
       
      function cb.TQBR_atr(t)
      	local sec_code = t.sec_code
      	local price = t.price
       
      	if sec_code == "SBER" then
       
      	end
      	--после сообщения скрипт остановится
      --	message("TQBR_atr "..sec_code.."\nprice= "..tostring(price), 2); exitflag = true
      end
       
      function cb.TQBR_ql2(t)
      	local sec_code = t.sec_code
      	local offer_count = tonumber(t.offer_count)
      	if offer_count == 0 then return end
       
      	local coll_offer = t.offer
      	local offer = coll_offer[offer_count]
       
      	if sec_code == "SBER" then
       
      	end
      	--после сообщения скрипт остановится
      --	message("TQBR_ql2 "..sec_code.."\noffer= "..tostring(offer.price), 2); exitflag = true
      end
       
      function main()
      	--по этим инструментам будем получать события
      	local sec =
      	{
      		SPBFUT = {"RIU0", "SiU0"},
      		TQBR = {"GAZP", "LKOH", "SBER"}
      	}
       
      	for class_code, list in pairs(sec) do
      		for i=1, #list do
      			local sec_code = list[i]
      			cb[class_code..sec_code] = true --cb["TQBRSBER"] = true
      			--заодно подписываемся на получение событий OnQuote
      			if not IsSubscribed_Level_II_Quotes(class_code, sec_code) then
      				Subscribe_Level_II_Quotes(class_code, sec_code)
      			end
      		end
      	end
       
      	last_tradenum = getItem("all_trades", getNumberOf("all_trades")-1).trade_num
      	--message(tostring(last_tradenum))
       
      	exitflag = nil --начинаем получать события
      	while not exitflag do
       
      		local c = 0
      		while #cb > 0 do
      			local t = table.sremove(cb, 1) --удаляем первый элемент массива
      			cb[t.name](t) --и отправляем на обработку
       
      			--если событий много...
      			c = c + 1
      			if c == 50 then --подобрать значение, что бы расчет не грузил проц
      				c = 0
      				sleep(1) --перекур
      			end
      		end
       
      		sleep(1)
      	end
      end
       
      function OnStop()
      	exitflag = true
      	return 500
      end
       
      function OnAllTrade(alltrade)
      	--фильтр: скрипт остановлен или получает заново события после дисконекта
      	if exitflag or alltrade.trade_num < last_tradenum then return end
      	last_tradenum = alltrade.trade_num
       
      	local class_code = alltrade.class_code
      	if not cb[class_code..alltrade.sec_code] then return end
       
      	--это наш инструмент
      	alltrade.name = class_code.."_atr" --имя функции для обработки события
      	table.sinsert(cb, alltrade)
      end
       
      function OnQuote(class_code, sec_code)
      	--фильтр: скрипт остановлен или не "наш" инструмент
      	if exitflag or not cb[class_code..sec_code] then return end
       
      	--это наш инструмент
      	local ql2 = getQuoteLevel2(class_code, sec_code)
       
      	ql2.name = class_code.."_ql2" --имя функции для обработки события
      	ql2.class_code = class_code
      	ql2.sec_code = sec_code
       
      	--теперь в main нам известен класс и код инструмента этого снепшота стакана
      	table.sinsert(cb, ql2)
      end
  3. Добрый день!
    Перешел на Квик 8.5.2.11, версия Луа 5.3. (Раньше был Квик 8.2 х64 с Луа 5.1). В итоге все ДЛЛ рухнули. Библиотеки не грузятся.
    Код с вариантами:
    extern "C" LUALIB_API int luaopen_cCalSpred(lua_State *L)
    {
    //luaL_openlib(L, "cCalSpred", ls_lib, 0);
    //luaL_setfuncs(L, ls_lib, 0);
    luaL_newlib(L, ls_lib);
    return 0;
    }
    Варианты не работают.
    Что там нужно сделать? Возможно уже с этим сталкивались?

    1. Ответ Дмитрия:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      //хидеры и либу брать с https://sourceforge.net/projects/luabinaries/files/5.3.5/Windows%20Libraries/Static/
      //и не забыть поставить в свойствах проекта платформу x64
      // !!!! ### для VS2017(на ней проверял) : lua - 5.3.5_Win64_vc14_lib.zip
      //Для сборки ddl под quik 8.5 и lua 5.3 нужно полностью заменить последний блок кода
      //(регистрация названия библиотеки), например на :
      extern "C" LUALIB_API int luaopen_QluaMultithreaded(lua_State *L) {
      	lua_newtable(L);
      	luaL_setfuncs(L, ls_lib, 0);
      	lua_pushvalue(L, -1);
      	lua_setglobal(L, "QluaMultithreaded");
      	return 0;
      }
      1. Спасибо.
        DLL сконнектилась. Все работает без ошибок. С самого начала использовал - lua-5.3.5_Win64_dll16_lib. Это переделывать на lua - 5.3.5_Win64_vc14_lib.zip не стал, с ней тоже работает.
        Начались какие-то проблемы с данными. Часть данных из Квик идет нормально, а часть не приходит, чего раньше не было. В общем, какие-то чудеса творятся.) Пока непонятно. Ну, с этим пока сам разбираться буду.
        Еще раз спасибо за помощь.

  4. Привет! Попробуйте так.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    local next_tm = 0
    function main()
     
         local LASTCHANGE = getParamEx (Class, SecCode, "LASTCHANGE").param_value
    --
        local tm = os.time()
        if tm > next_tm then
          next_tm = tm + 5
          if LASTCHANGE > "0.20" then
            message("БОЛЬШЕ",1)
          elseif LASTCHANGE < "0.17" then
            message("МЕНЬШЕ",2)
          else
            message("МЕЖДУ",3)
          end
        end
        sleep(1000)
    end
  5. 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
    
     IsRun = true
    function OnInit()																				
    		TableRTS = AllocTable()																 
    		AddColumn(TableRTS, 1,"Дата", true, QTABLE_DATE_TYPE, 13)									
    		AddColumn(TableRTS, 2,"Время", true, QTABLE_TIME_TYPE, 10)
    		AddColumn(TableRTS, 3,"Код", true, QTABLE_STRING_TYPE, 10)
    		AddColumn(TableRTS, 4,"Цена", true, QTABLE_INT_TYPE, 10)									
    		AddColumn(TableRTS, 5,"ГО", true, QTABLE_DOUBLE_TYPE, 10)
    		AddColumn(TableRTS, 6,"Лимит, руб.", true, QTABLE_DOUBLE_TYPE, 13)
    		AddColumn(TableRTS, 7,"Контракты", true, QTABLE_INT_TYPE, 13)
    		AddColumn(TableRTS, 8,"Позиция", true, QTABLE_INT_TYPE, 10)
    		CreateWindow(TableRTS)
    		Clear(TableRTS)  
    		SetWindowCaption(TableRTS, "Таблица параметров RIZ7")	
    		SetWindowPos(TableRTS, 0, 10, 600, 70)	
    		InsertRow(TableRTS, -1)
     
    end
     
    function main()
    	while IsRun do
    		local TRADEDATE = getInfoParam("TRADEDATE")
    		local SERVERTIME = getInfoParam("SERVERTIME")
    		local SecCode = "USD000UTSTOM"
    		local Class = "ММВБ Валюта: ЕТС"
    		local LastPrice = getParamEx (Class, SecCode, "LAST").param_value         
    		local BIDDEPTHT = getParamEx (Class, SecCode, "BIDDEPTHT").param_value
    		local VALUE = getParamEx (Class, SecCode, "VALUE").param_value
    		local LASTCHANGE = getParamEx (Class, SecCode, "LASTCHANGE").param_value
    		SetCell(TableRTS,1,1,tostring(TRADEDATE))
    		SetCell(TableRTS,1,2,tostring(SERVERTIME))
    		SetCell(TableRTS,1,3,tostring(SecCode))
    		SetCell(TableRTS,1,4,tostring(LastPrice))
    		SetCell(TableRTS,1,5,tostring(BIDDEPTHT))
    		SetCell(TableRTS,1,6,tostring(VALUE))
    		SetCell(TableRTS,1,7,tostring(LASTCHANGE))			
    		if LASTCHANGE > "0.20" then
                    message("БОЛЬШЕ",1)
                    sleep(100000)
                elseif LASTCHANGE < "0.17" then
                    message("МЕНЬШЕ",2)    
    				sleep(100000)
    		end
     
    		sleep(1000) 
    	end	 
     
    end	 
     
    function OnStop()
          IsRun = false
          DestroyTable(TableRTS)
     
    end
  6. Добрый вечер! Не подскажите как сделать так что бы задержка в основном цикле и сообщении была разная.А то у меня и сообщение и цикл зависает на столько сколько я прописываю для сообщения!

    IsRun = true
    function OnInit()
    TableRTS = AllocTable()
    AddColumn(TableRTS, 1,"Дата", true, QTABLE_DATE_TYPE, 13)
    AddColumn(TableRTS, 2,"Время", true, QTABLE_TIME_TYPE, 10)
    AddColumn(TableRTS, 3,"Код", true, QTABLE_STRING_TYPE, 10)
    AddColumn(TableRTS, 4,"Цена", true, QTABLE_INT_TYPE, 10)
    AddColumn(TableRTS, 5,"ГО", true, QTABLE_DOUBLE_TYPE, 10)
    AddColumn(TableRTS, 6,"Лимит, руб.", true, QTABLE_DOUBLE_TYPE, 13)
    AddColumn(TableRTS, 7,"Контракты", true, QTABLE_INT_TYPE, 13)
    AddColumn(TableRTS, 8,"Позиция", true, QTABLE_INT_TYPE, 10)
    CreateWindow(TableRTS)
    Clear(TableRTS)
    SetWindowCaption(TableRTS, "Таблица параметров RIZ7")
    SetWindowPos(TableRTS, 0, 10, 600, 70)
    InsertRow(TableRTS, -1)

    end

    function main()
    while IsRun do
    local TRADEDATE = getInfoParam("TRADEDATE")
    local SERVERTIME = getInfoParam("SERVERTIME")
    local SecCode = "USD000UTSTOM"
    local Class = "ММВБ Валюта: ЕТС"
    local LastPrice = getParamEx (Class, SecCode, "LAST").param_value
    local BIDDEPTHT = getParamEx (Class, SecCode, "BIDDEPTHT").param_value
    local VALUE = getParamEx (Class, SecCode, "VALUE").param_value
    local LASTCHANGE = getParamEx (Class, SecCode, "LASTCHANGE").param_value
    SetCell(TableRTS,1,1,tostring(TRADEDATE))
    SetCell(TableRTS,1,2,tostring(SERVERTIME))
    SetCell(TableRTS,1,3,tostring(SecCode))
    SetCell(TableRTS,1,4,tostring(LastPrice))
    SetCell(TableRTS,1,5,tostring(BIDDEPTHT))
    SetCell(TableRTS,1,6,tostring(VALUE))
    SetCell(TableRTS,1,7,tostring(LASTCHANGE))
    if LASTCHANGE > "0.20" then
    message("БОЛЬШЕ",1)
    sleep(100000)
    elseif LASTCHANGE < "0.17" then
    message("МЕНЬШЕ",2)
    sleep(100000)
    end

    sleep(1000)
    end

    end

    function OnStop()
    IsRun = false
    DestroyTable(TableRTS)

    end

  7. Добрый день, такой вопрос: сколько скриптов возможно одновременно запустить в Quik? Это для тестирования, сделки не производиться, но каждый скрипт выводит инфу в Excel. Или может быть есть ограничения по выводу через DDE?

  8. Добрый вечер. Прошу, помогите разобраться с SetUpdateCallback и SetEmptyCallback
    Какую строку кода (используя SetUpdateCallback или SetEmptyCallback) надо добавить в нижеуказанный код, чтобы при появлении новой свечи вывести сообщение "Появилась новая свеча"?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    IsRun = true;
     
    function OnStop()
       IsRun = false;
    end; 
     
    function main()
    	while IsRun do
     		ds, Error = CreateDataSource("SPBFUT", "SiM0", INTERVAL_M1); --получаем свечки в набор данных
    		while (Error == "" or Error == nil) and ds:Size() == 0 do sleep(1) end
    		if Error ~= "" and Error ~= nil then message("Ошибка подключения к графику: "..Error) end
     
    	end
    end
    1. Смотрите документацию по QLua (в интернете много информации)

      Нужно использовать SetUpdateCallback
      Формат вызова:
      BOOLEAN res SetUpdateCallback (FUNCTION callback_function)
      В качестве параметра принимает функцию обратного вызова.
      Формат функции обратного вызова:
      function call_back(NUMBER index)
      Параметры:
      • index – номер изменившейся свечки. Индексы свечек начинаются с 1.
      Функция возвращает «true» в случае успешного завершения, иначе – «false».
      Код:

      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
      
      IsRun = true;
       
      function OnStop()
         IsRun = false;
      end; 
       
      function main()
              ds, Error = CreateDataSource("SPBFUT", "SiM0", INTERVAL_M1); -- создаем источник данных
      	while (Error == "" or Error == nil) and ds:Size() == 0 do sleep(1) end
      	if Error ~= "" and Error ~= nil then 
                   message("Ошибка подключения к графику: "..Error) 
                   OnStop()  --- принудительное завершение скрипта
             еlse
                    if not SetUpdateCallback (call_back)   then    --- подписка на функцию call_back  (вызывается при появлении новой свечи)
                          message("Ошибка  подписка на функцию call_back") 
                          OnStop()  --- принудительное завершение скрипта
                    end          
             end 
       
      	while IsRun 	do	 -- 
                  -----   ----
                  sleep (10)
      	end
      end
       
      function call_back(index)
         message(  "Появилась новая свеча " .. index)
      end
        1. while (Error == "" or Error == nil) and ds:Size() == 0 do sleep(1) end
          так нельзя делать вообще
          1. данных может не быть, тупо не было сделок никогда (лпционы, например);
          2, после дисконекта данные могут появится часов через 5
          цикл будет крутить "вечно", а ошибки не будет.
          вот так можно сделать обезличенный калбэк:

          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
          
          local exitflag
          local DS = {}
          local DSINDEX = {}
          local function sb(ds, key, market, ticker, index) 
          	local o_index = DSINDEX[key]
          	if o_index == 0 then
          		DSINDEX[key] = ds:Size()
          		message("Зашёл "..key.."\n index= "..index, 2)
          		--
          		return
          	end
           
          	if index > o_index then
          		DSINDEX[key] = index
          		message("Новый бар "..key.."\n o_index= "..o_index.."\n C= "..ds:C(o_index), 2)
          		--
          	end
          end
          local function cds(key, market, ticker, interval)
          	local ds, err = CreateDataSource(market, ticker, interval)
          	assert(ds, ticker.." "..tostring(err))
          	DSINDEX[key] = 0
          	DS[key] = ds
          	ds:SetUpdateCallback(function(...) sb(ds, key, market, ticker, ...) end)
          	sleep(1000)
          end
           
          function main()
          	cds("SiM0_M1", "SPBFUT", "SiM0", INTERVAL_M1)
          	cds("SiM0_M2", "SPBFUT", "SiM0", INTERVAL_M2)
           
          	cds("RIM0_M1", "SPBFUT", "RIM0", INTERVAL_M1)
          	cds("SiM0_M2", "SPBFUT", "RIM0", INTERVAL_M2)
           
          	while not exitflag do
          		sleep(1)
          	end
           
          	local index = DSINDEX["SiM0_M1"]
          	message("Exit SiM0_M1\n C= "..DS["SiM0_M1"]:C(index - 1), 2)
           
          	for k, ds in pairs(DS) do
          		ds:Close()
          	end
          end
          function OnStop()
          	exitflag = true
          	return 1000
          end
          1. а, забыл,
            в калбэке первой строкой стоит сделать проверку
            if exitflag then return end
            иначе может быть ошибка при выключении скрипта, но тут это не критично

            1. Здравствуйте kalikazandr!

              Ваши замечания правильные. Я ответил "Good_man" формально, исходя из того, что , похоже, он только начал заниматься программированием на QLua.

              1. Здравствуйте!
                печально, что толку от "правильности" в рамках квика - нет, чего не коснись - работает криво.
                это касается и других подобных ПО, которые пишут люди, никак не связанные с торговлей.
                и пишут, и поправляют без конца, потому-что не понимают, что пишут и как это должно работать.

  9. Здравствуйте. Подскажите как работать с метками.
    Добавил я на график несколько меток.
    С помощью: AddLevel()
    А как изменить местоположение определенной метки?
    Я понимаю сначала DelLabel(), а потом снова добавить AddLevel()
    Или через SetLabelParams()
    Но не пойму где взять: label_id–идентификатор метки

    1. для начала добавляете тестовую метку, пофик на какой бар, получаете ее id и сразу удаляете.
      test_id = AddLebel(tag, param)
      теперь вам известно примерное кол-во меток на графике:
      for chart_id =1, test_id do
      local param = GetLabelParams(tag, chart_id)
      if type(param) == "table" then
      --это метка, ее id = chart_id
      end
      end