Git Product home page Git Product logo

invest-python's Introduction

Tinkoff Invest

GitHub Workflow Status PyPI PyPI - Python Version Docs GitHub PyPI - Downloads GitHub last commit

Данный репозиторий предоставляет клиент для взаимодействия с торговой платформой Тинькофф Инвестиции на языке Python.

Начало работы

$ pip install tinkoff-investments

Возможности

  • ☑ Синхронный и асинхронный GRPC клиент
  • ☑ Возможность отменить все заявки
  • ☑ Выгрузка истории котировок "от" и "до"
  • ☑ Кеширование данных
  • ☑ Торговая стратегия

Как пользоваться

Получить список аккаунтов

from tinkoff.invest import Client

TOKEN = 'token'

with Client(TOKEN) as client:
    print(client.users.get_accounts())

Переопределить target

В Tinkoff Invest API есть два контура - "боевой", предназначенный для исполнения ордеров на бирже и "песочница", предназначенный для тестирования API и торговых гипотез, заявки с которого не выводятся на биржу, а исполняются в эмуляторе.

Переключение между контурами реализовано через target, INVEST_GRPC_API - "боевой", INVEST_GRPC_API_SANDBOX - "песочница"

from tinkoff.invest import Client
from tinkoff.invest.constants import INVEST_GRPC_API

TOKEN = 'token'

with Client(TOKEN, target=INVEST_GRPC_API) as client:
    print(client.users.get_accounts())

⚠️ Не публикуйте токены в общедоступные репозитории


Остальные примеры доступны в examples.

Contribution

Для тех, кто хочет внести свои изменения в проект.

License

Лицензия The Apache License.

invest-python's People

Contributors

0dminnimda avatar alexandervolkovtcs avatar anta-semenov avatar b1ng0o avatar daxartio avatar ddmitiy avatar github-actions[bot] avatar grasth avatar gt-volk avatar irusland avatar kordimsan avatar martins0n avatar sourinjir avatar terekhinao avatar therb1 avatar wiseplat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

invest-python's Issues

[Issue] Неочевидное поведение при запросе get_all_candles

Что случилось?

Сегодня (19.04) начали немного странно работать выборки по свечам.
При запросе с 17.04 по 19.04 возвращается две дневных свечи, за 18.04 и 19.04, это ок.
При аналогичном запросе с 18.04 по 19.04 ожидаю увидеть сегодняшнюю дневную свечу (19.04) - но не возвращается ни одной.

Воспроизведение

Выполняемый код:

import asyncio
from datetime import datetime, timedelta

from tinkoff.invest import AsyncClient, CandleInterval
from tinkoff.invest.token import TOKEN


async def main():
    async with AsyncClient(TOKEN) as client:
        print(f'This selection goes from {datetime.today() - timedelta(days=2)} to {datetime.today()}')
        async for candle in client.get_all_candles(
            figi="BBG004S68BR5",
            from_=datetime.today() - timedelta(days=2),
            to=datetime.today(),
            interval=CandleInterval.CANDLE_INTERVAL_DAY,
        ):
            print(candle.volume, candle.time)

        print(f'This selection goes from {datetime.today() - timedelta(days=1)} to {datetime.today()}')
        async for candle in client.get_all_candles(
            figi="BBG004S68BR5",
            from_=datetime.today() - timedelta(days=1),
            to=datetime.today(),
            interval=CandleInterval.CANDLE_INTERVAL_DAY,
        ):
            print(candle.volume, candle.time)



if __name__ == "__main__":
    asyncio.run(main())

Tinkoff Invest Version

0.2.0-beta20

Python Version

3.9

OS

Windows

Логи

No response

Публикация пакета в test.pypi

Ветку develop стоит опубликовать в тестовом режистри. Чтобы пользователи уже могли тестировать функционал.

PostOrder

PostOrder

При выставлении лимитного торгового поручения необходимо записать Price в Quotation, который состоит из PriceUnits и PriceNano, которые в формате int32-64. Как записать PriceNano в int, если вначале необходимо добавить нули, которые есть только в формате str?

Воспроизведение

No response

Tinkoff Invest Version

Другая

Python Version

Другая

OS

Windows

Логи

No response

Code Completion in PyCharm

Что случилось?

Не работает автозаполнение кода в PyCharm в области редактирования. Инвалидами и реиндексация кэша не помогает. В run time в консоли PyCharm все работает

Воспроизведение

import tinkoff.invest as invest

with invest.Client(TOKEN) as client:
client.

Tinkoff Invest Version

0.2.0-beta23

Python Version

3.9

OS

Mac OS

Логи

No response

[Bug] ValueError: metadata was invalid

Что случилось?

При попытке что-либо сделать, выдает
image

Воспроизведение

f = open("../../../sen/t", "rt")
TOKEN = f.read()
f.close()

from tinkoff.invest import Client
from tinkoff.invest.constants import INVEST_GRPC_API
from tinkoff.invest.schemas import InstrumentIdType

with Client(TOKEN, target=INVEST_GRPC_API) as client:
    print(client.users.get_accounts())

TOKEN пересоздал на всякий (и дал полный доступ).

Tinkoff Invest Version

0.2.0-beta30

Python Version

3.10

OS

Linux

Логи

No response

Кеширование

Есть необходимость кешировать данные.

Добавить кеши для:
...

Кеши хранить на диске, чтобы после рестарта, можно было использовать их.
Также добавить хранение в памяти.

Кеши хранить в протоформате.

[Bug] TypeError: Protocols cannot be instantiated

Что случилось?

Ошибка TypeError: Protocols cannot be instantiated при работе образца стратегии из поставки

Воспроизведение

запустить файл из поставки ~/invest-python/examples/strategies/param-search.ipynb

Ошибка возникает при выполнении блока кода после "Обеспечить такой выбор через обращение к полю events в виде events(best_stock)".

Выполнено три итерации с результатами:
2022-02-01 20:00:00,000 INFO:5ee74bd2e50c67dab24fcde8494fe5ed GetCandles
2022-02-01 20:00:00,000 INFO:a3a5dc504ae68ebbf6d20c08d16b6196 GetCandles
2022-02-01 20:00:00,000 INFO:73d98cb7d9fb90ac14c53d3c57ca5ffc GetCandles

Получена ошибка: TypeError: Protocols cannot be instantiated

Tinkoff Invest Version

0.2.0-beta21

Python Version

3.9

OS

Windows

Логи

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_9120/2488483488.py in <module>
     32         )
     33         state = MovingAverageStrategyState()
---> 34         strategy = MovingAverageStrategy(
     35             settings=settings,
     36             account_manager=account_manager,

~\site-packages\tinkoff\invest\strategies\moving_average\strategy.py in __init__(self, settings, account_manager, state)
     44         state: MovingAverageStrategyState,
     45     ):
---> 46         super().__init__()
     47         self._data: List[CandleEvent] = []
     48         self._settings = settings

C:\ProgramData\Anaconda3\lib\typing.py in _no_init(self, *args, **kwargs)
   1081 
   1082 def _no_init(self, *args, **kwargs):
-> 1083     raise TypeError('Protocols cannot be instantiated')
   1084 
   1085 

TypeError: Protocols cannot be instantiated

[Bug] ModuleNotFoundError: No module named 'dateutil'

Что случилось?

  1. скопировал пример
from tinkoff.invest import Client

TOKEN = 'token'

with Client(TOKEN) as client:
    print(client.users.get_accounts())
  1. подставляю sandbox token
  2. запускаю

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta26

Python Version

3.10

OS

Mac OS (m1)

Логи

Traceback (most recent call last):
  File "/Users/pudins/Desktop/ne_tinkoff/test.py", line 1, in <module>
    from tinkoff.invest import Client
  File "/Users/pudins/Desktop/ne_tinkoff/venv/lib/python3.10/site-packages/tinkoff/invest/__init__.py", line 1, in <module>
    from .clients import AsyncClient, Client
  File "/Users/pudins/Desktop/ne_tinkoff/venv/lib/python3.10/site-packages/tinkoff/invest/clients.py", line 3, in <module>
    from .async_services import AsyncServices
  File "/Users/pudins/Desktop/ne_tinkoff/venv/lib/python3.10/site-packages/tinkoff/invest/async_services.py", line 137, in <module>
    from .utils import get_intervals, now
  File "/Users/pudins/Desktop/ne_tinkoff/venv/lib/python3.10/site-packages/tinkoff/invest/utils.py", line 7, in <module>
    import dateutil.parser  # noqa:  I900 'dateutil' not listed as a requirement
ModuleNotFoundError: No module named 'dateutil'

Как парсить nano при возвращении последней цены?

Что случилось?

Метод market_data.get_last_prices() возврщает units - целую часть и nano - дробную часть.
Вопрос такой, а как в nano отличить например 1 копейку от 10, если число заполняется нулями в ответе?

{'units': 0, 'nano': 10000000}

Проблема при выставлении лимитного ордера на цене с дробным числом

Что случилось?

отправляю запрос на выставление лимитного лонг ордера

client.orders.post_order(figi="BBG004730N88", quantity=size, price=Quotation(115, 5), direction=1, order_type=1, account_id=account_id, order_id=str(int(time.time() * 1000)))

но получаю такую ошибку, в чем может быть дело?

tinkoff.invest.exceptions.RequestError: (<StatusCode.INVALID_ARGUMENT: (3, 'invalid argument')>, '30049', Metadata(tracking_id='64e7338c2e78b86aa8829de3a1b4a01f', ratelimit_limit='300, 300;w=60', ratelimit_remaining=299, ratelimit_reset=19, message='post order error: Invalid Price. Possible reason: price should have no more than 15 digits before point and no more than 2 digits after point')

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta29

Python Version

3.8

OS

Windows

Логи

64e7338c2e78b86aa8829de3a1b4a01f PostOrder INVALID_ARGUMENT 30049
Traceback (most recent call last):
  File "C:\Users\yafen\AppData\Local\Programs\Python\Python38\lib\site-packages\tinkoff\invest\_errors.py", line 18, in wrapper
    return func(*args, **kwargs)
  File "C:\Users\yafen\AppData\Local\Programs\Python\Python38\lib\site-packages\tinkoff\invest\services.py", line 990, in post_order
    response, call = self.stub.PostOrder.with_call(
  File "C:\Users\yafen\AppData\Local\Programs\Python\Python38\lib\site-packages\grpc\_channel.py", line 957, in with_call
    return _end_unary_response_blocking(state, call, True, None)
  File "C:\Users\yafen\AppData\Local\Programs\Python\Python38\lib\site-packages\grpc\_channel.py", line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
	status = StatusCode.INVALID_ARGUMENT
	details = "30049"
	debug_error_string = "{"created":"@1654158761.116000000","description":"Error received from peer ipv4:91.194.227.80:443","file":"src/core/lib/surface/call.cc","file_line":1070,"grpc_message":"30049","grpc_status":3}"
>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "D:/PythonPrj/talborProject/tinkoff 33/trading_api_v2.py", line 148, in <module>
    print(long_limit("SBER", 1, 115.1))
  File "D:/PythonPrj/talborProject/tinkoff 33/trading_api_v2.py", line 106, in long_limit
    res = client.orders.post_order(figi=figi[symbol]["figi"], quantity=int(size), price=Quotation(x, y), direction=1, order_type=1, account_id=account_id, order_id=str(int(time.time() * 1000)))
  File "C:\Users\yafen\AppData\Local\Programs\Python\Python38\lib\site-packages\tinkoff\invest\_errors.py", line 28, in wrapper
    raise RequestError(
tinkoff.invest.exceptions.RequestError: (<StatusCode.INVALID_ARGUMENT: (3, 'invalid argument')>, '30049', Metadata(tracking_id='64e7338c2e78b86aa8829de3a1b4a01f', ratelimit_limit='300, 300;w=60', ratelimit_remaining=299, ratelimit_reset=19, message='post order error: Invalid Price. Possible reason: price should have no more than 15 digits before point and no more than 2 digits after point'))

Ошибка при выполнении запроса AsyncClient().instruments.trading_schedules()

Запрос расписания торгов делаю следующим образом.

async def trading_schedules(self,
                                exchange: str = "",
                                from_: Optional[datetime] = None,
                                to: Optional[datetime] = None) -> 'TradingSchedulesResponse':
        async with AsyncClient(self.token) as client:
            return await client.instruments.trading_schedules(exchange=exchange, from_=from_, to=to)

Во время выполнения возникает ошибка

  File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
    return future.result()
  File "/home/denis/markets/lib/markets_lib/tinkoff/collector.py", line 81, in trading_schedules
    return await client.instruments.trading_schedules(exchange=exchange, from_=from_, to=to)
  File "/home/denis/markets/env/lib/python3.8/site-packages/tinkoff/invest/_errors.py", line 68, in wrapper
    return await func(*args, **kwargs)
  File "/home/denis/markets/env/lib/python3.8/site-packages/tinkoff/invest/async_services.py", line 213, in trading_schedules
    request=_grpc_helpers.dataclass_to_protobuff(
  File "/home/denis/markets/env/lib/python3.8/site-packages/tinkoff/invest/_grpc_helpers.py", line 308, in dataclass_to_protobuff
    seconds, nanos = datetime_to_ts(field_value)
  File "/home/denis/markets/env/lib/python3.8/site-packages/tinkoff/invest/_grpc_helpers.py", line 31, in datetime_to_ts
    seconds = int(value.timestamp())
AttributeError: 'object' object has no attribute 'timestamp'
python-BaseException```

(<class 'AttributeError'>, AttributeError("'object' object has no attribute 'timestamp'"), <traceback object at 0x7f8c21bf5400>)

[Bug] trading_schedules "'from' can't be less than the current date"

Что случилось?

Каждый день, с нуля и до шести утра получаю ошибку "'from' can't be less than the current date" в функции trading_schedules.
При этом в from использую datetime.utcnow()

Воспроизведение

from datetime import datetime, timedelta, time
from tinkoff.invest import Client
from tinkoff.invest.token import TOKEN

with Client(TOKEN) as client:
    TradingSchedules = client.instruments.trading_schedules(exchange='', from_ = datetime.utcnow(), to=datetime.combine(datetime.utcnow()+timedelta(days=5), time(23, 59, 59, 999999)))

Tinkoff Invest Version

0.2.0-beta24

Python Version

3.9

OS

Windows

Логи

(<StatusCode.INVALID_ARGUMENT: (3, 'invalid argument')>, '30003', Metadata(tracking_id='9750d6e4e15f3a65038d0a0d8c99b60f', ratelimit_limit='200, 200;w=60', ratelimit_remaining=199, ratelimit_reset=33, message="'from' can't be less than the current date"))

[Feature] Как корректно параллельно слушать несколько streams?

Описание

Добрый день.
Перехожу на потоки, и возник вопрос - как оптимально ими пользоваться.
У меня в задачах, получать параллельно:

  1. минутные свечи (10-30 активов)
  2. часовые свечи (30-60 активов)
  3. выставлять новые торговые поручения (покупка-продажа)
  4. следить за сделками (покупка-продажа)
  5. отслеживать стаканы по единичным активам (до 15 активов)

Желаемое решение

Как корректно организовать прослушивание такого набора потоков, минимизировав количество подключений?
Есть пример реализации параллельно в одном модуле нескольких перечисленных пунктов?
В приложении пример, который набросал исходя из своих скромных знаний. Реализует пункты 1 и 4. Он корректный? Или можно как-то оптимизировать/улучшить?
Хочется сразу заложить корректное ядро, которое минимизирует кол-во подключений к серверу, а также будет устойчиво в части восстановления подключений при сбоях любого характера.
Думаю подобный пример от разработчикам SDK будет полезен многим клиентам, и сократит лишнюю нагрузку на сервера.

Дополнительно

import asyncio

from tinkoff.invest import (
    AsyncClient,
    CandleInstrument,
    MarketDataRequest,
    SubscribeCandlesRequest,
    SubscriptionAction,
    SubscriptionInterval
)
from tinkoff.invest.token import TOKEN


async def MarketData_iter():
    async def request_iterator():
        yield MarketDataRequest(
            subscribe_candles_request=SubscribeCandlesRequest(
                subscription_action=SubscriptionAction.SUBSCRIPTION_ACTION_SUBSCRIBE,
                instruments=[
                    CandleInstrument(
                        figi="BBG004730N88",
                        interval=SubscriptionInterval.SUBSCRIPTION_INTERVAL_ONE_MINUTE,
                    )
                ],
            )
        )
        while True:
            await asyncio.sleep(30)

    async with AsyncClient(TOKEN) as client:
        try:
            async for marketdata in client.market_data_stream.market_data_stream(request_iterator()):
                print(marketdata)
        except:
            print('error in market_data_stream')
            await asyncio.sleep(100)


async def TradesData():
    async with AsyncClient(TOKEN) as client:
        try:
            async for tradesdata in client.orders_stream.trades_stream():
                print(tradesdata)
                await asyncio.sleep(1)
        except:
            print('error in orders_stream')
            await asyncio.sleep(100)


async def check_state(ioloop):
    while True:
        print(ioloop.is_running())
        await asyncio.sleep(300)

if __name__ == "__main__":
    while True:
        ioloop = asyncio.get_event_loop()
        tasks = [ioloop.create_task(MarketData_iter()),
                 ioloop.create_task(TradesData()),
                 ioloop.create_task(check_state(ioloop))]
        wait_tasks = asyncio.wait(tasks)
        ioloop.run_until_complete(wait_tasks)
        ioloop.close()

[Feature] Получение типа актива из get_positions()

Описание

Функция возвращает PositionsSecurities, без указания типа актива.
Методы share_by, etf_by и т.д. вернут ошибку при попытке поиска по figi тех инструментов, которые не подходят под соответствующие методы.

Желаемое решение

Добавьте пожалуйста в ответ сервера тип актива, чтобы избавиться от лишних ошибок.

Дополнительно

PositionsSecurities(figi=string, blocked=int, balance=int, type=enum)

[Issue] Ошибка trades_stream()

Что случилось?

Добрый день. Не удается реализовать подписку по orders_stream.trades_stream()
Изначально писал по аналогии с market_data_stream.market_data_stream()

Выдает ошибку TypeError: OrdersStreamService.trades_stream() takes 1 positional argument but 2 were given

Сравнил код:

def market_data_stream(
self,
request_iterator: Iterable[MarketDataRequest],
) -> Iterable[MarketDataResponse]:
for response in self.stub.MarketDataStream(
request_iterator=self._convert_market_data_stream_request(request_iterator),
metadata=self.metadata,
):
yield _grpc_helpers.protobuf_to_dataclass(response, MarketDataResponse)

def trades_stream(self) -> Iterable[TradesStreamResponse]:
request = TradesStreamRequest()
for response in self.stub.TradesStream(
request=_grpc_helpers.dataclass_to_protobuff(
request, operations_pb2.WithdrawLimitsRequest()
),
metadata=self.metadata,
):
yield _grpc_helpers.protobuf_to_dataclass(response, TradesStreamResponse)

В объявлении trades_stream отсутствует request_iterator

Если так и задумано, то подскажите пожалуйста как реализовать функцию trades_stream().

Спасибо!

Воспроизведение

dotenv_path = join(dirname(file), '../.env')
load_dotenv(dotenv_path)

API_KEY = os.environ.get("API_KEY")

def request_iterator(id):
yield TradesStreamRequest(accounts=id)
while True:
time.sleep(1)

with Client(API_KEY) as client:
# Получаем список id аккаунтов
accounts = client.users.get_accounts().accounts
# Среди полученных акrаунтов ищем брокерские счета
brokerageAccount = [acc for acc in accounts if acc.type == 1]
# Получаем их id
brokerageAccountId = [
acc.id for acc in brokerageAccount if id]
for orderData in client.orders_stream.trades_stream(request_iterator(brokerageAccountId)):
print(orderData)

Tinkoff Invest Version

0.2.0-beta23

Python Version

3.10

OS

Windows

Логи

Traceback (most recent call last):
  File "*", line 31, in <module>
    for orderData in client.orders_stream.trades_stream(request_iterator(brokerageAccountId)):
  File "*\Roaming\Python\Python310\site-packages\tinkoff\invest\_errors.py", line 43, in wrapper
    yield from func(*args, **kwargs)
TypeError: OrdersStreamService.trades_stream() takes 1 positional argument but 2 were given

Стриминговый сервис не дает стакан глубиной больше 1

Что случилось?

При попытке подписаться с помощью сервиса котировок (стриминга) на стаканы глубиной более 1 уровня, данные отсутствуют . Работает только, при depth=1. Скажите пожалуйста с чем это может быть связано? При этом, если заглянуть в статус подписки, то он выдает, что глубина неверна (см. кизображение)
image

Воспроизведение

import tinkoff.invest as ti

load_dotenv()

token = os.getenv('token')
account_id = os.getenv('BROKER_ID')

figi = 'BBG004730RP0'
with ti.Client(token) as client:
    stream = client.create_market_data_stream()
    #stream.candles.subscribe([ti.CandleInstrument(figi=figi, interval=1)])
    stream.order_book.subscribe([ti.OrderBookInstrument(figi=figi, depth=2)])
    for data in stream:
        print(data.orderbook)

Tinkoff Invest Version

0.2.0-beta27

Python Version

3.8

OS

Windows

Логи

No response

MarketDataStream подписка на одном стриме для всех инструментов или...

Что случилось?

Здравствуйте!
Такой вопрос, могу ли я подписаться на одном стриме для нескольких инструментов торговли, или же это нужно делать: один стрим - один иструмент?

Воспроизведение

No response

Tinkoff Invest Version

Другая

Python Version

3.10

OS

Linux

Логи

No response

Не выполняется request SDK tinkoff-investments v 0.2.0b27 после конвертации *.py в *.exe

Что случилось?

В среде разработки все работает корректно, но после конвертации выполнение кода останавливается на первом же реквесте. Написал в службу поддержки Tinkoff, но они пока работают над моим вопросом и решения пока нет. Было предположение, что не передается токен, но я проверил, сто процентов токен передается. Есть предположение, что сборщик не видит какой-то нужный файл, Буду признателен за любые мысли по этому поводу. Всем удачи!

Воспроизведение

with Client(token) as client:
shares = client.instruments.shares().instruments

Tinkoff Invest Version

0.2.0-beta27

Python Version

3.9

OS

Windows

Логи

Лог Py_to_exe.txt
Совместный доступ

Свойства системы
Тип
Текст
Размер
14 КБ
Занимает
14 КБ
Расположение
Лог
Владелец
я
Изменено
07:02 (я)
Открыто
07:07 (я)
Создано
07:04 (Google Drive Web (Unverified))
Добавить описание
Читателям разрешено скачивать файл
Running auto-py-to-exe v2.19.0
Building directory: C:\Users\User\AppData\Local\Temp\tmp4n45oaeo
Provided command: pyinstaller --noconfirm --onedir --windowed --add-data "D:/PyCharm_Projects/tinvest/style.css;." --add-data "D:/PyCharm_Projects/tinvest/moex_schedule.csv;."  "D:/PyCharm_Projects/tinvest/SDK_v2_09.py"
Recursion Limit is set to 5000
Executing: pyinstaller --noconfirm --onedir --windowed --add-data D:/PyCharm_Projects/tinvest/style.css;. --add-data D:/PyCharm_Projects/tinvest/moex_schedule.csv;. D:/PyCharm_Projects/tinvest/SDK_v2_09.py --distpath C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\application --workpath C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\build --specpath C:\Users\User\AppData\Local\Temp\tmp4n45oaeo

209133 INFO: PyInstaller: 5.0.1
209133 INFO: Python: 3.9.7
209149 INFO: Platform: Windows-10-10.0.19044-SP0
209165 INFO: wrote C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\SDK_v2_09.spec
209183 INFO: UPX is not available.
209215 INFO: Extending PYTHONPATH with paths
['D:\\PyCharm_Projects\\tinvest']
209929 INFO: checking Analysis
209942 INFO: Building Analysis because Analysis-00.toc is non existent
209948 INFO: Initializing module dependency graph...
209966 INFO: Caching module graph hooks...
210011 INFO: Analyzing base_library.zip ...
212378 INFO: Processing pre-find module path hook distutils from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path\\hook-distutils.py'.
212434 INFO: distutils: retargeting to non-venv dir 'C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python39_64\\lib'
215363 INFO: Caching module dependency graph...
215522 INFO: running Analysis Analysis-00.toc
215550 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
  required by C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\python.exe
215628 INFO: Analyzing D:\PyCharm_Projects\tinvest\SDK_v2_09.py
219086 INFO: Processing pre-find module path hook site from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path\\hook-site.py'.
219117 INFO: site: retargeting to fake-dir 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\fake-modules'
229782 INFO: Processing pre-safe import module hook six.moves from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\pre_safe_import_module\\hook-six.moves.py'.
244416 INFO: Processing module hooks...
244428 INFO: Loading module hook 'hook-certifi.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
244526 INFO: Loading module hook 'hook-eel.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
244701 INFO: Loading module hook 'hook-lxml.etree.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
244715 INFO: Loading module hook 'hook-lxml.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
245543 INFO: Loading module hook 'hook-openpyxl.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
245921 INFO: Loading module hook 'hook-pycparser.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
245928 INFO: Loading module hook 'hook-difflib.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
245969 INFO: Loading module hook 'hook-distutils.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
245975 INFO: Loading module hook 'hook-distutils.util.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
245981 INFO: Loading module hook 'hook-encodings.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
246090 INFO: Loading module hook 'hook-gevent.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
246847 INFO: Determining a mapping of distributions to packages...
257052 WARNING: Unable to find package for requirement zope.event from package gevent.
257075 WARNING: Unable to find package for requirement zope.interface from package gevent.
257075 INFO: Packages required by gevent:
['setuptools', 'greenlet', 'cffi']
258235 INFO: Loading module hook 'hook-heapq.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
258264 INFO: Loading module hook 'hook-lib2to3.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
258420 INFO: Loading module hook 'hook-matplotlib.backends.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
258445 INFO: Matplotlib backend selection method: automatic discovery of used backends
258462 INFO: Selected matplotlib backends: ['Qt5Agg']
258557 INFO: Loading module hook 'hook-matplotlib.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
258954 INFO: Loading module hook 'hook-multiprocessing.util.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
258970 INFO: Loading module hook 'hook-numpy.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
259244 INFO: Import to be excluded not found: 'f2py'
259293 INFO: Loading module hook 'hook-numpy._pytesttester.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
259310 INFO: Loading module hook 'hook-packaging.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
259342 INFO: Loading module hook 'hook-pandas.io.formats.style.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
259876 INFO: Loading module hook 'hook-pandas.plotting.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
260177 INFO: Loading module hook 'hook-pandas.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
261635 INFO: Loading module hook 'hook-pickle.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
261647 INFO: Loading module hook 'hook-PIL.Image.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
262397 INFO: Loading module hook 'hook-PIL.ImageFilter.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
262413 INFO: Loading module hook 'hook-PIL.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
262447 INFO: Loading module hook 'hook-PIL.SpiderImagePlugin.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
262458 INFO: Loading module hook 'hook-pkg_resources.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
263493 INFO: Processing pre-safe import module hook win32com from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\pre_safe_import_module\\hook-win32com.py'.
264106 WARNING: Hidden import "pkg_resources.py2_warn" not found!
264123 WARNING: Hidden import "pkg_resources.markers" not found!
264129 INFO: Loading module hook 'hook-PyQt5.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
264441 INFO: Loading module hook 'hook-PyQt5.QtCore.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
264712 INFO: Loading module hook 'hook-PyQt5.QtGui.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
265134 INFO: Loading module hook 'hook-PyQt5.QtWidgets.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
265769 INFO: Loading module hook 'hook-PySide6.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
266747 INFO: Loading module hook 'hook-PySide6.QtCore.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
267200 INFO: Loading module hook 'hook-PySide6.QtGui.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
267728 INFO: Loading module hook 'hook-PySide6.QtNetwork.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
268666 INFO: Loading module hook 'hook-PySide6.QtWidgets.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
269178 INFO: Loading module hook 'hook-pytz.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
269350 INFO: Loading module hook 'hook-setuptools.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271330 INFO: Loading module hook 'hook-sqlite3.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271440 INFO: Loading module hook 'hook-sysconfig.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271458 INFO: Loading module hook 'hook-win32ctypes.core.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271895 INFO: Loading module hook 'hook-xml.dom.domreg.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271915 INFO: Loading module hook 'hook-xml.etree.cElementTree.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271916 INFO: Loading module hook 'hook-xml.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271926 INFO: Loading module hook 'hook-zope.interface.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
271943 INFO: Loading module hook 'hook-_tkinter.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
272149 INFO: checking Tree
272157 INFO: Building Tree because Tree-00.toc is non existent
272163 INFO: Building Tree Tree-00.toc
272318 INFO: checking Tree
272326 INFO: Building Tree because Tree-01.toc is non existent
272326 INFO: Building Tree Tree-01.toc
272439 INFO: checking Tree
272446 INFO: Building Tree because Tree-02.toc is non existent
272446 INFO: Building Tree Tree-02.toc
272460 INFO: Loading module hook 'hook-lxml.isoschematron.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
272476 INFO: Loading module hook 'hook-lxml.objectify.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\_pyinstaller_hooks_contrib\\hooks\\stdhooks'...
272492 INFO: Loading module hook 'hook-setuptools.msvc.py' from 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks'...
272558 INFO: Looking for ctypes DLLs
272685 INFO: Analyzing run-time hooks ...
272696 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_subprocess.py'
272754 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py'
272761 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py'
272778 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py'
272793 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pyside6.py'
272810 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgres.py'
272874 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pyqt5.py'
272885 INFO: Including run-time hook 'd:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_mplconfig.py'
272914 INFO: Looking for dynamic libraries
283822 INFO: Looking for eggs
283822 INFO: Using Python library C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\python39.dll
283822 INFO: Found binding redirects: 
[]
283853 INFO: Warnings written to C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\build\SDK_v2_09\warn-SDK_v2_09.txt
284088 INFO: Graph cross-reference written to C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\build\SDK_v2_09\xref-SDK_v2_09.html
284150 INFO: Appending 'datas' from .spec
284229 INFO: checking PYZ
284244 INFO: Building PYZ because PYZ-00.toc is non existent
284244 INFO: Building PYZ (ZlibArchive) C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\build\SDK_v2_09\PYZ-00.pyz
286424 INFO: Building PYZ (ZlibArchive) C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\build\SDK_v2_09\PYZ-00.pyz completed successfully.
286470 INFO: checking PKG
286486 INFO: Building PKG because PKG-00.toc is non existent
286502 INFO: Building PKG (CArchive) SDK_v2_09.pkg
286548 INFO: Building PKG (CArchive) SDK_v2_09.pkg completed successfully.
286564 INFO: Bootloader d:\pycharm_projects\venv\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe
286580 INFO: checking EXE
286596 INFO: Building EXE because EXE-00.toc is non existent
286596 INFO: Building EXE from EXE-00.toc
286611 INFO: Copying bootloader EXE to C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\build\SDK_v2_09\SDK_v2_09.exe.notanexecutable
286658 INFO: Copying icon to EXE
286658 INFO: Copying icons from ['d:\\pycharm_projects\\venv\\lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-windowed.ico']
286689 INFO: Writing RT_GROUP_ICON 0 resource with 104 bytes
286689 INFO: Writing RT_ICON 1 resource with 3752 bytes
286705 INFO: Writing RT_ICON 2 resource with 2216 bytes
286720 INFO: Writing RT_ICON 3 resource with 1384 bytes
286736 INFO: Writing RT_ICON 4 resource with 38188 bytes
286752 INFO: Writing RT_ICON 5 resource with 9640 bytes
286752 INFO: Writing RT_ICON 6 resource with 4264 bytes
286767 INFO: Writing RT_ICON 7 resource with 1128 bytes
286783 INFO: Copying 0 resources to EXE
286814 INFO: Embedding manifest in EXE
286830 INFO: Updating manifest in C:\Users\User\AppData\Local\Temp\tmp4n45oaeo\build\SDK_v2_09\SDK_v2_09.exe.notanexecutable
286846 INFO: Updating resource type 24 name 1 language 0
286877 INFO: Appending PKG archive to EXE
289471 INFO: Building EXE from EXE-00.toc completed successfully.
289486 INFO: checking COLLECT
289486 INFO: Building COLLECT because COLLECT-00.toc is non existent
289502 INFO: Building COLLECT COLLECT-00.toc
303784 INFO: Building COLLECT COLLECT-00.toc completed successfully.

Moving project to: D:\PyCharm_Projects\tinvest\output
Complete.

Документация на SDK

Что случилось?

Не могу сказать, что я супер гуру по современным средствам разработки. Может быть поэтому я никак не могу разобраться в самом Python SDK.
Документации или нет или я ее не могу найти.
Например:
Вот беру пример client.py
Вижу print(client.users.get_accounts()). Оригинальный запрос в API - GetAccounts из UsersService.
Пытаюсь аналогично получить список фьючерсов. Он в инструментах.
print(client.instruments.get_futures(instrument_status=INSTRUMENT_STATUS_ALL))- получаю: 'InstrumentsService' object has no attribute 'get_futures'
Предполагаю, надо что-то дополнительно импортнуть. Но что?
Где можно найти доку по официальной Python SDK? Какой метод соответствует чему в API? И как его вызывать?
В примерах нет ни операций, ни акций, ни фьюч, ни размещения ставки.
Или я как-то не так ищу? Спасибо.

Воспроизведение

  1. Шаг 1
  2. Шаг 2

Version

0.2.0-beta19

OS

Linux

Логи

No response

Упростить использование market_data_stream

Сейчас нужно удерживать итератор, чтобы не закрыть коннект маркетдаты. Выглядит это не очень очевидно, поэтому есть предложение поменять интерфейс на отдельный объект с методом subscribe.

Будет что-то вроде

with Client(TOKEN) as client:
    market_data_stream = client.create_market_data_stream()
    market_data_stream.subscribe(MarketDataRequest(...))
    for marketdata in market_data_stream:
        print(marketdata)
        market_data_stream.subscribe(MarketDataRequest(...))

[Bug]

Что случилось?

Ошибка при запросе истории как в #53

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta28

Python Version

3.10

OS

Linux

Логи

GetCandles UNAVAILABLE upstream request timeout
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/tinkoff/invest/_errors.py", line 18, in wrapper
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/tinkoff/invest/services.py", line 730, in get_candles
    response, call = self.stub.GetCandles.with_call(
  File "/usr/local/lib/python3.10/site-packages/grpc/_channel.py", line 957, in with_call
    return _end_unary_response_blocking(state, call, True, None)
  File "/usr/local/lib/python3.10/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNAVAILABLE
        details = "upstream request timeout"
        debug_error_string = "{"created":"@1653662845.758154867","description":"Error received from peer ipv4:91.194.227.80:443","file":"src/core/lib/surface/call.cc","file_line":952,"grpc_message":"upstream request timeout","grpc_status":14}"
>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/app/trading/service.py", line 285, in load_history
    response = self.get_history_candles(client, date_to, figi, date_from)
  File "/usr/src/app/trading/service.py", line 303, in get_history_candles
    return client.market_data.get_candles(figi=figi, from_=_from, to=to,
  File "/usr/local/lib/python3.10/site-packages/tinkoff/invest/_errors.py", line 28, in wrapper
    raise RequestError(
tinkoff.invest.exceptions.RequestError: (<StatusCode.UNAVAILABLE: (14, 'unavailable')>, 'upstream request timeout', None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/manage.py", line 22, in <module>
    main()
  File "/usr/src/app/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 414, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
  File "/usr/src/app/trading/management/commands/load_history.py", line 22, in handle
    candle_service.load_history(figi, _from=start_day, to=end_date)
  File "/usr/src/app/trading/service.py", line 292, in load_history
    raise RequestError(e.code, e.details, e.metadata)
tinkoff.invest.exceptions.RequestError: (<StatusCode.UNAVAILABLE: (14, 'unavailable')>, 'upstream request timeout', None)

[Bug] market_data.get_last_prices(): цена ОФЗ меньше в 10 раз

Что случилось?

Почему-то цена на ОФЗ показывается в 10 раз меньше. В документации упомянута лотность, но лоты ОФЗ по 1 штуке.

Воспроизведение

Для примера, ОФЗ 26207, figi BBG002PD3452

pprint(await client.get().instruments.bond_by(
    id_type=InstrumentIdType.INSTRUMENT_ID_TYPE_FIGI,
    id='BBG002PD3452',
))

pprint(await client.get().market_data.get_last_prices(
    figi=['BBG002PD3452']))

Выдаёт:

BondResponse(instrument=Bond(figi='BBG002PD3452',
                             ticker='SU26207RMFS9',
                             class_code='TQOB',
                             isin='RU000A0JS3W6',
                             lot=1,
                             currency='rub',
                             klong=Quotation(units=2, nano=0),
                             kshort=Quotation(units=2, nano=0),
                             dlong=Quotation(units=0, nano=300000000),
                             dshort=Quotation(units=0, nano=300000000),
                             dlong_min=Quotation(units=0, nano=163300000),
                             dshort_min=Quotation(units=0, nano=140200000),
                             short_enabled_flag=False,
                             name='ОФЗ 26207',
                             exchange='MOEX_PLUS',
                             coupon_quantity_per_year=2,
                             maturity_date=datetime.datetime(2027, 2, 3, 0, 0, tzinfo=datetime.timezone.utc),
                             nominal=MoneyValue(currency='rub',
                                                units=1000,
                                                nano=0),
                             state_reg_date=datetime.datetime(2012, 2, 14, 0, 0, tzinfo=datetime.timezone.utc),
                             placement_date=datetime.datetime(2012, 2, 22, 0, 0, tzinfo=datetime.timezone.utc),
                             placement_price=MoneyValue(currency='rub',
                                                        units=0,
                                                        nano=0),
                             aci_value=MoneyValue(currency='rub',
                                                  units=0,
                                                  nano=0),
                             country_of_risk='RU',
                             country_of_risk_name='Российская Федерация',
                             sector='government',
                             issue_kind='documentary',
                             issue_size=350000000,
                             issue_size_plan=150000000,
                             trading_status=<SecurityTradingStatus.SECURITY_TRADING_STATUS_CLOSING_AUCTION: 6>,
                             otc_flag=False,
                             buy_available_flag=True,
                             sell_available_flag=True,
                             floating_coupon_flag=False,
                             perpetual_flag=False,
                             amortization_flag=False,
                             min_price_increment=Quotation(units=0,
                                                           nano=1000000),
                             api_trade_available_flag=True,
                             uid='1c5d6a37-5790-46f4-b4cc-aff8ce533c4b',
                             real_exchange=<RealExchange.REAL_EXCHANGE_MOEX: 1>))
GetLastPricesResponse(last_prices=[LastPrice(figi='BBG002PD3452',
                                             price=Quotation(units=98,
                                                             nano=439000000),
                                             time=datetime.datetime(2022, 6, 24, 15, 37, 31, 486339, tzinfo=datetime.timezone.utc))])

Цена ОФЗ выходит 98.439 рублей. Настоящая цена одной облигации 984.39 рублей.

Tinkoff Invest Version

0.2.0-beta30

Python Version

3.10

OS

Linux

Логи

No response

[Bug] Проблема с функцией market_data.get_last_prices()

Что случилось?

Функция не всегда возвращает корректные данные при одинаковых вызовах. Для демонстрации проблемы я использовал простой циклический вызов, FIGI не важен. Эта же проблема воспроизводится через Kreya, данные проходят то корректные, то нет.

Воспроизведение

def test_func():
    for i in range(20):
        try:
            with Client(TOKEN) as client:
                last_price = client.market_data.get_last_prices(figi=['BBG000BH0FR6'])
        except:
            continue        
        print(last_price.last_prices[0].time)
    return

def main():
    test_func()

if __name__ == "__main__":
    main()

Tinkoff Invest Version

0.2.0-beta20

Python Version

3.8

OS

Windows

Логи

runfile('C:/Trading/Phyton/tinklib.py', wdir='C:/Trading/Phyton')
1970-01-01 00:00:00+00:00
1970-01-01 00:00:00+00:00
2022-04-08 20:00:00.917000+00:00
1970-01-01 00:00:00+00:00
1970-01-01 00:00:00+00:00
2022-04-08 20:00:00.917000+00:00
1970-01-01 00:00:00+00:00
1970-01-01 00:00:00+00:00
2022-04-08 20:00:00.917000+00:00
2022-04-08 20:00:00.917000+00:00
2022-04-08 20:00:00.917000+00:00
1970-01-01 00:00:00+00:00
1970-01-01 00:00:00+00:00
1970-01-01 00:00:00+00:00
2022-04-08 20:00:00.917000+00:00
2022-04-08 20:00:00.917000+00:00
2022-04-08 20:00:00.917000+00:00
1970-01-01 00:00:00+00:00
2022-04-08 20:00:00.917000+00:00
1970-01-01 00:00:00+00:00

Не указана причина ошибки - message

Предлагаю вывести в трейсинг ошибок поле message из header, которое описывает причину.
Без него догадаться очень сложно.
Привожу пример вызов post_order из sdk

grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
status = StatusCode.INVALID_ARGUMENT
details = "30019"
debug_error_string = "{"created":"@1643573459.685079000","description":"Error received from peer ipv4:91.194.227.80:443","file":"src/core/lib/surface/call.cc","file_line":1075,"grpc_message":"30019","grpc_status":3}"

И вывод из Kreya

image

[Bug] TypeError: can't compare offset-naive and offset-aware datetimes

Что случилось?

Ошибка выполнения

File "..\site-packages\tinkoff\invest\utils.py", line 27, in get_intervals
while local_from + interval_timedelta <= to:

TypeError: can't compare offset-naive and offset-aware datetimes

Воспроизведение

запустить файл из поставки https://github.com/Tinkoff/invest-python/blob/main/examples/all_candles.py

Tinkoff Invest Version

0.2.0-beta21

Python Version

3.9

OS

Windows

Логи

No response

Ошибка при выполнении запроса get_all_candles

При получении истории свечей возникает ошибка:
tinkoff.invest.exceptions.RequestError: (<StatusCode.INVALID_ARGUMENT: (3, 'invalid argument')>, '30012', Metadata(tracking_id='849485810b568de052ac312ec9de2379', ratelimit_limit='200, 200;w=60', ratelimit_remaining=183, ratelimit_reset=15, message="'to' can't be less then 'from'"))

Выполняемый код:

import os
from datetime import datetime, timedelta
from tinkoff.invest import CandleInterval, Client

token = os.getenv('TIN_TOKEN', '')


def main():
    with Client(token) as client:
        for candle in client.get_all_candles(
            figi="BBG000BBJQV0",
            from_=datetime.utcnow() - timedelta(days=3),
            interval=CandleInterval.CANDLE_INTERVAL_1_MIN,
        ):
            print(candle)

if __name__ == "__main__":
    main()

Улучшаем пакет, избавляясь от ненужного

Как я вижу, tinkoff/invest/token.py в коде нигде не используется, почему бы его не удалить. Пакет всё ещё 0.Х.Х, да и единственные релизы в pip - все пререлизы.

Если в ранних версиях это был основной метод, то нет проблем просто использовать os.environ["INVEST_TOKEN"] в качестве токена для клиента.

[Bug] MarketDataStream UNAVAILABLE GOAWAY received

Что случилось?

Каждый день, примерно в период с 15:30 до 17:00, 1-2 раза получаю сообщение указанное в логах. После этого поток прерывается. После повторной подписки все работает штатно.

Воспроизведение

Использую async_stream_client.py из примеров, добавив внутрь:
subscribe_order_book_request=SubscribeOrderBookRequest(
subscription_action=SubscriptionAction.SUBSCRIPTION_ACTION_SUBSCRIBE,
instruments=......

Tinkoff Invest Version

0.2.0-beta19

Python Version

3.9

OS

Windows

Логи

04:42:59: log_error      : None MarketDataStream UNAVAILABLE GOAWAY received
(<StatusCode.UNAVAILABLE: (14, 'unavailable')>, 'GOAWAY received', Metadata(tracking_id=None, ratelimit_limit='200, 200;w=60', ratelimit_remaining=199, ratelimit_reset=29, message=None))

[Feature] Календарь частичных погашений бондов с амортизацией

Описание

Сейчас ни в приложении, ни в апи, нельзя получить наряду с календарём купонов календарь погашений.

Желаемое решение

Хочется примерно такую табличку:
https://bonds.finam.ru/issue/details01E4000002/default.asp

Например в вызове GetBondCoupons добавить поле погашение

Coupon(
figi='BBG00F5FK1W7',
coupon_date=datetime.datetime(2022, 10, 30, 0, 0, tzinfo=datetime.timezone.utc),
coupon_number=24, fix_date=datetime.datetime(2022, 10, 28, 0, 0, tzinfo=datetime.timezone.utc),
...
nominal_repayment=MoneyValue(currency='rub', units=300, nano=0),
)

Дополнительно

No response

Не писать в кэш свечи с is_complete = false

Что случилось?

Если мы запрашиваем свечи за еще идущий интервал, то свечи могут прийти с is_complete = false и в дальнейшем измениться. Предлагаю не сохранять в кэш свечи с is_complete = false.

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta30

Python Version

3.10

OS

Windows

Логи

No response

Как получить данные по базовому активу для фьючерса?

Что случилось?

Добрый день!
В текущей версии АПИ не понятна связка фьючерсов с базовым инструментом.
В параметрах фьючерса указан тикер базового актива, но чтобы теперь получить по нему данные, одного тикера недостаточно - для получения figi и, соответственно, в дальнейшем данных по базовому активу, требуется еще class_code для базового инструмента. Подскажите, где его взять на фьючерсе?

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta27

Python Version

3.8

OS

Linux

Логи

No response

[Bug] await 2 раза на одну корутину

Что случилось?

Убрать await в строчке

response_coro = await self.stub.GetFavorites(

instruments.get_favorites() выдает ошибку TypeError: object GetFavoritesResponse can't be used in 'await' expression

Корутина ожидается дважды:

@handle_aio_request_error("GetFavorites")
    async def get_favorites(
        self,
    ) -> GetFavoritesResponse:
        request = GetFavoritesRequest()
        response_coro = await self.stub.GetFavorites(
            request=_grpc_helpers.dataclass_to_protobuff(
                request, instruments_pb2.GetFavoritesRequest()
            ),
            metadata=self.metadata,
        )
        response = await response_coro
        log_request(await get_tracking_id_from_coro(response_coro), "GetFavorites")
        return _grpc_helpers.protobuf_to_dataclass(response, GetFavoritesResponse)

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta30

Python Version

3.10

OS

Windows

Логи

No response

Unresolved reference

1)В терминале ввел pip install tinkoff-investments
2)В .py файле ввел пример
3) Выдает ошибки Unresolved reference 'tinkoff','Client'
Я только начал, а у меня уже ничего не получается

Некорректная работа метода get_all_candles()

Что случилось?

Метод get_all_candles() некорректно отрабатывает последнюю свечу. Если запрашиваешь дневной интервал, то выдается одна лишняя свеча, дата которой больше параметра 'to'. Например при запросе дневных свечей Газпрома при параметрах 'from_' = datetime(2022, 4, 1, 0, 0, tzinfo=utc), 'to' = datetime(2022, 4, 5, 0, 0, tzinfo=utc) возвращается свеча, датированная datetime(2022, 4, 5, 7, 0, tzinfo=utc).
На меньших интервалах такого не наблюдается.
Также не наблюдается при некоторых других бумагах, например Apple отрабатывает корректно на всех интервалах

Воспроизведение

async def get_history(from_, to, interval, figi):
    async with AsyncClientV1(TOKEN) as client:
        response = await client.get_market_candles(from_=from_, to=to, interval=interval, figi=figi)
        return response

if __name__ == "__main__":
    figi = 'BBG004730RP0'
    interval = CandleInterval.CANDLE_INTERVAL_DAY
    start = datetime(2022, 4, 1, 0, 0, tzinfo=utc)
    end = datetime(2022, 4, 5, 0, 0, tzinfo=utc)
    response = asyncio.run(get_historyV2(from_=start, to=end, interval=interval_v2, figi=figi))
    print(response_2[-1].time)
    
> 2022-04-05 07:00:00+00:00

Tinkoff Invest Version

0.2.0-beta27

Python Version

3.9

OS

Mac OS

Логи

No response

get_portfolio

Что случилось?

issue
Добрый день!

Подскажите пожалуйста почему не работает метод "get_portfolio" сервиса "operation"?
Я передаю в метод один аргумент "account_id".
А ошибка говорит, что было передано 2 позиционных аргумента.
Если в метод вообще ничего не передать, то будет ошибка, требующая обязательного аргумента "account_id".
Отмечу, что аналогичный пример с "get_accounts" работает как должен.
То есть проблема именно в методе и его использовании.

Воспроизведение

`import os
from dotenv import load_dotenv
import tinkoff.invest as ti

load_dotenv()

token = os.getenv('token')
account_id = os.getenv('BROKER_ID')
client = ti.Client(token)

with ti.Client(token) as client:
print(client.operations.get_portfolio(account_id))`

Tinkoff Invest Version

0.2.0-beta27

Python Version

3.8

OS

Windows

Логи

No response

проблема с подключением

Добрый день.

Вопрос очень примитивный, но буду признателен за совет.

в локальном jupyter notebooks выполнил установку
!pip install tinkoff-investments

импортировал в локальную переменную токен

import os
os.environ["INVEST_TOKEN"] =#указал здесь свой токен. пробовал токен песочницы и боевой

Пытаюсь выполнить пример client.py

но получаю
40982fba45e663c72c049baad9b64aaf GetAccounts UNAUTHENTICATED

RequestError: (<StatusCode.UNAUTHENTICATED: (16, 'unauthenticated')>, '', Metadata(tracking_id='40982fba45e663c72c049baad9b64aaf', ratelimit_limit='100, 100;w=60', ratelimit_remaining=98, ratelimit_reset=30, message='Authentication failed'))

Видимо мне нужно выполнить аутентификацию до запуска примеров. Подскажите, пожалуйста, как это сделать? Или где можно почитать про это?

Спасибо.

[Bug] Ошибка при подписки на свечи, разница между версиями beta28 и beta29

Что случилось?

При подписке на свечи через Client возникает ошибка.
Я понимаю что это бетта версии апи, но думаю должна быть обратная совместимость. либо какие-то дефолтные значения для таких параметров. Либо обновлять примеры кода.

Воспроизведение

Отправить запрос без waiting_close,

yield MarketDataRequest(
subscribe_candles_request=SubscribeCandlesRequest(
subscription_action=SubscriptionAction.SUBSCRIPTION_ACTION_SUBSCRIBE,
instruments=instruments_subscribe,
)
)

Tinkoff Invest Version

0.2.0-beta29

Python Version

3.10

OS

Linux

Логи

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/grpc/aio/_call.py", line 406, in _consume_request_iterator
    async for request in request_iterator:
  File "/usr/local/lib/python3.10/site-packages/tinkoff/invest/async_services.py", line 734, in _convert_market_data_stream_request
    yield _grpc_helpers.dataclass_to_protobuff(
  File "/usr/local/lib/python3.10/site-packages/tinkoff/invest/_grpc_helpers.py", line 314, in dataclass_to_protobuff
    dataclass_to_protobuff(field_value, pb_value)
  File "/usr/local/lib/python3.10/site-packages/tinkoff/invest/_grpc_helpers.py", line 303, in dataclass_to_protobuff
    setattr(protobuff_obj, field_name, field_value)
TypeError: <object object at 0x7fe0a4904ae0> has type object, but expected one of: int, bool

Генератор grpc клиента

Описание

На данный момент для удобства все объекты представлены как dataclass-ы. И происходит конвертация в типы от protobuf. Модельки приходится поддерживать руками. Чтобы избавиться от рутины, предлагается написать свой генератор клиента.
Есть вариант использовать proto-plus-python. Но все равно придется писать свой генератор.

Вопросы

  1. Почему не подходит betterproto? Из коробки поддерживает grpclib и работает только в асинхронном варианте. Непонятно как работать с метадатой
  2. Чем плох стандартный генератор? Стандартный генератор не пайтоник. Сложно использовать. Нужна абстракция для упрощения использования

пожалуйста сбилдите под arm!Mac m1

ImportError: dlopen(/Users/muratsigalugov/Desktop/tinkoff-invest-bot/venv/lib/python3.10/site-packages/grpc/_cython/cygrpc.cpython-310-darwin.so, 0x0002): tried: '/Users/muratsigalugov/Desktop/tinkoff-invest-bot/venv/lib/python3.10/site-packages/grpc/_cython/cygrpc.cpython-310-darwin.so' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), '/usr/lib/cygrpc.cpython-310-darwin.so' (no such file)

Неверный ответ в методе get_last_prices

Делаю вызов через KREYA по figi = RU000A101GB7. Получаю ответ:
{ "lastPrices": [ { "figi": "RU000A101GB7", "price": { "units": "99", "nano": 940000000 }, "time": "2022-02-16T14:03:14.583164Z" } ] }

Делаю аналогичный вызов в python:
client.market_data.get_last_prices(figi=bond_item.figi)

В ответ получаю очень странный массив last_prices, значение figi каждого элемента - это один символ из реального figi, а цены везде нулевые. Пример скрина из отладки:
изображение

Прошу подсказать, это я что-то не так делаю или реально ошибка?

Господа! Как получить figi коды по средствам имени тикера? [Issue]

Что случилось?

Казалось бы, задача простая, но перерыв с десяток методов не нашел решения. Даже openfigi api пробовал, не помогло. В общем, как можно замапить тикер и получить figi по средствам invest-python?

Воспроизведение

Не работает:

from openapi_client import openapi

client = openapi.api_client(TOKEN)
instr = client.market.market_search_by_ticker_get('AAPL' ) 
print(instr)
import requests

response = requests.post(url='https://api.openfigi.com/v3/search/',
                        headers={'Content-Type': 'text/json'},
                        json={
                            'query': 'AAPL',
                            'exchCode': 'GM'
                        })
                        
APPLE_FIGI = response.json()['data'][0]['figi']

async def main():
    global APPLE_FIGI
    async with ti.Streaming(TOKEN) as streaming:
        await streaming.candle.subscribe(APPLE_FIGI, ti.CandleResolution.min5) 
        async for event in streaming:
            print(event)

from tinkoff.investments import TinkoffInvestmentsRESTClient

async def main():
    client = TinkoffInvestmentsRESTClient(token=TOKEN)
    instruments = await client.market.instruments.search('AAPL')
    for instrument in instruments:
        print(instrument.figi)

asyncio.run(main())

Tinkoff Invest Version

0.2.0-beta19

Python Version

3.9

OS

Windows

Логи

Первый метод выдает 403, второй метод выдает что такой Figi не найден. 

Третий метод выдает длинный лог, суть которого как я понял в том, что в запрос передается некорректный mime type

Traceback (most recent call last):
  File "C:\Users\kgera\Desktop\tin api\main.py", line 65, in <module>
    asyncio.run(main())
  File "C:\Users\kgera\anaconda3\lib\asyncio\runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "C:\Users\kgera\anaconda3\lib\asyncio\base_events.py", line 642, in run_until_complete
    return future.result()
  File "C:\Users\kgera\Desktop\tin api\main.py", line 61, in main
    instruments = await client.market.instruments.search('AAPL')
  File "C:\Users\kgera\anaconda3\lib\site-packages\tinkoff\investments\api\market.py", line 26, in search
    return await self.__get_instruments(
  File "C:\Users\kgera\anaconda3\lib\site-packages\tinkoff\investments\api\market.py", line 59, in __get_instruments
    payload = await self._request(
  File "C:\Users\kgera\anaconda3\lib\site-packages\tinkoff\investments\api\base.py", line 25, in _request
    data = await self._client._request(method, path, rate_limit, **kwargs)
  File "C:\Users\kgera\anaconda3\lib\site-packages\tinkoff\investments\client\rest.py", line 63, in _request
    return await response.json()
  File "C:\Users\kgera\anaconda3\lib\site-packages\aiohttp\client_reqrep.py", line 1103, in json
    raise ContentTypeError(
aiohttp.client_exceptions.ContentTypeError: 0, message='Attempt to decode JSON with unexpected mimetype: ', url=URL('https://api-invest.tinkoff.ru/openapi/market/search/by-ticker?ticker=AAPL')
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x000001A604162C10>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x000001A6041B47C0>, 34763.546)]']
connector: <aiohttp.connector.TCPConnector object at 0x000001A604162460>
Fatal error on SSL transport
protocol: <asyncio.sslproto.SSLProtocol object at 0x000001A604162BB0>
transport: <_ProactorSocketTransport fd=664 read=<_OverlappedFuture cancelled>>
Traceback (most recent call last):
  File "C:\Users\kgera\anaconda3\lib\asyncio\sslproto.py", line 684, in _process_write_backlog
    self._transport.write(chunk)
  File "C:\Users\kgera\anaconda3\lib\asyncio\proactor_events.py", line 359, in write
    self._loop_writing(data=bytes(data))
  File "C:\Users\kgera\anaconda3\lib\asyncio\proactor_events.py", line 395, in _loop_writing
    self._write_fut = self._loop._proactor.send(self._sock, data)
AttributeError: 'NoneType' object has no attribute 'send'
Exception ignored in: <function _SSLProtocolTransport.__del__ at 0x000001A602FE65E0>
Traceback (most recent call last):
  File "C:\Users\kgera\anaconda3\lib\asyncio\sslproto.py", line 321, in __del__
  File "C:\Users\kgera\anaconda3\lib\asyncio\sslproto.py", line 316, in close
  File "C:\Users\kgera\anaconda3\lib\asyncio\sslproto.py", line 593, in _start_shutdown
  File "C:\Users\kgera\anaconda3\lib\asyncio\sslproto.py", line 598, in _write_appdata
  File "C:\Users\kgera\anaconda3\lib\asyncio\sslproto.py", line 706, in _process_write_backlog
  File "C:\Users\kgera\anaconda3\lib\asyncio\sslproto.py", line 720, in _fatal_error
  File "C:\Users\kgera\anaconda3\lib\asyncio\proactor_events.py", line 151, in _force_close
  File "C:\Users\kgera\anaconda3\lib\asyncio\base_events.py", line 746, in call_soon
  File "C:\Users\kgera\anaconda3\lib\asyncio\base_events.py", line 510, in _check_closed
RuntimeError: Event loop is closed

[Bug] Bonds aci_value is empty

Что случилось?

При вызове функций бондов возвращает всегда НКД=0 (bond.aci_value)

Воспроизведение

#!/usr/bin/env python
import tinkoff.invest as ti

token = 'your_token'
with ti.Client(token) as client:
    # all bonds
    bonds = client.instruments.bonds(
        instrument_status=ti.InstrumentStatus.INSTRUMENT_STATUS_BASE)

    # single bond data for checking
    b = client.instruments.bond_by(
        id_type=ti.InstrumentIdType.INSTRUMENT_ID_TYPE_FIGI, id='BBG012R5Y2V7')

    # results
    print('\t', b.instrument.name, b.instrument.aci_value)
    print('\t', bonds.instruments[0].name, bonds.instruments[0].aci_value)

Tinkoff Invest Version

0.2.0-beta22

Python Version

3.10

OS

Linux

Логи

No response

[Bug] trades_stream() -> AttributeError: accounts

Что случилось?

После обновления с 19 на 23 бетту возникли проблемы с client.orders_stream.trades_stream()
Понижение версии восстанавливает работу кода.

Воспроизведение

async with AsyncClient(TOKEN) as client:
        async for tradesdata in client.orders_stream.trades_stream():
            await queue.put(tradesdata)
            await asyncio.sleep(0.5)

Tinkoff Invest Version

0.2.0-beta23

Python Version

3.9

OS

Windows

Логи

11:18:09: default_exception_handler: Task exception was never retrieved
future: <Task finished name='Task-2' coro=<TradesData() done, defined at c:\Users\LLLL\Dropbox\Docs\Coding\kkkk\tinkof_new_sdk_stream_v11.py:106> exception=AttributeError('accounts')>
Traceback (most recent call last):
  File "c:\Users\LLLL\Dropbox\Docs\Coding\kkkk\tinkof_new_sdk_stream_v11.py", line 109, in TradesData
    async for tradesdata in client.orders_stream.trades_stream():
  File "c:\Users\LLLL\Dropbox\Docs\Coding\kkkk\.venv\lib\site-packages\tinkoff\invest\_errors.py", line 91, in wrapper
    async for result in func(*args, **kwargs):
  File "c:\Users\LLLL\Dropbox\Docs\Coding\kkkk\.venv\lib\site-packages\tinkoff\invest\async_services.py", line 887, in trades_stream
    request=_grpc_helpers.dataclass_to_protobuff(
  File "c:\Users\LLLL\Dropbox\Docs\Coding\kkkk\.venv\lib\site-packages\tinkoff\invest\_grpc_helpers.py", line 324, in dataclass_to_protobuff
    pb_value = getattr(protobuff_obj, field_name)
AttributeError: accounts

[Issue] Господа! client.get_all_candles возвращает int. Причина?

Что случилось?

Хотелось бы возвращать значения в float. Это возможно?

# tinkoff.invest.schemas 

@dataclass(eq=False, repr=True)
class Quotation(_grpc_helpers.Message):
    units: int = _grpc_helpers.int64_field(1)
    nano: int = _grpc_helpers.int32_field(2)

Воспроизведение


def main():
    global TOKEN 
    with Client(TOKEN) as client:
        for candle in client.get_all_candles(
            figi="BBG004730N88", #BBG000B9XRY4
            from_=datetime.utcnow() - timedelta(days=15),
            interval=CandleInterval.CANDLE_INTERVAL_15_MIN,
        ):
            print(candle.high.units)
            print(candle)
            break
             

    return 0

if __name__ == "__main__":
    main()

Tinkoff Invest Version

0.2.0-beta19

Python Version

3.10

OS

Windows

Логи

No response

Прекращают поступать котировки после промежуточного клиринга

Что случилось?

После клиринга в 14:00 по Москве перестают приходить котировки на фьючерсы ФОРТС (проверял на figi="FUTRTS062200"). При этом соединение не разрывается и никаких дополнительных уведомлений MarketDataResponse не приходит.

Добавил последнюю запись в логах, после которой новых MarketDataResponse больше нет.

Подписываюсь аналогично примеру из easy_async_stream_client.py.

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta26

Python Version

3.9

OS

Linux

Логи

2022-05-11 13:59:00,838 WARNING tinkoff_api Received non-candle market data: MarketDataResponse(subscribe_candles_response=None, subscribe_order_book_response=None, subscribe_trades_response=None, subscribe_info_response=None, candle=None, trade=None, orderbook=None, trading_status=TradingStatus(figi='FUTRTS062200', trading_status=<SecurityTradingStatus.SECURITY_TRADING_STATUS_BREAK_IN_TRADING: 4>, time=datetime.datetime(2022, 5, 11, 11, 0, 4, 521000, tzinfo=datetime.timezone.utc), limit_order_available_flag=False, market_order_available_flag=False), ping=None, subscribe_last_price_response=None, last_price=None)

Добавить кэш всех инструментов, инициализируемый при старте приложения

Описание

Есть проблемы:

  • зная только figi инструмента, мы не можем без дополнительных вызовов api понять, что это за инструмент
  • большое количество клиентов, реализуют свои решения без кеша.

Желаемое решение

  1. Добавить в конфиг параметр - "работать с кэшем в сервисе инструментов" + время жизни этого кэша
  2. При старте приложения при включенном параметре загружать все результаты вызовов Shares(), Bonds(), Futures(), ETFs(), Currrencies() в кэш со временем жизни, указываемом в конфиге.

При последующем запросе любого метода Get, GetBy и FindInstrument сервиса инструментов отдавать результаты из кэша.

Дополнительно

No response

SubscribeOrderBookRequest выдает ошибку

Что случилось?

Пытаюсь подключиться строимом к стакану.

def request_iterator():
        yield MarketDataRequest(
            subscribe_order_book_request=SubscribeOrderBookRequest(
                subscription_action=SubscriptionAction.SUBSCRIPTION_ACTION_SUBSCRIBE,
                instruments=[
                    OrderBookInstrument(
                        figi="BBG000BH5LT6",
                        depth=10,
                    )
                ],
            )
        )

Получаю:
None MarketDataStream UNKNOWN Exception iterating requests!

Воспроизведение

No response

Tinkoff Invest Version

0.2.0-beta19

Python Version

3.9

OS

Linux

Логи

Traceback (most recent call last):
  File "/home/cust/.local/lib/python3.8/site-packages/tinkoff/invest/_errors.py", line 43, in wrapper
    yield from func(*args, **kwargs)
  File "/home/cust/.local/lib/python3.8/site-packages/tinkoff/invest/services.py", line 600, in market_data_stream
    for response in self.stub.MarketDataStream(
  File "/home/cust/.local/lib/python3.8/site-packages/grpc/_channel.py", line 426, in __next__
    return self._next()
  File "/home/cust/.local/lib/python3.8/site-packages/grpc/_channel.py", line 809, in _next
    raise self
grpc._channel._MultiThreadedRendezvous: <_MultiThreadedRendezvous of RPC that terminated with:
	status = StatusCode.UNKNOWN
	details = "Exception iterating requests!"
	debug_error_string = "None"
>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "robot_1.py", line 220, in <module>
    orderbook(figi)
  File "robot_1.py", line 121, in orderbook
    for marketdata in client.market_data_stream.market_data_stream(
  File "/home/cust/.local/lib/python3.8/site-packages/tinkoff/invest/_errors.py", line 53, in wrapper
    raise RequestError(
tinkoff.invest.exceptions.RequestError: (<StatusCode.UNKNOWN: (2, 'unknown')>, 'Exception iterating requests!', None)

[Bug]

Что случилось?

Ошибка при подписке на свечи

Воспроизведение

import asyncio
import os

from tinkoff.invest import (
AsyncClient,
CandleInstrument,
InfoInstrument,
SubscriptionInterval,
)
from tinkoff.invest.async_services import AsyncMarketDataStreamManager

async def main():
async with AsyncClient(TOKEN) as client:
market_data_stream: AsyncMarketDataStreamManager = (
client.create_market_data_stream()
)
market_data_stream.candles.subscribe(
[
CandleInstrument(
figi="BBG004730N88",
interval=SubscriptionInterval.SUBSCRIPTION_INTERVAL_ONE_MINUTE,
)
]
)
async for marketdata in market_data_stream:
print(marketdata)
market_data_stream.info.subscribe([InfoInstrument(figi="BBG004730N88")])

if name == "main":
asyncio.run(main())

Tinkoff Invest Version

0.2.0-beta29

Python Version

3.10

OS

Linux

Логи

Traceback (most recent call last):
  File "test.py", line 49, in <module>
    asyncio.run(main())
  File "/usr/local/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/lib/python3.10/asyncio/base_events.py", line 641, in run_until_complete
    return future.result()
  File "test.py", line 43, in main
    async for marketdata in market_data_stream:
  File "venv/lib/python3.10/site-packages/tinkoff/invest/_errors.py", line 91, in wrapper
    async for result in func(*args, **kwargs):
  File "venv/lib/python3.10/site-packages/tinkoff/invest/async_services.py", line 747, in market_data_stream
    yield _grpc_helpers.protobuf_to_dataclass(response, MarketDataResponse)
  File "venv/lib/python3.10/site-packages/tinkoff/invest/_grpc_helpers.py", line 269, in protobuf_to_dataclass
    field_value = protobuf_to_dataclass(pb_value, field_type)
  File "venv/lib/python3.10/site-packages/tinkoff/invest/_grpc_helpers.py", line 278, in protobuf_to_dataclass
    field_value = [
  File "venv/lib/python3.10/site-packages/tinkoff/invest/_grpc_helpers.py", line 279, in <listcomp>
    protobuf_to_dataclass(item, first_arg) for item in pb_value
  File "venv/lib/python3.10/site-packages/tinkoff/invest/_grpc_helpers.py", line 271, in protobuf_to_dataclass
    field_value = field_type(pb_value)
  File "/usr/local/lib/python3.10/enum.py", line 385, in __call__
    return cls.__new__(cls, value)
  File "/usr/local/lib/python3.10/enum.py", line 710, in __new__
    raise ve_exc
ValueError: 8 is not a valid SubscriptionStatus

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.