<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>Форум QUIK [тема: Ошибка при вызове sendTransaction из нескольких потоков]</title>
		<link>http://forum.quik.ru</link>
		<description>Новое в теме Ошибка при вызове sendTransaction из нескольких потоков форума  на сайте Форум QUIK [forum.quik.ru]</description>
		<language>ru</language>
		<docs>http://backend.userland.com/rss2</docs>
		<pubDate>Sun, 26 Apr 2026 00:00:33 +0300</pubDate>
		<item>
			<title>Ошибка при вызове sendTransaction из нескольких потоков</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message21891/topic2343/">Ошибка при вызове sendTransaction из нескольких потоков</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			<br />====quote====<br /><a class="blog-p-user-name" id="bp_TM8xo7c4" href="/user/2799/" bx-tooltip-user-id="2799">SG</a> написал:<br />Если функцию sendTransaction вызвать одновременно из двух потоков - один вызов из main, а другой из функции обратного вызова, то на корректную транзакцию может прийти ответ с ошибкой &quot;Неверный формат заявки&quot;.<br /><br />Ниже приведён скрипт, воспроизводящий проблему. В нём нужно перед запуском заменить номер счёта в первой строке. Для появления ошибки может потребоваться несколько запусков скрипта.<br /><br />В терминале версии 7.2.2.3 ошибки не было. В версиях 7.4, 7.5 и 7.6 ошибка есть.<br /><br />Скрипт:<br /> &nbsp; &nbsp; Скрытый текст &nbsp; &nbsp; &nbsp; 
====code====
<pre>&nbsp;&nbsp; local&nbsp;&nbsp;accountName&nbsp;&nbsp;=&nbsp;&nbsp; "SPBFUT00000"&nbsp;&nbsp;&nbsp;&nbsp;-- заменить на правильный номер счёта 
 local&nbsp;&nbsp;classCode&nbsp;&nbsp;=&nbsp;&nbsp; "SPBFUT" 
 local&nbsp;&nbsp;secCode&nbsp;&nbsp;=&nbsp;&nbsp; "SRZ6" 
 local&nbsp;&nbsp;priceMin&nbsp;&nbsp;=&nbsp;&nbsp; nil 
 local&nbsp;&nbsp;logFile&nbsp;&nbsp;=&nbsp;&nbsp; nil 
 local&nbsp;&nbsp;running&nbsp;&nbsp;=&nbsp;&nbsp; true 
 local&nbsp;&nbsp;testStarted&nbsp;&nbsp;=&nbsp;&nbsp; false 
 local&nbsp;&nbsp;activeOrders&nbsp;&nbsp;=&nbsp;&nbsp;{}

 function&nbsp;&nbsp; Log ( message )
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;&nbsp;logFile ~ =&nbsp;&nbsp; nil&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;timestamp&nbsp;&nbsp;=&nbsp;&nbsp; os.date ( "&#91;%Y-%m-%d %X&#93;" )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logFile:write(timestamp&nbsp;&nbsp;..&nbsp;&nbsp; " "&nbsp;&nbsp; ..&nbsp;&nbsp; message&nbsp;&nbsp; ..&nbsp;&nbsp; "&#92;n" )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logFile:flush()
&nbsp;&nbsp;&nbsp;&nbsp;end 
 end 

 function&nbsp;&nbsp; LogTable ( message , tbl)
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;&nbsp;res&nbsp;&nbsp;=&nbsp;&nbsp;{}
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;&nbsp;key, value&nbsp;&nbsp;in&nbsp;&nbsp;pairs(tbl)&nbsp;&nbsp;do 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;vtype&nbsp;&nbsp;=&nbsp;&nbsp;type(value)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;vtype&nbsp;&nbsp;=&nbsp;&nbsp;=&nbsp;&nbsp; "nil"&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res&#91; # res&nbsp;&nbsp;+&nbsp;&nbsp; 1 &#93;&nbsp;&nbsp;=&nbsp;&nbsp;key&nbsp;&nbsp;..&nbsp;&nbsp; " = &#60;nil&#62;" 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif&nbsp;&nbsp;vtype&nbsp;&nbsp;=&nbsp;&nbsp;=&nbsp;&nbsp; "number"&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res&#91; # res&nbsp;&nbsp;+&nbsp;&nbsp; 1 &#93;&nbsp;&nbsp;=&nbsp;&nbsp;key&nbsp;&nbsp;..&nbsp;&nbsp; " = "&nbsp;&nbsp; ..&nbsp;&nbsp;value
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elseif&nbsp;&nbsp;vtype&nbsp;&nbsp;=&nbsp;&nbsp;=&nbsp;&nbsp; "string"&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res&#91; # res&nbsp;&nbsp;+&nbsp;&nbsp; 1 &#93;&nbsp;&nbsp;=&nbsp;&nbsp;key&nbsp;&nbsp;..&nbsp;&nbsp; " = "&nbsp;&nbsp; ..&nbsp;&nbsp; string.format ( "%q" , value)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; res&#91; # res&nbsp;&nbsp;+&nbsp;&nbsp; 1 &#93;&nbsp;&nbsp;=&nbsp;&nbsp;key&nbsp;&nbsp;..&nbsp;&nbsp; " = ?" 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end 
&nbsp;&nbsp;&nbsp;&nbsp;end 
&nbsp;&nbsp; Log( message&nbsp;&nbsp; ..&nbsp;&nbsp; table.concat (res,&nbsp;&nbsp;"; " ))
 end&nbsp;&nbsp;&nbsp;&nbsp;

 function&nbsp;&nbsp; PlaceOrders (price, count, id)
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;&nbsp;i&nbsp;&nbsp;=&nbsp;&nbsp; 1 , count&nbsp;&nbsp;do 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;transaction&nbsp;&nbsp;=&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "ACTION" &#93;&nbsp;&nbsp;=&nbsp;&nbsp; "NEW_ORDER" ,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "CLASSCODE" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;classCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "SECCODE" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;secCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "ACCOUNT" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;accountName,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "OPERATION" &#93;&nbsp;&nbsp;=&nbsp;&nbsp; "B" ,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "PRICE" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;tostring(price),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "QUANTITY" &#93;&nbsp;&nbsp;=&nbsp;&nbsp; "1" ,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "TRANS_ID" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;tostring(id),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogTable( "Placing order: " , transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp; message&nbsp;&nbsp; =&nbsp;&nbsp; sendTransaction (transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log( "Result: "&nbsp;&nbsp; ..&nbsp;&nbsp;id&nbsp;&nbsp;..&nbsp;&nbsp; ", &#91;"&nbsp;&nbsp; ..&nbsp;&nbsp; message&nbsp;&nbsp; ..&nbsp;&nbsp; "&#93;" )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;&nbsp;=&nbsp;&nbsp;id&nbsp;&nbsp;+&nbsp;&nbsp; 1 
&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;&nbsp;&nbsp;
 end 

 function&nbsp;&nbsp; CancelOrders (id)
&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;&nbsp;ordernum, value&nbsp;&nbsp;in&nbsp;&nbsp;pairs(activeOrders)&nbsp;&nbsp;do 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;transaction&nbsp;&nbsp;=&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "ACTION" &#93;&nbsp;&nbsp;=&nbsp;&nbsp; "KILL_ORDER" ,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "CLASSCODE" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;classCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "SECCODE" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;secCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "ORDER_KEY" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;tostring(ordernum),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#91; "TRANS_ID" &#93;&nbsp;&nbsp;=&nbsp;&nbsp;tostring(id),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogTable( "Cancelling order: " , transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp; message&nbsp;&nbsp; =&nbsp;&nbsp; sendTransaction (transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log( "Result: "&nbsp;&nbsp; ..&nbsp;&nbsp;id&nbsp;&nbsp;..&nbsp;&nbsp; ", &#91;"&nbsp;&nbsp; ..&nbsp;&nbsp; message&nbsp;&nbsp; ..&nbsp;&nbsp; "&#93;" )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;&nbsp;=&nbsp;&nbsp;id&nbsp;&nbsp;+&nbsp;&nbsp; 1 
&nbsp;&nbsp;&nbsp;&nbsp;end 
 end 

 function&nbsp;&nbsp; OnTransReply (transaction)
&nbsp;&nbsp; LogTable( "OnTransReply: " , transaction)
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;&nbsp; not&nbsp;&nbsp;testStarted&nbsp;&nbsp;then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- этот код вызывается только один раз для старта теста 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log( "Starting test" )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testStarted&nbsp;&nbsp;=&nbsp;&nbsp; true 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- ставим тестовые заявки 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PlaceOrders(priceMin,&nbsp;&nbsp;5 ,&nbsp;&nbsp;3000 )
&nbsp;&nbsp;&nbsp;&nbsp;end 
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;&nbsp;transaction.status&nbsp;&nbsp;=&nbsp;&nbsp;=&nbsp;&nbsp; 3&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;activeOrders&#91;transaction.order_num&#93;&nbsp;&nbsp;=&nbsp;&nbsp; true 
&nbsp;&nbsp;&nbsp;&nbsp;else 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -- если попали сюда, значит произошла ошибка 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log( "ERROR: "&nbsp;&nbsp; ..&nbsp;&nbsp;transaction.result_msg)
&nbsp;&nbsp;&nbsp;&nbsp;end 
 end 

 function&nbsp;&nbsp; OnStop ()
&nbsp;&nbsp; running&nbsp;&nbsp;=&nbsp;&nbsp; false 
 end 

 function&nbsp;&nbsp; GetPriceMin ()
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;&nbsp;param&nbsp;&nbsp;=&nbsp;&nbsp; getParamEx (classCode, secCode,&nbsp;&nbsp;"pricemin" )
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;&nbsp;param&nbsp;&nbsp;=&nbsp;&nbsp;=&nbsp;&nbsp; nil&nbsp;&nbsp; or&nbsp;&nbsp;param.result ~ =&nbsp;&nbsp; "1"&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; 0 
&nbsp;&nbsp;&nbsp;&nbsp;end 
&nbsp;&nbsp;&nbsp;&nbsp;local&nbsp;&nbsp;value&nbsp;&nbsp;=&nbsp;&nbsp;tonumber(param.param_value)
&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;&nbsp;value&nbsp;&nbsp;=&nbsp;&nbsp;=&nbsp;&nbsp; nil&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; 0 
&nbsp;&nbsp;&nbsp;&nbsp;end 
&nbsp;&nbsp; Log( "pricemin = "&nbsp;&nbsp; ..&nbsp;&nbsp;value)
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;value
 end 

 function&nbsp;&nbsp; OnInit (scriptName)
&nbsp;&nbsp; logFile&nbsp;&nbsp;=&nbsp;&nbsp; io.open (scriptName&nbsp;&nbsp;..&nbsp;&nbsp; ".log" ,&nbsp;&nbsp;"at" )
 end 

 function&nbsp;&nbsp; main ()
&nbsp;&nbsp;&nbsp;&nbsp;-- получаем нижний лимит цены 
&nbsp;&nbsp; priceMin&nbsp;&nbsp;=&nbsp;&nbsp;GetPriceMin()
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;&nbsp;running&nbsp;&nbsp;and&nbsp;&nbsp;priceMin&nbsp;&nbsp;=&nbsp;&nbsp;=&nbsp;&nbsp; 0&nbsp;&nbsp; do 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep ( 100 )
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;priceMin&nbsp;&nbsp;=&nbsp;&nbsp;GetPriceMin()
&nbsp;&nbsp;&nbsp;&nbsp;end 

&nbsp;&nbsp;&nbsp;&nbsp;-- отправляем первую заявку 
&nbsp;&nbsp; PlaceOrders(priceMin,&nbsp;&nbsp;1 ,&nbsp;&nbsp;1000 )
&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;-- активное ожидание начала теста 
&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;&nbsp; not&nbsp;&nbsp;testStarted&nbsp;&nbsp;do 
&nbsp;&nbsp;&nbsp;&nbsp;end 
&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;-- ставим тестовые заявки 
&nbsp;&nbsp; PlaceOrders(priceMin,&nbsp;&nbsp;5 ,&nbsp;&nbsp;2000 )
&nbsp;&nbsp;&nbsp;&nbsp;-- ждём исполнение всех транзакций 
&nbsp;&nbsp;&nbsp;&nbsp;sleep ( 2000 )
&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;-- снимаем все заявки 
&nbsp;&nbsp; CancelOrders( 4000 )
&nbsp;&nbsp;&nbsp;&nbsp;-- ждём исполнение всех транзакций 
&nbsp;&nbsp;&nbsp;&nbsp;sleep ( 2000 )
&nbsp;&nbsp; 
&nbsp;&nbsp; logFile:close()
&nbsp;&nbsp; logFile&nbsp;&nbsp;=&nbsp;&nbsp; nil 
 end 
&nbsp;&nbsp;</pre>
=============
<br />=============<br /> &nbsp; &nbsp; Добрый день, <br /> &nbsp; &nbsp; <br /> &nbsp; &nbsp; Описанная в данном инциденте проблема была устранена в версии 7.7.0 &nbsp; &nbsp; терминала QUIK.<br /> &nbsp; &nbsp; Рекомендуем Вам обновить версию программы.<br /> &nbsp; &nbsp; <br /> &nbsp; &nbsp; Приносим извинения за причиненные неудобства. <br />
			<i>23.01.2017 15:22:57, Egor Zaytsev.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message21891/topic2343/</link>
			<guid>http://forum.quik.ru/messages/forum10/message21891/topic2343/</guid>
			<pubDate>Mon, 23 Jan 2017 15:22:57 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>Ошибка при вызове sendTransaction из нескольких потоков</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message20872/topic2343/">Ошибка при вызове sendTransaction из нескольких потоков</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			<a class="blog-p-user-name" id="bp_1XT4xaGX" href="/user/2799/" bx-tooltip-user-id="2799">SG</a>, &nbsp; &nbsp; &nbsp;Добрый день, <br /> &nbsp; &nbsp; <br /> &nbsp; &nbsp; Описанная в данном инциденте ошибка будет исправлена в одной из следующих версий программы.<br /> &nbsp; &nbsp; Приносим извинения за причиненные неудобства. <br />
			<i>07.12.2016 08:01:19, Zoya Skvorcova.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message20872/topic2343/</link>
			<guid>http://forum.quik.ru/messages/forum10/message20872/topic2343/</guid>
			<pubDate>Wed, 07 Dec 2016 08:01:19 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>Ошибка при вызове sendTransaction из нескольких потоков</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message20867/topic2343/">Ошибка при вызове sendTransaction из нескольких потоков</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Очень хорошо, что у Вас получилось воспроизвести ошибку &quot;Неверный формат заявки&quot;. У нас она тоже изредка появляется, хотя мы не отправляем заявки из разных потоков, но в терминале одновременно работает несколько скриптов, каждый из которых шлёт заявки из своего main-потока. Теперь разработчики, скорее всего, быстро найдут и устранят причину (скорее всего, баг синхронного доступа к общему ресурсу). По нашему обращению не получилось этого сделать. <br />
			<i>07.12.2016 07:10:29, _sk_.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message20867/topic2343/</link>
			<guid>http://forum.quik.ru/messages/forum10/message20867/topic2343/</guid>
			<pubDate>Wed, 07 Dec 2016 07:10:29 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>Ошибка при вызове sendTransaction из нескольких потоков</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message20854/topic2343/">Ошибка при вызове sendTransaction из нескольких потоков</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Добрый день,<br /><br />Ваше сообщение получено, проблема изучается. Постараемся в ближайшее время дать ответ. <br />
			<i>06.12.2016 19:42:53, Stanislav Tvorogov.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message20854/topic2343/</link>
			<guid>http://forum.quik.ru/messages/forum10/message20854/topic2343/</guid>
			<pubDate>Tue, 06 Dec 2016 19:42:53 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>Ошибка при вызове sendTransaction из нескольких потоков</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message20849/topic2343/">Ошибка при вызове sendTransaction из нескольких потоков</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Если функцию sendTransaction вызвать одновременно из двух потоков - один вызов из main, а другой из функции обратного вызова, то на корректную транзакцию может прийти ответ с ошибкой &quot;Неверный формат заявки&quot;.<br /><br />Ниже приведён скрипт, воспроизводящий проблему. В нём нужно перед запуском заменить номер счёта в первой строке. Для появления ошибки может потребоваться несколько запусков скрипта.<br /><br />В терминале версии 7.2.2.3 ошибки не было. В версиях 7.4, 7.5 и 7.6 ошибка есть.<br /><br />Скрипт:<br /><table class="forum-spoiler"><thead onclick="if (this.nextSibling.style.display=='none') { this.nextSibling.style.display=''; BX.addClass(this, 'forum-spoiler-head-open'); } else { this.nextSibling.style.display='none'; BX.removeClass(this, 'forum-spoiler-head-open'); } BX.onCustomEvent('BX.Forum.Spoiler:toggle', [{node: this}]); event.stopPropagation();"><tr><th><div>Скрытый текст</div></th></tr></thead><tbody class="forum-spoiler" style="display:none;"><tr><td>
====code====
<pre>local accountName = "SPBFUT00000"&nbsp;&nbsp;-- заменить на правильный номер счёта
local classCode = "SPBFUT"
local secCode = "SRZ6"
local priceMin = nil
local logFile = nil
local running = true
local testStarted = false
local activeOrders = {}

function Log(message)
&nbsp;&nbsp;&nbsp;if logFile ~= nil then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local timestamp = os.date("&#91;%Y-%m-%d %X&#93;")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logFile:write(timestamp .. " " .. message .. "&#92;n")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;logFile:flush()
&nbsp;&nbsp;&nbsp;end
end

function LogTable(message, tbl)
&nbsp;&nbsp;&nbsp;local res = {}
&nbsp;&nbsp;&nbsp;for key, value in pairs(tbl) do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local vtype = type(value)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if vtype == "nil" then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&#91;#res + 1&#93; = key .. " = &#60;nil&#62;"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elseif vtype == "number" then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&#91;#res + 1&#93; = key .. " = " .. value
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elseif vtype == "string" then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&#91;#res + 1&#93; = key .. " = " .. string.format("%q", value)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res&#91;#res + 1&#93; = key .. " = ?"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;Log(message .. table.concat(res, "; "))
end&nbsp;&nbsp;&nbsp;

function PlaceOrders(price, count, id)
&nbsp;&nbsp;&nbsp;for i = 1, count do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local transaction = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"ACTION"&#93; = "NEW_ORDER",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"CLASSCODE"&#93; = classCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"SECCODE"&#93; = secCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"ACCOUNT"&#93; = accountName,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"OPERATION"&#93; = "B",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"PRICE"&#93; = tostring(price),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"QUANTITY"&#93; = "1",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"TRANS_ID"&#93; = tostring(id),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogTable("Placing order: ", transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local message = sendTransaction(transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log("Result: " .. id .. ", &#91;" .. message .. "&#93;")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id = id + 1
&nbsp;&nbsp;&nbsp;end&nbsp;&nbsp;&nbsp;
end

function CancelOrders(id)
&nbsp;&nbsp;&nbsp;for ordernum, value in pairs(activeOrders) do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local transaction = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"ACTION"&#93; = "KILL_ORDER",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"CLASSCODE"&#93; = classCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"SECCODE"&#93; = secCode,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"ORDER_KEY"&#93; = tostring(ordernum),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"TRANS_ID"&#93; = tostring(id),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LogTable("Cancelling order: ", transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local message = sendTransaction(transaction)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log("Result: " .. id .. ", &#91;" .. message .. "&#93;")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id = id + 1
&nbsp;&nbsp;&nbsp;end
end

function OnTransReply(transaction)
&nbsp;&nbsp;&nbsp;LogTable("OnTransReply: ", transaction)
&nbsp;&nbsp;&nbsp;if not testStarted then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- этот код вызывается только один раз для старта теста
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log("Starting test")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;testStarted = true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- ставим тестовые заявки
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PlaceOrders(priceMin, 5, 3000)
&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;if transaction.status == 3 then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;activeOrders&#91;transaction.order_num&#93; = true
&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- если попали сюда, значит произошла ошибка
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log("ERROR: " .. transaction.result_msg)
&nbsp;&nbsp;&nbsp;end
end

function OnStop()
&nbsp;&nbsp;&nbsp;running = false
end

function GetPriceMin()
&nbsp;&nbsp;&nbsp;local param = getParamEx(classCode, secCode, "pricemin")
&nbsp;&nbsp;&nbsp;if param == nil or param.result ~= "1" then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0
&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;local value = tonumber(param.param_value)
&nbsp;&nbsp;&nbsp;if value == nil then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return 0
&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;Log("pricemin = " .. value)
&nbsp;&nbsp;&nbsp;return value
end

function OnInit(scriptName)
&nbsp;&nbsp;&nbsp;logFile = io.open(scriptName .. ".log", "at")
end

function main()
&nbsp;&nbsp;&nbsp;-- получаем нижний лимит цены
&nbsp;&nbsp;&nbsp;priceMin = GetPriceMin()
&nbsp;&nbsp;&nbsp;while running and priceMin == 0 do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(100)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;priceMin = GetPriceMin()
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;-- отправляем первую заявку
&nbsp;&nbsp;&nbsp;PlaceOrders(priceMin, 1, 1000)
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;-- активное ожидание начала теста
&nbsp;&nbsp;&nbsp;while not testStarted do
&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;-- ставим тестовые заявки
&nbsp;&nbsp;&nbsp;PlaceOrders(priceMin, 5, 2000)
&nbsp;&nbsp;&nbsp;-- ждём исполнение всех транзакций
&nbsp;&nbsp;&nbsp;sleep(2000)
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;-- снимаем все заявки
&nbsp;&nbsp;&nbsp;CancelOrders(4000)
&nbsp;&nbsp;&nbsp;-- ждём исполнение всех транзакций
&nbsp;&nbsp;&nbsp;sleep(2000)
&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;logFile:close()
&nbsp;&nbsp;&nbsp;logFile = nil
end
</pre>
=============
</td></tr></tbody></table> <br />
			<i>06.12.2016 16:21:19, SG.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message20849/topic2343/</link>
			<guid>http://forum.quik.ru/messages/forum10/message20849/topic2343/</guid>
			<pubDate>Tue, 06 Dec 2016 16:21:19 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
	</channel>
</rss>
