mirror of
https://github.com/ada-dmitry/dca_bot_tinv.git
synced 2026-09-24 08:40:19 +00:00
369 lines
16 KiB
Markdown
369 lines
16 KiB
Markdown
# DCA Bot для Tinkoff Invest
|
||
|
||
Автоматический бот для реализации стратегии Dollar Cost Averaging (DCA) через API Tinkoff Invest. Поддерживает работу с акциями, ETF, облигациями и валютами на реальном брокерском счете.
|
||
|
||
## Что это такое?
|
||
|
||
DCA (Dollar Cost Averaging) — это инвестиционная стратегия, при которой вы регулярно покупаете финансовые инструменты на фиксированную сумму, независимо от их текущей цены. Это помогает снизить влияние волатильности рынка на общую стоимость инвестиций.
|
||
|
||
## Основные возможности
|
||
|
||
- ✅ Автоматическое распределение бюджета по заданным весам между инструментами
|
||
- ✅ Поддержка акций, ETF, облигаций и валют
|
||
- ✅ Корректный расчет стоимости облигаций (номинал + НКД)
|
||
- ✅ Проверка торгового статуса инструментов
|
||
- ✅ Защита от ошибок недостатка средств с автоматическим уменьшением размера ордера
|
||
- ✅ Детальное логирование всех операций в CSV
|
||
- ✅ Режим симуляции (dry-run) для тестирования
|
||
- ✅ Буферы для комиссий и проскальзывания
|
||
- ✅ Работа только с реальными счетами (без песочницы)
|
||
|
||
## Требования
|
||
|
||
- Python 3.8+
|
||
- Реальный брокерский счет в Tinkoff
|
||
- API токен с правами на торговлю
|
||
|
||
## Установка
|
||
|
||
1. Клонируйте репозиторий:
|
||
```bash
|
||
git clone <url>
|
||
cd dca_bot
|
||
```
|
||
|
||
2. Установите зависимости:
|
||
|
||
> Рекомендуется использование виртуального окружения Python.
|
||
```bash
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
3. Скопируйте файл с переменными окружения:
|
||
```bash
|
||
cp .env.example .env
|
||
```
|
||
|
||
4. Заполните `.env` файл:
|
||
```env
|
||
TINKOFF_TOKEN="ваш_токен"
|
||
TINKOFF_ACCOUNT_ID="ваш_id_счета" # опционально
|
||
```
|
||
|
||
## Настройка
|
||
|
||
Создайте файл конфигурации `config.yml` со списком инструментов и их весами:
|
||
|
||
```yaml
|
||
assets:
|
||
- figi: "BBG004730N88" # Сбербанк
|
||
weight: 0.3 # 30%
|
||
- figi: "BBG00475KKY8" # Яндекс
|
||
weight: 0.2 # 20%
|
||
- figi: "BBG333333333" # ОФЗ
|
||
weight: 0.3 # 30%
|
||
- figi: "BBG444444444" # Доллар США
|
||
weight: 0.2 # 20%
|
||
```
|
||
|
||
**Важно:** Сумма весов должна равняться 1.0!
|
||
|
||
## Использование
|
||
|
||
### Основная команда
|
||
|
||
```bash
|
||
python main.py --config config.yml --rub-budget 10000
|
||
```
|
||
|
||
### Режим симуляции (тестирование)
|
||
|
||
```bash
|
||
python main.py --config config.yml --rub-budget 10000 --dry-run
|
||
```
|
||
|
||
### Расписание и ежедневный запуск
|
||
|
||
Бот теперь предполагает ежедневный запуск в фиксированное время (через cron/Systemd и т.п.) и сам решает, исполнять ли сделки сегодня.
|
||
|
||
Правила:
|
||
- В конфиге задаёте портфель, а день месяца указываете ключом `--day-of-month` (по умолчанию 5).
|
||
- Если запланированный день выпадает на выходной, а флаг `--allow-weekend` не передан — сделки автоматически переносятся на ближайший понедельник.
|
||
- Во все остальные дни бот просто завершает работу и пишет в лог статус `SKIPPED_NOT_SCHEDULED_TODAY(expected=YYYY-MM-DD)`.
|
||
|
||
Пример ежедневного cron на 10:00:
|
||
|
||
```bash
|
||
0 10 * * * cd /path/to/dca_bot && python main.py --config config.yml --rub-budget 10000 --day-of-month 5
|
||
```
|
||
|
||
Чтобы разрешить сделки в выходные именно в запланированный день:
|
||
|
||
```bash
|
||
0 10 * * * cd /path/to/dca_bot && python main.py --config config.yml --rub-budget 10000 --day-of-month 5 --allow-weekend
|
||
```
|
||
|
||
### Дополнительные параметры
|
||
|
||
```bash
|
||
python main.py \
|
||
--config config.yml \
|
||
--rub-budget 10000 \
|
||
--dry-run \
|
||
--fee-buf-bps 300 \
|
||
--safe-rub-pct 0.97 \
|
||
--wait-tradable-sec 60 \
|
||
--poll-sec 10 \
|
||
--allow-weekend
|
||
```
|
||
|
||
**Параметры:**
|
||
- `--config` — путь к YAML файлу конфигурации (обязательно)
|
||
- `--rub-budget` — общий бюджет в рублях для данного запуска (обязательно)
|
||
- `--dry-run` — режим симуляции, реальные ордера не размещаются
|
||
- `--fee-buf-bps` — буфер для комиссий в базисных пунктах (по умолчанию 300 = 3%)
|
||
- `--safe-rub-pct` — использовать только N% от доступных средств (по умолчанию 0.97 = 97%)
|
||
- `--wait-tradable-sec` — ждать до N секунд пока инструмент станет торгуемым (по умолчанию 0)
|
||
- `--poll-sec` — интервал проверки торгового статуса в секундах (по умолчанию 10)
|
||
- `--allow-weekend` — разрешить размещать ордера в субботу/воскресенье. По умолчанию при запуске в выходные бот фиксирует отложенные сделки в CSV со статусом `DEFERRED_TO_MONDAY(<дата>)` и завершает работу без размещения ордеров.
|
||
- `--day-of-month` — день месяца (1..28), в который бот должен исполнять сделки. Если выпадает на выходной и не указан `--allow-weekend`, сделки переносятся на ближайший понедельник. В остальные дни бот завершает работу со статусом `SKIPPED_NOT_SCHEDULED_TODAY`.
|
||
|
||
## Вспомогательные инструменты
|
||
|
||
В папке `tools/` находятся полезные утилиты для работы с API Tinkoff Invest:
|
||
|
||
### 1. Проверка баланса (`check_balance.py`)
|
||
|
||
```bash
|
||
python tools/check_balance.py
|
||
```
|
||
|
||
**Назначение:** Показывает текущее состояние вашего брокерского счета.
|
||
|
||
**Что показывает:**
|
||
- ID активного счета
|
||
- Свободные рубли (RUB free)
|
||
- Заблокированные рубли (RUB blocked)
|
||
- Доступные для торговли рубли (RUB available)
|
||
- Общая оценка портфеля в валютах (если доступно)
|
||
|
||
**Пример вывода:**
|
||
```
|
||
ACCOUNT_ID: 2235046505
|
||
RUB free: 25000.00
|
||
RUB blocked: 1500.00
|
||
RUB available: 23500.00
|
||
Portfolio total_amount_currencies: 150000.50
|
||
```
|
||
|
||
**Когда использовать:**
|
||
- Перед запуском DCA бота для проверки достаточности средств
|
||
- Для мониторинга состояния счета
|
||
- При отладке проблем с размещением ордеров
|
||
|
||
### 2. Проверка инструментов (`check_figi.py`)
|
||
|
||
```bash
|
||
python tools/check_figi.py
|
||
```
|
||
|
||
**Назначение:** Проверяет корректность FIGI из вашей конфигурации и получает актуальные рыночные данные.
|
||
|
||
**Настройка:** Отредактируйте список `FIGI` в начале файла, добавив ваши FIGI из `config.yml`:
|
||
|
||
```python
|
||
FIGI = [
|
||
"BBG004730N88", # Сбербанк
|
||
"BBG00475KKY8", # Яндекс
|
||
"BBG0013HGFT4", # USD000UTSTOM
|
||
# добавьте ваши FIGI здесь
|
||
]
|
||
```
|
||
|
||
**Что показывает:**
|
||
- Информацию об инструменте (тикер, название, размер лота, валюта)
|
||
- Текущие рыночные цены
|
||
- Список инструментов без доступных цен
|
||
|
||
**Пример вывода:**
|
||
```
|
||
BBG004730N88: SBER | ПАО Сбербанк | lot=10 | curr=rub
|
||
BBG00475KKY8: YNDX | Яндекс Н.В. | lot=1 | curr=rub
|
||
PRICE BBG004730N88: 285.50
|
||
PRICE BBG00475KKY8: 2850.00
|
||
Нет last price для: []
|
||
```
|
||
|
||
**Когда использовать:**
|
||
- При настройке нового `config.yml`
|
||
- Для проверки актуальности FIGI перед запуском
|
||
- При отладке проблем с получением цен
|
||
|
||
### 3. Поиск инструментов (`search.py`)
|
||
|
||
```bash
|
||
python tools/search.py
|
||
```
|
||
|
||
**Назначение:** Помогает найти FIGI для нужных финансовых инструментов по тикеру или названию.
|
||
|
||
**Текущие поисковые запросы в скрипте:**
|
||
- Поиск золота по тикеру "TGLD@"
|
||
- Поиск ОФЗ 26212 по названию
|
||
- Поиск ETF "TPAY"
|
||
- Поиск основных валют (USD, EUR, GBP, JPY)
|
||
|
||
**Как настроить под свои нужды:**
|
||
|
||
1. **Поиск по тикеру акции:**
|
||
```python
|
||
shares = client.instruments.shares()
|
||
for s in shares.instruments:
|
||
if s.ticker == "SBER": # замените на нужный тикер
|
||
print(s.ticker, s.figi, s.name)
|
||
```
|
||
|
||
2. **Поиск облигаций по названию:**
|
||
```python
|
||
bonds = client.instruments.bonds()
|
||
for b in bonds.instruments:
|
||
if "Сбербанк" in b.name: # замените на нужное название
|
||
print(b.name, b.figi)
|
||
```
|
||
|
||
3. **Поиск ETF:**
|
||
```python
|
||
etfs = client.instruments.etfs()
|
||
for e in etfs.instruments:
|
||
if "TECH" in e.ticker: # замените на нужный тикер
|
||
print(e.ticker, e.figi, e.name)
|
||
```
|
||
|
||
4. **Поиск валют:**
|
||
```python
|
||
currencies = client.instruments.currencies()
|
||
for cur in currencies.instruments:
|
||
if "USD" in (cur.ticker or ""):
|
||
print(cur.ticker, cur.figi, cur.name)
|
||
```
|
||
|
||
**Пример вывода:**
|
||
```
|
||
TGLD@ BBG222222222 Золото
|
||
ОФЗ 26212 BBG00Y91R9T3 ОФЗ 26212
|
||
TPAY BBG111111111 TCS Payments
|
||
USD000UTSTOM BBG0013HGFT4 Доллар США
|
||
```
|
||
|
||
**Когда использовать:**
|
||
- При составлении нового портфеля
|
||
- Для поиска альтернативных инструментов
|
||
- При обновлении FIGI (например, для новых выпусков ОФЗ)
|
||
|
||
### Полезные советы по работе с инструментами
|
||
|
||
1. **Всегда проверяйте FIGI** перед добавлением в конфигурацию с помощью `check_figi.py`
|
||
|
||
2. **Для облигаций** FIGI может изменяться при новых выпусках, регулярно обновляйте
|
||
|
||
3. **Валютные пары** имеют разные FIGI для разных сроков поставки (TOM, TOD, SPOT)
|
||
|
||
4. **ETF и фонды** могут иметь ограничения по времени торговли
|
||
|
||
5. **Используйте поиск** для нахождения похожих инструментов в той же отрасли
|
||
|
||
### Автоматизация проверок
|
||
|
||
Можно создать скрипт для автоматической проверки перед запуском DCA:
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
echo "=== Проверка баланса ==="
|
||
python tools/check_balance.py
|
||
|
||
echo -e "\n=== Проверка инструментов ==="
|
||
python tools/check_figi.py
|
||
|
||
echo -e "\n=== Запуск DCA (dry-run) ==="
|
||
python main.py --config config.yml --rub-budget 10000 --dry-run
|
||
```
|
||
|
||
## Логирование
|
||
|
||
Все операции записываются в файл `orders_log.csv` со следующими полями:
|
||
|
||
- `ts` — временная метка
|
||
- `period_key` — ключ периода (YYYY-MM)
|
||
- `figi` — FIGI инструмента
|
||
- `ticker` — тикер
|
||
- `name` — название инструмента
|
||
- `instrument_type` — тип (share, bond, etf, currency)
|
||
- `lots` — количество лотов
|
||
- `lot_size` — размер лота
|
||
- `filled_price_per_share` — цена исполнения за бумагу
|
||
- `cost_rub` — общая стоимость в рублях
|
||
- `status` — статус операции
|
||
- `order_request_id` — ID запроса (если не dry-run)
|
||
|
||
## Особенности работы
|
||
|
||
### Облигации
|
||
Для облигаций автоматически рассчитывается полная стоимость с учетом номинала и накопленного купонного дохода (НКД).
|
||
|
||
### Защита от ошибок
|
||
- Автоматическое уменьшение размера ордера при ошибке 30042 (недостаток средств)
|
||
- Проверка торгового статуса инструментов
|
||
- Пропуск неторгуемых инструментов
|
||
- Буферы для комиссий и проскальзывания
|
||
|
||
### Валюты
|
||
Поддерживаются только инструменты в рублях. Валютные инструменты пропускаются.
|
||
|
||
## Безопасность
|
||
|
||
1. **Никогда не коммитьте `.env` файл** — он содержит секретные токены
|
||
2. **Используйте токены только с необходимыми правами**
|
||
3. **Тестируйте конфигурацию в режиме `--dry-run`**
|
||
4. **Проверяйте баланс перед запуском**
|
||
|
||
## Получение токена
|
||
|
||
1. Перейдите в [личный кабинет Tinkoff Invest](https://www.tinkoff.ru/invest/)
|
||
2. Настройки → API → Создать токен
|
||
3. Выберите права: "Торговля" и "Чтение счетов"
|
||
4. Скопируйте токен в `.env` файл
|
||
|
||
## Автоматизация
|
||
|
||
Для регулярного запуска можно использовать cron:
|
||
|
||
```bash
|
||
# Ежедневно в 10:00 (бот сам решит исполнять ли сделки сегодня)
|
||
0 10 * * * cd /path/to/dca_bot && python main.py --config config.yml --rub-budget 10000 --day-of-month 5
|
||
```
|
||
|
||
## Структура проекта
|
||
|
||
```
|
||
dca_bot/
|
||
├── main.py # Основной скрипт
|
||
├── config.yml # Конфигурация портфеля (создать самостоятельно)
|
||
├── requirements.txt # Зависимости Python
|
||
├── .env # Переменные окружения (создать из .env.example)
|
||
├── .env.example # Шаблон переменных окружения
|
||
├── orders_log.csv # Лог операций (создается автоматически)
|
||
├── tools/
|
||
│ ├── check_balance.py # Проверка баланса
|
||
│ ├── check_figi.py # Проверка инструментов
|
||
│ └── search.py # Поиск инструментов
|
||
└── README.md # Этот файл
|
||
```
|
||
|
||
## Лицензия
|
||
|
||
MIT License
|
||
|
||
## Отказ от ответственности
|
||
|
||
Этот бот предоставляется "как есть" без каких-либо гарантий. Автор не несет ответственности за возможные финансовые потери. Используйте на свой страх и риск. Всегда тестируйте в режиме `--dry-run` перед реальной торговлей.
|