На информационном ресурсе применяются рекомендательные технологии (информационные технологии предоставления информации на основе сбора, систематизации и анализа сведений, относящихся к предпочтениям пользователей сети "Интернет", находящихся на территории Российской Федерации)

artydev & Co

1 подписчик

Обмен заблокированных активов СБП биржа

img

Мы разработали сервис для удобного просмотра заблокированных в СПБ бирже бумаг используя интеграцию с Tinkoff Invest API.
Собираем данных о замороженных позициях, сравниваем их с доступным к обмену списку от организатора торгов ООО “Инвестиционная Палата” и отображаем финальную сумму конвертации.

Сервис для проверки активов в брокере Тинькофф: https://844.

artydev.ru/

Введение

Важно иметь в виду, что иностранные акции, которые были заблокированы после наложенных на СПБ Биржу в 2023 году санкций, не могут участвовать в продаже по указу № 844 — даже если они включены в список на сайте организатора торгов.

Вот как устанавливается цена продажи заблокированных активов:

  • Организатор торгов установил минимальную цену продажи для каждого актива — это цена актива на иностранных биржах 22 марта 2024 года, но рассчитанная в рублях по курсу ЦБ РФ. Посмотреть минимальные цены активов на сайте организатора торгов.
  • С 3 июня по 5 июля организатор торгов будет собирать от нерезидентов заявки на покупку заблокированных активов.
  • Конечная цена продажи будет определена на основе спроса и предложения.

Если в момент продажи активов будет повышенный спрос от нерезидентов, активы могут быть проданы даже выше установленной минимальной цены. А если спроса от нерезидентов не окажется, активы просто не будут проданы — даже с дисконтом.

Как получить токен

  1. Перейдите в настройки профиля Тинькофф Инвестиции по ссылке: https://www.tinkoff.ru/invest/settings/
  2. Авторизуйтесь в системе, если это требуется.
  3. Выпустите токен TINKOFF INVEST API для биржи. Возможно, система попросит вас авторизоваться еще раз. Не беспокойтесь, это необходимо для подключения робота к торговой платформе.
  4. Скопируйте токен и сохраните его. Токен отображается только один раз, просмотреть его позже не получится. Тем не менее вы можете выпускать неограниченное количество токенов.
img

Разработка

Основная обработка токена состоит из 3 функций:

  • Сбор данных о заблокированных позициях
  • Трансформация в pandas DataFrame
  • Расчет итоговых сумм
def get_user_portfolio(token: str) -> list:     info = []     with Client(token) as client:         accounts = client.users.get_accounts()         for account in accounts.accounts:             logger.info(f"Check account: {account.name}")             portfolio = client.operations.get_portfolio(account_id=account.id)             for pos in portfolio.positions:                 if pos.blocked is True:                     price = quotation_to_decimal(pos.current_price)                     data = {                         "figi": pos.figi,                         "quantity": pos.quantity_lots.units,                         "price": price,                         "total": price * pos.quantity_lots.units,                         "currency": pos.current_price.currency.upper(),                         "acc": account.name,                     }                     logger.info(f"Blocked position: {data}")                     info.append(data)     return info 
def convert_portfolio_to_df(data: list) -> pd.DataFrame:     df = pd.DataFrame(data)     df["total"] = df["total"].astype(float)     df["quantity"] = df["quantity"].astype(int)     df["price"] = df["price"].astype(float)     df["zfigi"] = df["figi"].str[4:]     cb_data["zfigi"] = cb_data["figi"].str[4:]     merge_df = df.merge(cb_data, how="left", on="zfigi", suffixes=("", "_cb"))     columns = ["figi", "quantity", "name", "price", "total", "currency", "acc", "isin", "_type", "price_cb"]     merge_df = merge_df[columns]     merge_df["total_cb_price"] = merge_df["quantity"] * merge_df["price_cb"]     merge_df.loc[merge_df['isin'].isnull(), 'is_exchange'] = 'N'     merge_df.loc[merge_df['isin'].notnull(), 'is_exchange'] = 'Y'     merge_df.loc[(df['quantity'] > 0) & (merge_df['total'] == 0), 'is_used'] = 'Y'     merge_df.loc[(df['quantity'] > 0) & (merge_df['total'] > 0), 'is_used'] = 'N'     return merge_df 
def convert_df_to_dict(data: pd.DataFrame) -> dict:     user_data = {         "rows": data.to_dict("records"),         "total_currency": data[data.is_exchange == "Y"].total.sum(),         "total_rub": data[data.is_exchange == "Y"].total_cb_price.sum(),         "total_rub_used": data[data.is_used == "Y"].total_cb_price.sum(),         "status": "success"     }     logger.info(f"Prepare to final response: {user_data}")     return user_data 

Эндпоинт в API сервисе на получение данных

@app.post('/api/v1/exchange_info', status_code=201, response_model=UserResponse) async def get_spb_info(data: UserRequest):     request_data = data.model_dump()     token = request_data["token"]     try:         data = get_user_portfolio(token)         df = convert_portfolio_to_df(data)         response_data = convert_df_to_dict(df)         return response_data     except UnauthenticatedError:         logger.error(f"Error with token: {token}. {traceback.format_exc()}")         return {             "rows": [],             "total_currency": 0.0,             "total_rub": 0.0,             "status": "failed",         } 

Большое спасибо всем за внимание! Если вам интересны подобные рассуждения - подписывайтесь на мой канал  artydev & Co.

Ссылка на первоисточник
Рекомендуем
Популярное
наверх