<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>Форум QUIK [тема: Не могу реализовать память через CSV файл]</title>
		<link>http://forum.quik.ru</link>
		<description>Новое в теме Не могу реализовать память через CSV файл форума  на сайте Форум QUIK [forum.quik.ru]</description>
		<language>ru</language>
		<docs>http://backend.userland.com/rss2</docs>
		<pubDate>Thu, 21 May 2026 03:03:54 +0300</pubDate>
		<item>
			<title>Не могу реализовать память через CSV файл</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message82524/topic9570/">Не могу реализовать память через CSV файл</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Главная причина, почему Ваш скрипт &quot;ничего не помнит&quot; — критические синтаксические ошибки, из-за которых Lua-интерпретатор в QUIK просто ломается и не может корректно выполнить код. <br /><br />Главные ошибки в Вашем коде:<br />1. Синтаксический слом в CheckLine: Конструкция end elseif написана с ошибкой. В Lua нет elseif после end. Из-за этого функция вообще не компилировалась. Сломанный массив - строка Trades[] в OnInit — это некорректный синтаксис Lua. Выдаст ошибку.<br />2. Потеря переменной current_line. В функции OnTrade вы вызываете remove_line_from_csv(secondfile, current_line). Но current_line была локальной переменной внутри CheckLine. В OnTrade она всегда равна nil или старой глобальной пустышке. Скрипт не понимал, какую строку удалять. <br />3. Бесконечный цикл без выхода. В main() запущен while do_main do sleep(1000) end, но флаг do_main нигде не меняется на false. Скрипт зависнет навсегда при остановке.<br />4. Конкуренция за файлы. Файл secondfile открывается в режиме &quot;r&quot; (чтение), но при удалении строки Вы пытаетесь стереть его через os.remove прямо во время работы, что в Windows часто блокируется, если хэндл не освобожден или пересекается с другими функциями.<br /><br />Попробуйте так. Исправленный скрипт. Этот вариант исправляет логику работы с файлом покупок (fibobuys.csv). Вот что изменилось. <br />Исправлен синтаксис.<br />Удален сломанный elseif в CheckLine и пустой массив Trades[]. <br />Скрипт теперь корректно запускается терминалом QUIK.<br />Добавлена функция поиска строки (find_line_by_price). Теперь скрипт при продаже сканирует файл fibobuys.csv, находит точный номер строки, где лежит цена этой покупки, и передает этот индекс в функцию удаления. Если точная цена не найдена (например, из-за проскальзывания), он удаляет первую строку (принцип FIFO).<br />Безопасная перезапись файла. Вместо рискованного удаления файла через os.remove (который часто блокируется Windows, если файл занят QUIK), скрипт выкачивает строки в массив, очищает файл через режим &quot;w&quot; и записывает обратно только нужные данные.<br />Добавлен корректный OnStop. Теперь при остановке скрипта кнопкой в QUIK цикл в main останавливается корректно, а хэндлы файлов закрываются.<br /><br />Скрипт все еще остается учебным и требуется доработать логику. Да и архитектуру тоже. Используйте код предварительно проверив, выкладываю как есть просто исправленный Ваш вариант. Удачи!<br />
====code====
<pre>-- Настройки торговой стратегии
local class = "QJSIM" 
local sec = "SBER" 
local account = "NL0011100043" 
local LotSize = 1 
local step = 0.02 --&#62; Нужно проверить не уверен что так?
local limits = 10 

-- Служебные переменные
local tid = 0 
local trz_comment = "FIBO-2 --&#62; " 
local uprice = nil
local dprice = nil
local TradeNums = {}
local do_main = true
local climits = 0

-- Пути к файлам
local csv_path = getScriptPath().."/FiboTrades.csv"
local secondfile = getScriptPath().."/fibobuys.csv"
local CSV = nil

function OnInit()
&nbsp;&nbsp;&nbsp;&nbsp;CSV = io.open(csv_path, "a+")
end

-- Округление
function math_round(roundIn, roundDig)
&nbsp;&nbsp;&nbsp;&nbsp;local mul = 10^roundDig
&nbsp;&nbsp;&nbsp;&nbsp;return math.floor((roundIn * mul) + 0.5) / mul
end

-- Отправка транзакции --&#62;&nbsp;&nbsp;Проверьте параметры?
function LimitSpot(operation, SpotPrice)
&nbsp;&nbsp;&nbsp;&nbsp;tid = tid + 1
&nbsp;&nbsp;&nbsp;&nbsp;local transaction = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"TRANS_ID"&#93;&nbsp;&nbsp; = tostring(tid),
&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;= class,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"SECCODE"&#93;&nbsp;&nbsp;&nbsp;&nbsp;= sec,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"OPERATION"&#93;&nbsp;&nbsp;= operation,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"QUANTITY"&#93;&nbsp;&nbsp; = tostring(LotSize),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"PRICE"&#93;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= tostring(SpotPrice),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"ACCOUNT"&#93;&nbsp;&nbsp;&nbsp;&nbsp;= tostring(account),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#91;"EXECUTION_CONDITION"&#93; = "PUT_IN_QUEUE",
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;local res = sendTransaction(transaction)
&nbsp;&nbsp;&nbsp;&nbsp;if res ~= '' then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment..'Transaction Error! '..res)
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment..'Transaction Success! ID = '..tid)
&nbsp;&nbsp;&nbsp;&nbsp;end
end

-- Проверка файла цен для продажи или покупки
function CheckLine(number)
&nbsp;&nbsp;&nbsp;&nbsp;local current_line = 1
&nbsp;&nbsp;&nbsp;&nbsp;local same = 0
&nbsp;&nbsp;&nbsp;&nbsp;local is_sold = false
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;local CheckFile = io.open(secondfile, "r")
&nbsp;&nbsp;&nbsp;&nbsp;if CheckFile then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for line in CheckFile:lines() do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local val = tonumber(line)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if val then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if val == number then same = same + 1 end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Если цена в файле ниже или равна текущей — продаем по этой фиксации
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if val &#60;= number then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LimitSpot('S', number)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is_sold = true
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current_line = current_line + 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CheckFile:close()
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;-- Если совпадений нет, лимит не исчерпан и мы не продали — покупаем
&nbsp;&nbsp;&nbsp;&nbsp;if not is_sold and same == 0 and climits &#60; limits then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LimitSpot('B', number) 
&nbsp;&nbsp;&nbsp;&nbsp;end
end

-- Удаление строки из CSV (безопасное переписывание)
function remove_line_from_csv(filename, line_to_remove)
&nbsp;&nbsp;&nbsp;&nbsp;local lines = {}
&nbsp;&nbsp;&nbsp;&nbsp;local input_file = io.open(filename, "r")
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;if input_file then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for line in input_file:lines() do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lines&#91;#lines + 1&#93; = line
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_file:close()
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;local output_file = io.open(filename, "w")
&nbsp;&nbsp;&nbsp;&nbsp;if not output_file then return end

&nbsp;&nbsp;&nbsp;&nbsp;for i, line in ipairs(lines) do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if i ~= line_to_remove then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;output_file:write(line .. "&#92;n")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;output_file:close()
&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment.."Строка "..line_to_remove.." удалена из базы покупок.")
end

-- Функция поиска строки по цене для удаления при OnTrade
function find_line_by_price(filename, price_to_find)
&nbsp;&nbsp;&nbsp;&nbsp;local input_file = io.open(filename, "r")
&nbsp;&nbsp;&nbsp;&nbsp;if not input_file then return nil end
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;local line_number = 1
&nbsp;&nbsp;&nbsp;&nbsp;for line in input_file:lines() do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if tonumber(line) == price_to_find then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input_file:close()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return line_number
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line_number = line_number + 1
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;input_file:close()
&nbsp;&nbsp;&nbsp;&nbsp;return nil
end

function main()
&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment..'Start.')
&nbsp;&nbsp;&nbsp;&nbsp;while do_main do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(1000)
&nbsp;&nbsp;&nbsp;&nbsp;end
end

function OnStop()
&nbsp;&nbsp;&nbsp;&nbsp;do_main = false
&nbsp;&nbsp;&nbsp;&nbsp;if CSV then CSV:close() end
&nbsp;&nbsp;&nbsp;&nbsp;return 1000
end

function OnParam(class1, sec1)
&nbsp;&nbsp;&nbsp;&nbsp;if class1 == class and sec1 == sec then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local last_param = getParamEx(class, sec, "last")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not last_param or last_param.param_value == "" then return end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local price = math_round(tonumber(last_param.param_value), 2)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if uprice ~= nil then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if price &#60;= dprice then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dprice = dprice - step
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uprice = uprice - step
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment..'Price-- -&#62; '..price)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elseif price &#62;= uprice then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CheckLine(price)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dprice = dprice + step
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uprice = uprice + step
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment.."Price++ -&#62; "..price)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
end

function OnTrade(trade)
&nbsp;&nbsp;&nbsp;&nbsp;if trade.sec_code == sec and trade.class_code == class then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Инициализация сетки по первой сделке
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if uprice == nil then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uprice = trade.price + step
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dprice = trade.price - step
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment..'Grid placed success!')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Проверка на дубликаты сделок
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for i = #TradeNums, 1, -1 do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if TradeNums&#91;i&#93; == trade.trade_num then return end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TradeNums&#91;#TradeNums + 1&#93; = trade.trade_num

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local Op = ""
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local t = bit.band(tonumber(trade.flags), 4) -- 4 = sell, 0 = buy
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if t == 0 then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- ЛОГИКА ПОКУПКИ
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Op = "Buy"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;climits = climits + 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment.."buy "..trade.price)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local wr = io.open(secondfile, 'a+')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if wr then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wr:write(trade.price.."&#92;n")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wr:flush()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wr:close()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- ЛОГИКА ПРОДАЖИ
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Op = "Sell"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;climits = climits - 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message(trz_comment.."Sell "..trade.price)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Ищем строку с ценой, которая послужила триггером для продажи
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local line_idx = find_line_by_price(secondfile, trade.price)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if line_idx then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove_line_from_csv(secondfile, line_idx)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Если точной цены нет, удаляем первую попавшуюся строку (FIFO)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;remove_line_from_csv(secondfile, 1)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-- Логирование в общий файл FiboTrades.csv
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if CSV then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local TradeLine = os.date("%x %X", os.time(trade.datetime))..";"..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trade.class_code..";"..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trade.sec_code..";"..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trade.trade_num..";"..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trade.order_num..";"..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Op..";"..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trade.price..";"..
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;trade.qty.."&#92;n"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSV:write(TradeLine)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CSV:flush()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
end
</pre>
============= <br />
			<i>20.05.2026 22:37:30, VPM.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message82524/topic9570/</link>
			<guid>http://forum.quik.ru/messages/forum10/message82524/topic9570/</guid>
			<pubDate>Wed, 20 May 2026 22:37:30 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
		<item>
			<title>Не могу реализовать память через CSV файл</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum10/message82523/topic9570/">Не могу реализовать память через CSV файл</a></b> в форуме <a href="http://forum.quik.ru/forum10/">Программирование на языке Lua</a>. <br />
			Всем добрый вечер. Мне 14, я пишу своему отцу пару скриптов, чтобы ему было удобнее работать в терминале. В этом скрипте должна быть реализована стратегия FiBo, вроде бы она довольно известная.<br />Суть в том что при увеличении цены срабатывает функция CheckLine, где я сравниваю строки в csv файле, состоящем из цен, по которым я покупал когда либо инструмент.<br />При покупке он должен записывать туда цену, при продаже вычеркивать одну из цен, ориентируясь на которую он продал.<br />Казус в том, что ничего из прошлой написанной мною строки он не делает. Память по просту не работает!<br />Я пишу скрипты на Qlua недолго, иногда использую ИИ (Извините меня все, я сам против вайбкодинга, но мне батя узкие сроки ставит). Помогите пожалуйста!!!!<br />Если есть любые другие замечания пишите.<br /><br />Сам скрипт:<br /><br />function OnInit()<br />--Настройки, изменять при надобности.--<br />	class = &quot;QJSIM&quot; -- Тип интсрумента<br />	sec = &quot;SBER&quot; -- Код интсрумента<br />	account = &quot;NL0011100043&quot; -- Номер аккаунта, тут всё понятно<br />	LotSize = 1 -- Кол-во лотов в заявке.<br />	step = 0.02 -- Шаг цены.<br />	limits = 10 -- Лимит торговли<br />	<br />	tid = 0 -- Не трогать!<br />	trz_comment = &quot;FIBO-2 --&gt; &quot; -- Не трогать.<br />	price = nil -- Не трогать.<br />	uprice = nil<br />	dprice = nil<br />	SellPrice = nil<br />	TradeNums = {}<br />	Trades&#91;&#93;<br />	<br />	CSV = io.open(getScriptPath()..&quot;/FiboTrades.csv&quot;, &quot;a+&quot;);<br />	secondfile = &quot;fibobuys.csv&quot;<br />end<br /><br />function CheckLine(number)<br />current_line = 0<br />	same = 0;<br />	ss = 0<br />	local CheckFile = io.open(secondfile, &quot;r&quot;);<br />	for line in CheckFile:lines() do<br />					if tonumber(line) == number then same = same+1; end<br />					if tonumber(line) &lt;= number then LimitSpot(&#39;S&#39;, number); break end; <br />					 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;current_line = current_line + 1<br />	end<br />				elseif same == 0 and climits ~= limits then LimitSpot(&#39;B&#39;, number) end<br />				<br />	CheckFile:close();<br />end<br /><br />function LimitSpot(operation, SpotPrice)<br />tid = tid+1<br />	transaction={<br />		&#91;&quot;TRANS_ID&quot;&#93;=tostring(tid),<br />		&#91;&quot;ACTION&quot;&#93;=&quot;NEW_ORDER&quot;,<br />		&#91;&quot;CLASSCODE&quot;&#93;=class,<br />		&#91;&quot;SECCODE&quot;&#93;=sec,<br />		&#91;&quot;OPERATION&quot;&#93;=operation,<br />		&#91;&quot;QUANTITY&quot;&#93;=tostring(LotSize),<br />		&#91;&quot;PRICE&quot;&#93;=tostring(SpotPrice),<br />		&#91;&quot;ACCOUNT&quot;&#93;=tostring(account),<br />		&#91;&quot;EXECUTION_CONDITION&quot;&#93;=&quot;PUT_IN_QUEUE&quot;,	-- тип заявки лимитная<br />	}<br />	res = sendTransaction(transaction)<br />	if res ~= &#39;&#39; then<br />		message(trz_comment..&#39;Transaction Error! &#39;..res)<br />		else<br />		message(trz_comment..&#39;Transaction Success! ID = &#39;..tid)<br />	end<br />end<br /><br />function math_round( roundIn , roundDig ) -- первый аргумент число для округления, второй - количество знаков после запятой <br /> &nbsp; &nbsp; local mul = 10^roundDig<br /> &nbsp; &nbsp; return ( math.floor( ( roundIn * mul ) + 0.5 )/mul )<br />end<br /><br />function main()<br />	message(trz_comment..&#39;Start.&#39;)<br />	climits = 0<br />	do_main = true<br /><br />	while do_main do<br />		sleep(1000)<br />	end<br />end<br /><br />function OnParam(class1, sec1)<br />	if class1 == class and sec1 == sec then<br />		price = math_round(getParamEx(class, &nbsp;sec, &quot;last&quot;).param_value, 2)<br />		if uprice ~= nil then<br />			if price &lt;= dprice then<br />				dprice = dprice-step<br />				uprice = uprice-step<br />				message(trz_comment..&#39;Price-- -&gt; &#39;..price)<br />				else if price &gt;= uprice then<br />					CheckLine(price);<br />					dprice = dprice+step<br />					uprice = uprice+step<br />					message(trz_comment..&quot;Price++ -&gt; &quot;..price)<br />				end<br />			end<br />		end<br />	end<br />end<br /><br />function OnTrade(trade)<br />	if trade.sec_code == sec and trade.class_code == class then<br />		if uprice == nil then<br />			uprice = trade.price + step<br />			dprice = trade.price - step<br />			message(trz_comment..&#39;Grid placed success!&#39;)<br />		end<br />		t = bit.band(tonumber(trade&#91;&#39;flags&#39;&#93;),4) -- 1 = sell 0 = buy<br />		if t == 0 then message(trz_comment..&quot;buy &quot;..trade.price); Op = &quot;Buy&quot;; climits = climits + 1;<br />		wr = io.open(secondfile, &#39;a+&#39;)<br />		wr:write(trade.price..&quot;\n&quot;);<br />		wr:flush();<br />		wr:close();<br />		<br />		else message(trz_comment..&quot;Sell &quot;..trade.price); climits = climits - 1; Op = &quot;Sell&quot;; SellPrice = nil;<br />			 remove_line_from_csv(secondfile, current_line)<br />		end<br />		<br />		<br />		for i=#TradeNums,1,-1 do<br />		-- Если данная сделка уже была записана, выходит из функции<br />		if TradeNums&#91;i&#93; == trade.trade_num then return; end;<br />	end;<br /> <br />	-- Если мы здесь, значит сделка не была найдена в числе уже записанных<br />	-- Добавляет в массив номер новой сделки<br />	TradeNums&#91;#TradeNums + 1&#93; = trade.trade_num;<br />	-- Вычисляет операцию сделки<br />	-- Создает строку сделки для записи в файл (&quot;Дата и время;Код класса;Код бумаги;Номер сделки;Номер заявки;Операция;Цена;Количество\n&quot;)<br />	local TradeLine = 	os.date(&quot;%c&quot;, os.time(trade.datetime))..&quot;;&quot;..<br />						trade.class_code..&quot;;&quot;..<br />						trade.sec_code..&quot;;&quot;..<br />						trade.trade_num..&quot;;&quot;..<br />						trade.order_num..&quot;;&quot;..<br />						Op..&quot;;&quot;..<br />						trade.price..&quot;;&quot;..<br />						trade.qty..&quot;\n&quot;;<br />	-- Записывает строку в файл<br />	CSV:write(TradeLine);<br />	-- Сохраняет изменения в файле<br />	CSV:flush();<br />end<br />	end<br />	<br />	function remove_line_from_csv(filename, line_to_remove)<br /> &nbsp;local input_file = io.open(filename, &quot;r&quot;)<br /> &nbsp;if not input_file then<br /> &nbsp; &nbsp;print(&quot;Ошибка открытия файла для чтения&quot;)<br /> &nbsp; &nbsp;return false<br /> &nbsp;end<br /><br /> &nbsp;local temp_filename = filename .. &quot;.tmp&quot;<br /> &nbsp;local output_file = io.open(temp_filename, &quot;w&quot;)<br /> &nbsp;if not output_file then<br /> &nbsp; &nbsp;print(&quot;Ошибка открытия временного файла для записи&quot;)<br /> &nbsp; &nbsp;input_file:close()<br /> &nbsp; &nbsp;return false<br /> &nbsp;end<br /><br /> &nbsp;local line_number = 1<br /> &nbsp;for line in input_file:lines() do<br /> &nbsp; &nbsp;if line_number ~= line_to_remove then<br /> &nbsp; &nbsp; &nbsp;output_file:write(line .. &quot;\n&quot;)<br /> &nbsp; &nbsp;end<br /> &nbsp; &nbsp;line_number = line_number + 1<br /> &nbsp;end<br /><br /> &nbsp;input_file:close()<br /> &nbsp;output_file:close()<br /> &nbsp;-- Удаляем старый файл и переименовываем временный<br /> os.remove(filename)<br /> &nbsp;os.rename(temp_filename, filename)<br /> &nbsp;message(&quot;deleted&quot;)<br />end <br />
			<i>20.05.2026 21:09:25, DimastaBalz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum10/message82523/topic9570/</link>
			<guid>http://forum.quik.ru/messages/forum10/message82523/topic9570/</guid>
			<pubDate>Wed, 20 May 2026 21:09:25 +0300</pubDate>
			<category>Программирование на языке Lua</category>
		</item>
	</channel>
</rss>
