Блог им. Grossmend

Скачиваем котировки акций через Python

 

Скачиваем котировки акций через Python

В 2016 году я делился постом на Smart-Lab о том, как скачивать котировки через Excel. Тогда это был удобный способ для многих. Сегодня я хочу поделиться простым Python скриптом для загрузки котировок через API Тинькофф Инвестиций.

Этот скрипт легко адаптировать под ваши нужды, даже если вы новичок. Вам понадобится только библиотека tinkoff.invest. (я не сотрудник Тинькофф и не рекламирую их — просто делюсь рабочим инструментом)

Важно: Код не запустится без токена API. Его получают на официальной странице Тинькофф Инвестиций.

Вот сам скрипт. Он загружает свечи (цены акций) для указанных тикеров и сохраняет их в CSV-файлы. Просто настройте тикеры, даты и интервал под себя.

# Импорт модуля os для работы с операционной системой (например, для работы с файлами и директориями)
import os
# Импорт библиотеки pandas для работы с данными в формате DataFrame
import pandas as pd

# Импорт класса datetime для работы с датами и временем
from datetime import datetime
# Импорт классов Client и CandleInterval из библиотеки tinkoff. <a name="cut"></a> invest для работы с API Тинькофф Инвестиций
from tinkoff.invest import Client, CandleInterval

# Определение переменной TOKEN, содержащей токен для доступа к API Тинькофф
# Обычно токен берется из переменной окружения INVEST_TOKEN
# TOKEN = os.environ.get("INVEST_TOKEN")

# В данном случае токен задан напрямую как строка (для примера, в реальном коде так делать не нужно)
# Почитайте о переменных окружения
TOKEN = 'тут_находится_токен'

# Проверка, задан ли токен; если нет, выбрасывается исключение
if not TOKEN:
    raise ValueError("Please set the INVEST_TOKEN environment variable.")

# Определение функции для загрузки свечей (ценовых данных) для нескольких инструментов
def download_candles_for_multiple_figis(id_instruments, start_date, end_date, interval, output_dir="quotes"):
    """
    Функция загружает свечи для нескольких FIGI и сохраняет их в отдельные CSV-файлы.

    Аргументы:
        id_instruments: Список тикеров инструментов
        start_date: Начальная дата в формате 'ГГГГ-ММ-ДД'
        end_date: Конечная дата в формате 'ГГГГ-ММ-ДД'
        interval: Интервал свечей ('1m', '5m', '15m', '1h', '1d')
        output_dir: Папка для сохранения CSV-файлов
    """
    # Словарь для сопоставления строкового интервала свечей с соответствующими значениями из CandleInterval
    interval_mapping = {
        "1m": CandleInterval.CANDLE_INTERVAL_1_MIN,
        "5m": CandleInterval.CANDLE_INTERVAL_5_MIN,
        "15m": CandleInterval.CANDLE_INTERVAL_15_MIN,
        "1h": CandleInterval.CANDLE_INTERVAL_HOUR,
        "1d": CandleInterval.CANDLE_INTERVAL_DAY,
    }

    # Проверка, является ли указанный интервал допустимым; если нет, выбрасывается исключение
    if interval not in interval_mapping:
        raise ValueError(f"Invalid interval. Available intervals: {list(interval_mapping.keys())}")

    # Попытка преобразовать строки дат в объекты datetime
    try:
        start = datetime.strptime(start_date, "%Y-%m-%d")
        end = datetime.strptime(end_date, "%Y-%m-%d")
    # Если формат даты неверный, выбрасывается исключение
    except ValueError:
        raise ValueError("Dates must be in 'YYYY-MM-DD' format.")

    # Проверка существования директории для сохранения файлов; если её нет, она создаётся
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    # Создание клиента для работы с API Тинькофф, используя токен
    with Client(TOKEN) as client:
        # Цикл по каждому тикеру инструмента из списка
        for id_instrument in id_instruments:
            try:
                # Поиск инструмента по тикеру через API
                response = client.instruments.find_instrument(query=id_instrument)
                # Проверка всех найденных инструментов
                for instrument in response.instruments:
                    # Если инструмент относится к бирже TQBR и его тикер совпадает с искомым
                    if instrument.class_code == 'TQBR' and instrument.ticker == id_instrument:
                        figi = instrument.figi  # Сохраняем FIGI инструмента
                        break
                else:
                    # Если инструмент не найден, выбрасывается исключение
                    raise ValueError(f"Instrument {id_instrument} not found in TQBR")

                # Список для хранения данных о свечах
                candles = []
                # Получение всех свечей для инструмента в указанном диапазоне дат и интервале
                for candle in client.get_all_candles(
                        figi=figi,
                        from_=start,
                        to=end,
                        interval=interval_mapping[interval]
                ):
                    # Добавление данных свечи в список в виде словаря
                    candles.append({
                        "time": candle.time,  # Время свечи
                        "open": candle.open.units + candle.open.nano / 1e9,  # Цена открытия (в рублях)
                        "high": candle.high.units + candle.high.nano / 1e9,  # Максимальная цена
                        "low": candle.low.units + candle.low.nano / 1e9,    # Минимальная цена
                        "close": candle.close.units + candle.close.nano / 1e9,  # Цена закрытия
                        "volume": candle.volume  # Объём торгов
                    })

                # Если данные о свечах отсутствуют, выводится сообщение, и цикл переходит к следующему инструменту
                if not candles:
                    print(f"No data found for FIGI: {figi}")
                    continue

                # Создание DataFrame из списка свечей
                df = pd.DataFrame(candles)
                # Формирование пути для сохранения CSV-файла
                output_file = os.path.join(output_dir, f"quotes_{figi}_{id_instrument}.csv")
                # Сохранение DataFrame в CSV-файл без индекса
                df.to_csv(output_file, index=False)

                # Вывод сообщения об успешном сохранении файла
                print(f"Data for FIGI {figi} and {id_instrument} saved to {output_file}")

            # Обработка ошибок при загрузке данных для инструмента
            except Exception as e:
                print(f"Error fetching data for FIGI {figi}: {e}")
                continue


if __name__ == "__main__":

    # Список тикеров инструментов для загрузки данных (задается списком)
    id_instruments = [
        "SBER",
        "GAZP",
        "VTBR",
        "T",
        "LKOH",
        "NVTK",
        "AFLT",
        "GMKN",
        "YDEX",
    ]

    # Вызов функции для загрузки свечей с заданными параметрами
    download_candles_for_multiple_figis(
        id_instruments=id_instruments,  # Список тикеров
        start_date="2025-08-06",       # Начальная дата
        end_date="2025-08-07",         # Конечная дата
        interval="1m",                  # Интервал свечей (1 минута)
        output_dir="quotes",             # Папка для сохранения файлов
    )

 Как использовать: 

1 — Установите библиотеку: tinkoff-invest
2 — Получите токен API от Тинькофф
3 — Замените "тут_находится_токен" на ваш токен
4 — Настройте тикеры (id_instruments), даты и интервал (interval)
5 — Запустите скрипт — данные сохранятся в папке quotes в виде CSV-файлов

Код простой, но гибкий. Добавляйте свои тикеры, меняйте интервалы или формат вывода. Дорабатывайте под свои задачи.

Важно: Никогда не передавайте токен третьим лицам — это ключ к вашим данным

720 | ★2
8 комментариев
Спасибо
avatar
Не то же самое? smart-lab.ru/blog/1179974.php
avatar
Михаил Шардин, 

Данная публикация фокусируется на загрузке исторических данных через API Тинькофф и сохранении их в CSV-файлы для анализа (предполагается для больших данных). Ваша же больше на мониторинг в реальном времени)

avatar
Grossmend, 
avatar
Да такие скрипты на раз через ИИ пишутся. Сейчас уже ценность около нуля. Лучше бы писали статьи как работать и решать прикладные задачи через ГПТ или Антропик. Полезнее было.
avatar
У меня кровь из глаз сочиться когда вижу код с 5 уровнями вложенности
avatar
Михаил, а почему??? 
avatar
Ho_Chu, наверное потому что так не пишут нормальный код. Но почему-то большинство кода, который публикуют на СмартЛабе, без содрогания смотреть не возможно
avatar

Читайте на SMART-LAB:
Фото
Сбер РПБУ 11 мес. 2025 г. - дивдоходность на уровне вкладов
Сбер опубликовал результаты за 11 месяцев по РПБУ. Чистая прибыль выросла на 8,5% до 1,57 трлн руб., за ноябрь +26,8% до 148,7 млрд руб....
Фото
В подарок — стабильность. Портфель на 2026 год
После бурного 2025 года многие инвесторы загадывают одно желание — стабильность. А лучшим подарком был бы портфель, который может спокойно расти и...
Фото
Сделка года. Как слияние Netflix и Warner Bros. Discovery повлияет на рынок
В пятницу, 5 декабря, стриминговый гигант Netflix объявил, что покупает киностудию и стриминговый бизнес Warner Bros. Discovery за $72 млрд....

теги блога Grossmend

....все тэги



UPDONW
Новый дизайн