<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>Форум QUIK [тема: Скрипты от ИИ]</title>
		<link>http://forum.quik.ru</link>
		<description>Новое в теме Скрипты от ИИ форума  на сайте Форум QUIK [forum.quik.ru]</description>
		<language>ru</language>
		<docs>http://backend.userland.com/rss2</docs>
		<pubDate>Sun, 10 May 2026 20:15:29 +0300</pubDate>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79562/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			Вот что ответил ИИ:<br />-------------------<br />Вы правы, в скрипте действительно есть ошибки. В языке Lua, который используется для индикаторов в торговых платформах (например, QUIK), для доступа к ценовым данным нужно использовать специальные функции:<br /><ul><li>High(i) → H(i)<br /><li>Low(i) → L(i)<br /><li>Open(i) → O(i)<br /><li>Close(i) → C(i)<br /></ul><p>Исправленный код индикатора:</p>Settings = {<br /> &nbsp; &nbsp;Name = &quot;*Kijun-sen&quot;,<br /> &nbsp; &nbsp;line = {{<br /> &nbsp; &nbsp; &nbsp; &nbsp;Name = &quot;Kijun-sen&quot;,<br /> &nbsp; &nbsp; &nbsp; &nbsp;Color = RGB(0, 0, 255),<br /> &nbsp; &nbsp; &nbsp; &nbsp;Type = TYPE_LINE,<br /> &nbsp; &nbsp; &nbsp; &nbsp;Width = 2<br /> &nbsp; &nbsp;}}<br />}<br /><br />function Init()<br /> &nbsp; &nbsp;return 1<br />end<br /><br />local kijun_period = 26 &nbsp; &nbsp;-- Период Kijun-sen (можно изменить)<br /><br />function OnCalculate(index)<br /> &nbsp; &nbsp;-- Проверяем, достаточно ли данных для расчета<br /> &nbsp; &nbsp;if index &lt; kijun_period - 1 then<br /> &nbsp; &nbsp; &nbsp; &nbsp;return nil<br /> &nbsp; &nbsp;end<br /> &nbsp; &nbsp;<br /> &nbsp; &nbsp;-- Инициализация переменных для экстремумов<br /> &nbsp; &nbsp;local max_high = H(index - kijun_period + 1)<br /> &nbsp; &nbsp;local min_low = L(index - kijun_period + 1)<br /> &nbsp; &nbsp;<br /> &nbsp; &nbsp;-- Поиск максимума и минимума за период<br /> &nbsp; &nbsp;for i = index - kijun_period + 2, index do<br /> &nbsp; &nbsp; &nbsp; &nbsp;local current_high = H(i)<br /> &nbsp; &nbsp; &nbsp; &nbsp;local current_low = L(i)<br /> &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;if current_high &gt; max_high then<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;max_high = current_high<br /> &nbsp; &nbsp; &nbsp; &nbsp;end<br /> &nbsp; &nbsp; &nbsp; &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;if current_low &lt; min_low then<br /> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;min_low = current_low<br /> &nbsp; &nbsp; &nbsp; &nbsp;end<br /> &nbsp; &nbsp;end <br />
			<i>21.09.2025 08:31:12, nikolz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79562/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79562/topic9257/</guid>
			<pubDate>Sun, 21 Sep 2025 08:31:12 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79558/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			я исправил сроки<br />-- Инициализация переменных для экстремумов<br /> &nbsp;local max_high = High(index - kijun_period + 1)<br /> &nbsp;local min_low = Low(index - kijun_period + 1)<br /><br />и<br />-- Поиск максимума и минимума за период<br /> &nbsp;for i = index - kijun_period + 2, index do<br /> &nbsp; &nbsp; &nbsp;local current_high = High(i)<br /> &nbsp; &nbsp; &nbsp;local current_low = Low(i)<br /><br />скрин прилагаю вылезла ошибка <br />
			<img src="https://forum.quik.ru/bitrix/components/bitrix/forum.interface/show_file.php?fid=12720&" width="974" height="642" /><br /><i>20.09.2025 13:43:49, Roman Koledin.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79558/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79558/topic9257/</guid>
			<pubDate>Sat, 20 Sep 2025 13:43:49 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79545/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			<br />====quote====<br /><a class="blog-p-user-name" id="bp_hf1K2Tvp" href="/user/62/" bx-tooltip-user-id="62">nikolz</a> написал:<br />Вариант индикатора kijun-sen line lua QUIK , который написал Ии ( не проверял). 
====code====
<pre>&nbsp;&nbsp;Settings&nbsp;&nbsp;=&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;=&nbsp;&nbsp; "*Kijun-sen" ,
&nbsp;&nbsp;&nbsp;&nbsp;line&nbsp;&nbsp;=&nbsp;&nbsp;{{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;=&nbsp;&nbsp; "Kijun-sen" ,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color&nbsp;&nbsp;=&nbsp;&nbsp; RGB ( 0 ,&nbsp;&nbsp;0 ,&nbsp;&nbsp;255 ),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type&nbsp;&nbsp;=&nbsp;&nbsp;TYPE_LINE,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width&nbsp;&nbsp;=&nbsp;&nbsp; 2 
&nbsp;&nbsp;&nbsp;&nbsp;}}
}

 function&nbsp;&nbsp; Init ()
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; 1 
 end 

 local&nbsp;&nbsp;kijun_period&nbsp;&nbsp;=&nbsp;&nbsp; 26&nbsp;&nbsp;&nbsp;&nbsp;-- Период Kijun-sen (можно изменить) 

 function&nbsp;&nbsp; OnCalculate (index)
&nbsp;&nbsp;&nbsp;&nbsp; -- Проверяем, достаточно ли данных для расчета 
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;index&nbsp;&nbsp;&#60;&nbsp;&nbsp;kijun_period&nbsp;&nbsp;-&nbsp;&nbsp; 1&nbsp;&nbsp; then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; nil 
&nbsp;&nbsp;&nbsp;&nbsp; end 
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; -- Инициализация переменных для экстремумов 
&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;max_high&nbsp;&nbsp;=&nbsp;&nbsp;High(index&nbsp;&nbsp;-&nbsp;&nbsp;kijun_period&nbsp;&nbsp;+&nbsp;&nbsp; 1 )
&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;min_low&nbsp;&nbsp;=&nbsp;&nbsp;Low(index&nbsp;&nbsp;-&nbsp;&nbsp;kijun_period&nbsp;&nbsp;+&nbsp;&nbsp; 1 )
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; -- Поиск максимума и минимума за период 
&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp;&nbsp;i&nbsp;&nbsp;=&nbsp;&nbsp;index&nbsp;&nbsp;-&nbsp;&nbsp;kijun_period&nbsp;&nbsp;+&nbsp;&nbsp; 2 , index&nbsp;&nbsp;do 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;current_high&nbsp;&nbsp;=&nbsp;&nbsp;High(i)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; local&nbsp;&nbsp;current_low&nbsp;&nbsp;=&nbsp;&nbsp;Low(i)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp;&nbsp;current_high&nbsp;&nbsp;&#62;&nbsp;&nbsp;max_high&nbsp;&nbsp;then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max_high&nbsp;&nbsp;=&nbsp;&nbsp;current_high
&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; if&nbsp;&nbsp;current_low&nbsp;&nbsp;&#60;&nbsp;&nbsp;min_low&nbsp;&nbsp;then 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;min_low&nbsp;&nbsp;=&nbsp;&nbsp;current_low
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end 
&nbsp;&nbsp;&nbsp;&nbsp; end 
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp; -- Расчет Kijun-sen 
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;(max_high&nbsp;&nbsp;+&nbsp;&nbsp;min_low) /&nbsp;&nbsp;2 
 end&nbsp;&nbsp; </pre>
=============
 <br />=============<br />Вот что квик сообщает ------- C:\QUIK_SBER\LuaIndicators\Kijun-sen.lua:24: attempt to call a nil value (global &#39;High&#39;) <br />
			<img src="https://forum.quik.ru/bitrix/components/bitrix/forum.interface/show_file.php?fid=12717&" width="838" height="611" /><br /><i>20.09.2025 09:54:44, Roman Koledin.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79545/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79545/topic9257/</guid>
			<pubDate>Sat, 20 Sep 2025 09:54:44 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79543/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			Вариант индикатора kijun-sen line lua QUIK , который написал Ии ( не проверял).
====code====
<pre>Settings = {
&nbsp;&nbsp;&nbsp;&nbsp;Name = "*Kijun-sen",
&nbsp;&nbsp;&nbsp;&nbsp;line = {{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name = "Kijun-sen",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Color = RGB(0, 0, 255),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Type = TYPE_LINE,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Width = 2
&nbsp;&nbsp;&nbsp;&nbsp;}}
}

function Init()
&nbsp;&nbsp;&nbsp;&nbsp;return 1
end

local kijun_period = 26&nbsp;&nbsp;-- Период Kijun-sen (можно изменить)

function OnCalculate(index)
&nbsp;&nbsp;&nbsp;&nbsp;-- Проверяем, достаточно ли данных для расчета
&nbsp;&nbsp;&nbsp;&nbsp;if index &#60; kijun_period - 1 then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return nil
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;-- Инициализация переменных для экстремумов
&nbsp;&nbsp;&nbsp;&nbsp;local max_high = High(index - kijun_period + 1)
&nbsp;&nbsp;&nbsp;&nbsp;local min_low = Low(index - kijun_period + 1)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;-- Поиск максимума и минимума за период
&nbsp;&nbsp;&nbsp;&nbsp;for i = index - kijun_period + 2, index do
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local current_high = High(i)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;local current_low = Low(i)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if current_high &#62; max_high then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;max_high = current_high
&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;if current_low &#60; min_low then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;min_low = current_low
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;end
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;-- Расчет Kijun-sen
&nbsp;&nbsp;&nbsp;&nbsp;return (max_high + min_low) / 2
end</pre>
============= <br />
			<i>20.09.2025 07:45:38, nikolz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79543/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79543/topic9257/</guid>
			<pubDate>Sat, 20 Sep 2025 07:45:38 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79539/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			Да я тоже Питон использую только для быстрой оценки результатов, написанных на других языках, предполагая что в нем библиотеки протестированы, и условно их можно считать эталонами для обработки данных. <br />
			<i>19.09.2025 12:14:23, Nikolay.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79539/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79539/topic9257/</guid>
			<pubDate>Fri, 19 Sep 2025 12:14:23 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79538/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			ИИ делал мне подобный скрипт и на Lua. Но для разработки Ai агентов он просит загрузить torch- luajit либо пишет агента на основе Q-таблицы.<br />-----------------<br />Питон нем и прикольно, что я на нем особо не пишу и знаю его хуже, чем ИИ. <br />
			<i>19.09.2025 11:59:39, nikolz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79538/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79538/topic9257/</guid>
			<pubDate>Fri, 19 Sep 2025 11:59:39 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79537/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			В последней версии загрузчика ИИ сделал сжатие сохраняемых файлов, что обеспечивает экономию диска примерно &nbsp;от 3 до 7 раз. &nbsp; <br />
			<i>19.09.2025 11:56:25, nikolz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79537/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79537/topic9257/</guid>
			<pubDate>Fri, 19 Sep 2025 11:56:25 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79536/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			<br />====quote====<br /><a class="blog-p-user-name" id="bp_D0Dw23ZH" href="/user/3132/" bx-tooltip-user-id="3132">Nikolay</a> написал:<br />И даже в этом простом коде ошибка - код обработки файла конфигурации не соответствует структуре json.<br />=============<br />ИИ просто сделал у него такое расширение. но читает его в питоне и все нормально обрабатывает. <br />
			<i>19.09.2025 11:54:09, nikolz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79536/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79536/topic9257/</guid>
			<pubDate>Fri, 19 Sep 2025 11:54:09 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79535/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			И самое веселое в современном vibe программировании - запускаешь такой скрипт, а он висит. Нет обработок прерывания, как понять висит он или ждет ответа сервера, что вообще происходит сейчас с ним - вывода индикаторов загрузки ведь нет.<br />Т.е. очевидные вещи, которые не надо говорить при постановке задачи он не делает. <br />
			<i>19.09.2025 10:27:27, Nikolay.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79535/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79535/topic9257/</guid>
			<pubDate>Fri, 19 Sep 2025 10:27:27 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79534/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			И даже в этом простом коде ошибка - код обработки файла конфигурации не соответствует структуре json. <br />
			<i>19.09.2025 10:03:23, Nikolay.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79534/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79534/topic9257/</guid>
			<pubDate>Fri, 19 Sep 2025 10:03:23 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79533/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			Пока это магический Питон, который уже давно перестал быть просто языком, а стал набором заклинаний для библиотек, то модели хорошо работают. А стоит попросить что-то иное, скажем на старом, добром C (не плюсы) и уже начинаешь проверять каждую строку. Впрочем, если ставить просто алгоритмическую задачу - то он пишет ее. Хотя и здесь надо все проверять, т.к. он очень любит проводить тесты на фиктивных данных и радостно говорить, что все хорошо. Запускаешь свой тест и видишь иное. <br />
			<i>19.09.2025 09:55:04, Nikolay.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79533/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79533/topic9257/</guid>
			<pubDate>Fri, 19 Sep 2025 09:55:04 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79524/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			Сейчас отлаживаю с ИИ скрипт AI агента для торговли акциями.<br />Весь код как и в предыдущий полностью написал ИИ.<br />Полет нормальный. <br />
			<i>17.09.2025 14:57:09, nikolz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79524/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79524/topic9257/</guid>
			<pubDate>Wed, 17 Sep 2025 14:57:09 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
		<item>
			<title>Скрипты от ИИ</title>
			<description><![CDATA[<b><a href="http://forum.quik.ru/messages/forum17/message79523/topic9257/">Скрипты от ИИ</a></b> в форуме <a href="http://forum.quik.ru/forum17/">Обмен опытом</a>. <br />
			Добрый день,<br />Выкладываю работающий скрипт, который написал ИИ под моим руководством. <br />-------------------------------<br />Скрипт позволяет загружать историю с биржи MOEX.<br />-------------------------<br />Состоит из двух файлов.<br />---------------<br /><B>config.json &nbsp;</B>
====code====
<pre>{
&nbsp;&nbsp;&nbsp;&nbsp;"instruments": &#91;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"name": "SBER",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"start_date": "2015-01-01",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"decimal_places": 2,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"intervals": &#91;1, 10, 60, 24&#93;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"parameters": &#91;"open", "high", "low", "close", "volume"&#93;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"board": "TQBR"
&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;"name": "GAZP",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"start_date": "2015-01-01",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"decimal_places": 2,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"intervals": &#91;1, 10, 60, 24&#93;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"parameters": &#91;"open", "high", "low", "close", "volume"&#93;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"board": "TQBR"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;&#93;
}
</pre>
=============
<B>data_fetcher.py</B>
====code====
<pre>import os
import pandas as pd
import requests
import json
from datetime import datetime, timedelta

def load_config(config_file="config.json"):
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;Загружает конфигурацию из JSON файла

&nbsp;&nbsp;&nbsp;&nbsp;Параметры:
&nbsp;&nbsp;&nbsp;&nbsp;config_file (str): Путь к файлу конфигурации

&nbsp;&nbsp;&nbsp;&nbsp;Возвращает:
&nbsp;&nbsp;&nbsp;&nbsp;dict: Конфигурация
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;if not os.path.exists(config_file):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Файл конфигурации {config_file} не найден")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return None

&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with open(config_file, 'r', encoding='utf-8') as f:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config = json.load(f)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return config
&nbsp;&nbsp;&nbsp;&nbsp;except Exception as e:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Ошибка при загрузке конфигурации: {e}")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return None

def fetch_moex_data(ticker, start_date, end_date, interval=60):
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;Загружает данные с MOEX API для указанного тикера и временного периода

&nbsp;&nbsp;&nbsp;&nbsp;Параметры:
&nbsp;&nbsp;&nbsp;&nbsp;ticker (str): Тикер инструмента
&nbsp;&nbsp;&nbsp;&nbsp;start_date (datetime): Начальная дата загрузки
&nbsp;&nbsp;&nbsp;&nbsp;end_date (datetime): Конечная дата загрузки
&nbsp;&nbsp;&nbsp;&nbsp;interval (int): Интервал свечей в минутах (по умолчанию 60 минут)

&nbsp;&nbsp;&nbsp;&nbsp;Возвращает:
&nbsp;&nbsp;&nbsp;&nbsp;pd.DataFrame: DataFrame с загруженными данными
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;data = &#91;&#93;
&nbsp;&nbsp;&nbsp;&nbsp;current_start = start_date
&nbsp;&nbsp;&nbsp;&nbsp;print(f"Загрузка данных с MOEX для {ticker} (интервал: {interval} мин) с {start_date} по {end_date}...")

&nbsp;&nbsp;&nbsp;&nbsp;while True:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url = f"http://iss.moex.com/iss/engines/stock/markets/shares/boards/TQBR/securities/{ticker}/candles.json"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;params = {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'from': current_start.strftime('%Y-%m-%d'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'till': end_date.strftime('%Y-%m-%d'),
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'interval': interval,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'start': 0
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response = requests.get(url, params=params)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.raise_for_status()&nbsp;&nbsp;# Проверка на ошибки HTTP
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;json_data = response.json()

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if 'candles' not in json_data or 'data' not in json_data&#91;'candles'&#93;:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Нет данных в ответе API")
&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;candles = pd.DataFrame(json_data&#91;'candles'&#93;&#91;'data'&#93;,
&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;columns=json_data&#91;'candles'&#93;&#91;'columns'&#93;)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(candles) == 0:
&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;data.append(candles)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Обновляем время для следующего запроса
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current_start = (pd.to_datetime(candles&#91;'end'&#93;.iloc&#91;-1&#93;) + timedelta(minutes=interval))

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if len(candles) &#60; 500:&nbsp;&nbsp;# Если получено меньше 500 записей, это последняя порция
&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;except requests.exceptions.RequestException as e:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Ошибка при запросе данных: {e}")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break

&nbsp;&nbsp;&nbsp;&nbsp;print(f"Загружено {len(data)} блоков данных")

&nbsp;&nbsp;&nbsp;&nbsp;if not data:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return pd.DataFrame()

&nbsp;&nbsp;&nbsp;&nbsp;# Объединяем все блоки данных и удаляем дубликаты
&nbsp;&nbsp;&nbsp;&nbsp;return pd.concat(data).drop_duplicates()

def process_raw_data(raw_data):
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;Обрабатывает сырые данные: разделяет begin на date и time, удаляет end

&nbsp;&nbsp;&nbsp;&nbsp;Параметры:
&nbsp;&nbsp;&nbsp;&nbsp;raw_data (pd.DataFrame): Сырые данные с MOEX

&nbsp;&nbsp;&nbsp;&nbsp;Возвращает:
&nbsp;&nbsp;&nbsp;&nbsp;pd.DataFrame: Обработанные данные
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;# Разделение begin на date и time
&nbsp;&nbsp;&nbsp;&nbsp;raw_data&#91;'date'&#93; = pd.to_datetime(raw_data&#91;'begin'&#93;).dt.date

&nbsp;&nbsp;&nbsp;&nbsp;# Преобразование времени в формат без двоеточий (HHMMSS)
&nbsp;&nbsp;&nbsp;&nbsp;raw_data&#91;'time'&#93; = pd.to_datetime(raw_data&#91;'begin'&#93;).dt.strftime('%H%M%S')

&nbsp;&nbsp;&nbsp;&nbsp;# Удаление ненужных столбцов
&nbsp;&nbsp;&nbsp;&nbsp;columns_to_keep = &#91;'date', 'time', 'open', 'high', 'low', 'close', 'volume'&#93;
&nbsp;&nbsp;&nbsp;&nbsp;processed_data = raw_data&#91;columns_to_keep&#93;.copy()

&nbsp;&nbsp;&nbsp;&nbsp;# Сортировка по дате и времени
&nbsp;&nbsp;&nbsp;&nbsp;processed_data = processed_data.sort_values(&#91;'date', 'time'&#93;)

&nbsp;&nbsp;&nbsp;&nbsp;return processed_data

def get_last_available_date(ticker_dir):
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;Определяет последнюю дату, за которую есть данные в структуре каталогов

&nbsp;&nbsp;&nbsp;&nbsp;Параметры:
&nbsp;&nbsp;&nbsp;&nbsp;ticker_dir (str): Путь к каталогу тикера

&nbsp;&nbsp;&nbsp;&nbsp;Возвращает:
&nbsp;&nbsp;&nbsp;&nbsp;datetime.date: Последняя дата или None, если данных нет
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;last_date = None

&nbsp;&nbsp;&nbsp;&nbsp;# Проходим по всем подкаталогам (годы)
&nbsp;&nbsp;&nbsp;&nbsp;if not os.path.exists(ticker_dir):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return None

&nbsp;&nbsp;&nbsp;&nbsp;for year_dir in os.listdir(ticker_dir):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;year_path = os.path.join(ticker_dir, year_dir)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not os.path.isdir(year_path):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Проходим по месяцам
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for month_dir in os.listdir(year_path):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;month_path = os.path.join(year_path, month_dir)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not os.path.isdir(month_path):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Проходим по дням
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for day_dir in os.listdir(month_path):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;day_path = os.path.join(month_path, day_dir)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not os.path.isdir(day_path):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&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 not day_dir.isdigit():
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&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;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;year = int(year_dir)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;month = int(month_dir)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;day = int(day_dir)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;current_date = datetime(year, month, day).date()
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&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 last_date is None or current_date &#62; last_date:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;last_date = current_date

&nbsp;&nbsp;&nbsp;&nbsp;return last_date

def update_data_file(ticker, interval, output_dir, start_date, end_date):
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;Обновляет файлы данных, добавляя новые записи при необходимости

&nbsp;&nbsp;&nbsp;&nbsp;Параметры:
&nbsp;&nbsp;&nbsp;&nbsp;ticker (str): Тикер инструмента
&nbsp;&nbsp;&nbsp;&nbsp;interval (int): Интервал свечей в минутах
&nbsp;&nbsp;&nbsp;&nbsp;output_dir (str): Путь к каталогу для сохранения данных
&nbsp;&nbsp;&nbsp;&nbsp;start_date (datetime): Начальная дата для загрузки
&nbsp;&nbsp;&nbsp;&nbsp;end_date (datetime): Конечная дата для загрузки

&nbsp;&nbsp;&nbsp;&nbsp;Возвращает:
&nbsp;&nbsp;&nbsp;&nbsp;None
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;# Определяем последнюю дату, за которую есть данные
&nbsp;&nbsp;&nbsp;&nbsp;last_date = get_last_available_date(output_dir)

&nbsp;&nbsp;&nbsp;&nbsp;if last_date is None:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Данных нет, загружаем с начальной даты
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_start_date = start_date
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Не найдено существующих данных. Загружаем все данные...")
&nbsp;&nbsp;&nbsp;&nbsp;else:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Загружаем с последней даты (включительно)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new_start_date = datetime.combine(last_date, datetime.min.time())
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Найдены данные до {last_date}. Загружаем новые данные начиная с этой даты...")

&nbsp;&nbsp;&nbsp;&nbsp;# Загружаем данные с MOEX
&nbsp;&nbsp;&nbsp;&nbsp;raw_data = fetch_moex_data(ticker, new_start_date, end_date, interval)

&nbsp;&nbsp;&nbsp;&nbsp;if raw_data.empty:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Нет новых данных для загрузки")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return

&nbsp;&nbsp;&nbsp;&nbsp;# Обрабатываем данные
&nbsp;&nbsp;&nbsp;&nbsp;processed_data = process_raw_data(raw_data)

&nbsp;&nbsp;&nbsp;&nbsp;# Сохраняем данные, разбивая по датам
&nbsp;&nbsp;&nbsp;&nbsp;save_data_by_date(ticker, interval, output_dir, processed_data)

&nbsp;&nbsp;&nbsp;&nbsp;print(f"Загружено и сохранено {len(processed_data)} записей")

def save_data_by_date(ticker, interval, output_dir, data):
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;Сохраняет данные с разбиением по датам в подкаталоги

&nbsp;&nbsp;&nbsp;&nbsp;Параметры:
&nbsp;&nbsp;&nbsp;&nbsp;ticker (str): Тикер инструмента
&nbsp;&nbsp;&nbsp;&nbsp;interval (int): Интервал в минутах
&nbsp;&nbsp;&nbsp;&nbsp;output_dir (str): Базовый каталог для сохранения
&nbsp;&nbsp;&nbsp;&nbsp;data (pd.DataFrame): Данные для сохранения

&nbsp;&nbsp;&nbsp;&nbsp;Возвращает:
&nbsp;&nbsp;&nbsp;&nbsp;None
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;# Получаем имя интервала
&nbsp;&nbsp;&nbsp;&nbsp;interval_name = get_interval_name(interval)

&nbsp;&nbsp;&nbsp;&nbsp;# Группируем данные по датам
&nbsp;&nbsp;&nbsp;&nbsp;grouped = data.groupby('date')

&nbsp;&nbsp;&nbsp;&nbsp;for date, day_data in grouped:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Разбиваем дату на год, месяц, день
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;year = date.year
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;month = date.month
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;day = date.day

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Форматируем месяц и день с ведущими нулями
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;month_str = f"{month:02d}"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;day_str = f"{day:02d}"

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Формируем путь к каталогу для этой даты
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date_dir = os.path.join(output_dir, str(year), month_str, day_str)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Создаем каталог, если он не существует
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.makedirs(date_dir, exist_ok=True)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Создаем подкаталог для интервала
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interval_dir = os.path.join(date_dir, interval_name)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;os.makedirs(interval_dir, exist_ok=True)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Удаляем столбец date перед сохранением
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;day_data_to_save = day_data.drop(columns=&#91;'date'&#93;)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Сохраняем каждый параметр в отдельный файл
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for column in day_data_to_save.columns:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;file_path = os.path.join(interval_dir, column)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Сохраняем столбец без индекса и без заголовка
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;day_data_to_save&#91;column&#93;.to_csv(file_path, index=False, header=False)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Сохранено {len(day_data_to_save&#91;column&#93;)} значений параметра '{column}' за {date} в {file_path}")

def get_interval_name(interval):
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;Преобразует интервал в минутах в текстовое представление

&nbsp;&nbsp;&nbsp;&nbsp;Параметры:
&nbsp;&nbsp;&nbsp;&nbsp;interval (int): Интервал в минутах

&nbsp;&nbsp;&nbsp;&nbsp;Возвращает:
&nbsp;&nbsp;&nbsp;&nbsp;str: Текстовое представление интервала
&nbsp;&nbsp;&nbsp;&nbsp;"""
&nbsp;&nbsp;&nbsp;&nbsp;if interval == 1:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "1min"
&nbsp;&nbsp;&nbsp;&nbsp;elif interval == 10:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "10min"
&nbsp;&nbsp;&nbsp;&nbsp;elif interval == 60:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "1hour"
&nbsp;&nbsp;&nbsp;&nbsp;elif interval == 1440:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return "1day"
&nbsp;&nbsp;&nbsp;&nbsp;else:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return f"{interval}min"

if __name__ == "__main__":
&nbsp;&nbsp;&nbsp;&nbsp;# Загрузка конфигурации
&nbsp;&nbsp;&nbsp;&nbsp;config = load_config()
&nbsp;&nbsp;&nbsp;&nbsp;if not config:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Не удалось загрузить конфигурацию. Выход...")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(1)

&nbsp;&nbsp;&nbsp;&nbsp;# Параметры загрузки
&nbsp;&nbsp;&nbsp;&nbsp;end_date = datetime.now()

&nbsp;&nbsp;&nbsp;&nbsp;print(f"Начало загрузки данных для тикеров: {', '.join(&#91;item&#91;'ticker'&#93; for item in config&#91;'tickers'&#93;&#93;)}")
&nbsp;&nbsp;&nbsp;&nbsp;print(f"Период: с {min(&#91;datetime.strptime(item&#91;'start_date'&#93;, '%Y-%m-%d') for item in config&#91;'tickers'&#93;&#93;)} по {end_date.strftime('%Y-%m-%d')}")
&nbsp;&nbsp;&nbsp;&nbsp;print("-" * 50)

&nbsp;&nbsp;&nbsp;&nbsp;# Обработка каждого тикера и интервала
&nbsp;&nbsp;&nbsp;&nbsp;for ticker_config in config&#91;'tickers'&#93;:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ticker = ticker_config&#91;'ticker'&#93;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start_date_str = ticker_config&#91;'start_date'&#93;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;intervals = ticker_config&#91;'intervals'&#93;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Преобразование начальной даты из строки в datetime
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start_date = datetime.strptime(start_date_str, '%Y-%m-%d')
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;except ValueError:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Ошибка в формате даты для тикера {ticker}: {start_date_str}")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"&#92;nОбработка тикера: {ticker} (начальная дата: {start_date_str})")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Интервалы: {', '.join(&#91;get_interval_name(i) for i in intervals&#93;)}")

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Формирование пути к каталогу для сохранения данных
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;base_dir = "moex"
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ticker_dir = os.path.join(base_dir, ticker)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Обработка каждого интервала для текущего тикера
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for interval in intervals:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"&#92;nОбработка интервала: {get_interval_name(interval)}")

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Обновление файла данных
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_data_file(ticker, interval, ticker_dir, start_date, end_date)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Проверка сохраненных данных
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("&#92;nПроверка сохраненных данных:")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interval_name = get_interval_name(interval)

&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 os.path.exists(ticker_dir):
&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;dates_found = &#91;&#93;

&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;for year_dir in sorted(os.listdir(ticker_dir)):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;year_path = os.path.join(ticker_dir, year_dir)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if not os.path.isdir(year_path):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue

&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;&nbsp;&nbsp;&nbsp;&nbsp;for month_dir in sorted(os.listdir(year_path)):
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;month_path = os.path.join(year_path, month_dir)
&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 not os.path.isdir(month_path):
&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;continue

&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for day_dir in sorted(os.listdir(month_path)):
&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;day_path = os.path.join(month_path, day_dir)
&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 not os.path.isdir(day_path):
&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;continue

&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interval_path = os.path.join(day_path, interval_name)
&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 os.path.isdir(interval_path):
&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;&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;try:
&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;year = int(year_dir)
&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;month = int(month_dir)
&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;day = int(day_dir)
&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;date_str = f"{year:04d}-{month:02d}-{day:02d}"
&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;dates_found.append(date_str)
&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;except:
&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;pass

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if dates_found:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"Найдено {len(dates_found)} дат с данными:")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# Показываем последние 5 дат
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for date_str in sorted(dates_found)&#91;-5:&#93;:
&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interval_path = os.path.join(ticker_dir, date_str.split('-')&#91;0&#93;,
&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date_str.split('-')&#91;1&#93;, date_str.split('-')&#91;2&#93;,
&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interval_name)

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #&nbsp;&nbsp;&nbsp;&nbsp; if os.path.exists(interval_path):
&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;print(f"&nbsp;&nbsp;{date_str}:")

&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for param in &#91;'time', 'open', 'high', 'low', 'close', 'volume'&#93;:
&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;param_file = os.path.join(interval_path, param)
&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 os.path.exists(param_file):
&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;# Читаем файл
&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;param_data = pd.read_csv(param_file, header=None)
&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;print(f"&nbsp;&nbsp;&nbsp;&nbsp;{param}: {len(param_data)} значений")

&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;# Выводим последние 3 значения для проверки
&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; if len(param_data) &#62; 0:
&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;&nbsp;&nbsp; print(f"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Последние 3 значения: {', '.join(map(str, param_data.tail(3).values.flatten()))}")
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(f"&nbsp;&nbsp;{date_str}: каталог интервала не найден")
&nbsp;&nbsp;&nbsp;&nbsp;&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;&nbsp;&nbsp;&nbsp;&nbsp;print("Данные не найдены")
&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;print(f"Каталог тикера {ticker} не найден")

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("-" * 30)

&nbsp;&nbsp; #&nbsp;&nbsp;&nbsp;&nbsp; print("-" * 50)

&nbsp;&nbsp;&nbsp;&nbsp;print("&#92;nЗагрузка данных завершена для всех инструментов и интервалов")
</pre>
============= <br />
			<i>17.09.2025 14:54:10, nikolz.</i>]]></description>
			<link>http://forum.quik.ru/messages/forum17/message79523/topic9257/</link>
			<guid>http://forum.quik.ru/messages/forum17/message79523/topic9257/</guid>
			<pubDate>Wed, 17 Sep 2025 14:54:10 +0300</pubDate>
			<category>Обмен опытом</category>
		</item>
	</channel>
</rss>
