Path: blob/master/ invest-robot-contest_tinkoffSDK-master/robot_fatbold.py
5925 views
import sys1import os2from urllib import response34from grpc import services56path = os.getcwd()7repo_folder = os.path.dirname(os.path.dirname(path))8sys.path.append(repo_folder)9#!set PATH=%PATH%;%APPDATA%\Python\Scripts10#os.chdir(os.path.dirname(os.path.dirname(path)))1112import logging13import time1415from tinkoff.invest.mock_services import MockedClient16from decimal import Decimal17from tinkoff.invest.strategies.moving_average.strategy_settings import (18MovingAverageStrategySettings,19)20from tinkoff.invest import CandleInterval, MoneyValue21from tinkoff.invest.strategies.moving_average.signal_executor import (22MovingAverageSignalExecutor,23)24from tinkoff.invest.strategies.moving_average.supervisor import (25MovingAverageStrategySupervisor,26)27from tinkoff.invest.strategies.moving_average.strategy_state import (28MovingAverageStrategyState,29)30from tinkoff.invest.strategies.moving_average.strategy import MovingAverageStrategy31from tinkoff.invest.strategies.moving_average.trader import MovingAverageStrategyTrader32from datetime import timedelta, datetime, timezone33from tinkoff.invest.typedefs import ShareId, AccountId34from tinkoff.invest.strategies.base.account_manager import AccountManager35from tinkoff.invest.strategies.moving_average.plotter import (36MovingAverageStrategyPlotter,37)3839from tinkoff.invest import (40CandleInstrument,41InvestError,42Client,43InfoInstrument,44SubscriptionInterval,45)4647from tinkoff.invest.services import MarketDataStreamManager48from tinkoff.invest.services import MarketDataService49from tinkoff.invest import GetTradingStatusRequest5051import my_account_manager52import my_trader53import my_strategy54import asyncio55import my_signal_executor565758#Все даты учитываются по всемирному времени59def start_datetime() -> datetime:60return datetime.now()6162async def main(long_ma = 30, short_ma= 3, std_period = 22):6364TOKEN = os.environ["IIS_INVEST_TOKEN"]6566account_id = os.environ["INVEST_ACCOUNT_ID"]6768candle_interval = SubscriptionInterval.SUBSCRIPTION_INTERVAL_ONE_MINUTE6970default_stock = {"figi": "BBG004730ZJ9"} #Акции ВТБ7172period = 1 # сюда добавить переход от tf к числу или отрекдактировать код снизу737475# Загружаем в робота настройки полученные из телеграмма. Наборы настроек для боевого робота и теста в песочнице одинаковые,76# чтобы можно было их быстро применить после теста.77# Настройки хранятся в словаре, для сохранения унификации кода с песочницей78settings_data = {}79settings_data['default'] = {80"stock": default_stock,81'long_ma' : long_ma,82'short_ma' : short_ma,83'std_period' : std_period, #волотильность пока не учитывается в стратегии84'tf' : candle_interval,85'period' : period86}8788set = 'default' #Ключ настроек робота, настройки хранятся в словаре, для сохранения унификации с песочницей8990figi = ShareId(settings_data[set]['stock']['figi'])919293#Начнем логирование здесь:94file_name = "Log_mov_aver__shortMA_%s, longMA_%s, stdP_%s,tf_%s.log" %(short_ma,long_ma, std_period, candle_interval)95logging.basicConfig(format="%(asctime)s %(levelname)s:%(message)s", level=logging.INFO, filename = file_name)96logger = logging.getLogger(__name__)9798logger.info(f'Инструмент = {figi}')99logger.info("Параметры Запуска робота _shortMA_%s, longMA_%s, stdP_%s,tf_%s.log" %(short_ma,long_ma, std_period,candle_interval))100101102settings = MovingAverageStrategySettings(103share_id=figi, # figi конкретной ценной бумаги104account_id=account_id, # неважно для sandbox105max_transaction_price=Decimal(106200107), # максимальный объем сделки - зависит от размера портфеля. сейчас фиксировано под Акции ВТБ108candle_interval=settings_data[set]['tf'], # тф - таймфрейм109long_period=timedelta(minutes=settings_data[set]['long_ma'] * settings_data[set]['period']), # длинная скользяшка110short_period=timedelta(minutes=settings_data[set]['short_ma'] * settings_data[set]['period']), # короткая скользяшка111std_period=timedelta(minutes=settings_data[set]['std_period'] * settings_data[set]['period']), # количество периодов для стд112)113114115k = 0116117my_app_name = "AndreiSoiko.tinkoffSDK" #Название приложения для участия в конкурсе118119start_balance_units = 0120121with Client(TOKEN,app_name=my_app_name) as client: #Присоединяемся к аккаунту для начала работы122market_data_stream: MarketDataStreamManager = client.create_market_data_stream()123124#Подписываемся на информацию о свечах инструмента125market_data_stream.candles.subscribe(126[127CandleInstrument(128figi,129interval=candle_interval,130)131]132)133134market_data_stream.info.subscribe(135[default_stock]136)137138#Позволяет получать информацию о состоянии счета139account_manager = my_account_manager.AccountManager(140services=client, strategy_settings=settings141)142143#Объект хранит информацию о количестве позиций, которые должны быть открыты/закрыты роботом согласно сигналам стратегии144state = MovingAverageStrategyState()145146#Сама стратегия, в которой проводит анализ данных рынка и генерирует сигналы147strategy = my_strategy.MovingAverageStrategy(148settings=settings,149account_manager=account_manager,150state=state,151)152153#Объект, который накапливает полученные сигналы. В песочнице используется для дальнейшей визуализации. В рабочем режиме пока не используется154supervisor = MovingAverageStrategySupervisor()155156157#Объект, который обрабатывает полученные стратегией сигналы и выставляет ордера на биржу158signal_executor = my_signal_executor.MovingAverageSignalExecutor(159services=client,160state=state,161settings=settings,162)163164#Объект, который собирает в себе все предыдущие объекты и ими управляет. Его метод trade() выполняет 1 такт торговли.165moving_average_strategy_trader = my_trader.MovingAverageStrategyTrader(166strategy=strategy,167settings=settings,168services=client,169state=state,170signal_executor=signal_executor,171account_manager=account_manager,172supervisor=supervisor,173)174175176#Зафиксируем баланс на начало работы сессии робота177if k == 0:178179start_balance_units, start_shares = account_manager.get_current_balance()180k += 1181182profit = 0 #Установим счетчик прибыли сессии в деньгах183profit_shares = 0 #Установим счетчик роста портфеля184185186real_market_data_from = start_datetime() #Зафиксируем время начало работы робота187#Рассчитаем время после, которого у робота должно быть достаточно данных для работы стратегии188real_market_data_start = start_datetime() + timedelta(minutes=max(std_period,long_ma))189190logger.info(f"Интервал: Дата начала получения свечей = {real_market_data_from}, Дата начала торговли (проверки сигналов) = {real_market_data_start}")191logger.info(f"Начальный баланс = {start_balance_units}")192logger.info(f"Начальный баланс акций= {start_shares}")193194195response = {} #Структура для возврата информации телеграмм боту196197for marketdata in market_data_stream:198print(marketdata) #Создает ощущение матрицы в терминале199market_data_stream.info.subscribe([InfoInstrument(figi)]) #Подписываемся на получение информации о акциях ВТБ200201202market_order_available_flag = client.market_data.get_trading_status(figi = default_stock['figi']).market_order_available_flag203if market_order_available_flag: #Торговля доступна204moving_average_strategy_trader.trade()205206207balance, shares = account_manager.get_current_balance()208profit = float(balance - start_balance_units + shares - start_shares)209profit_shares = float(shares - start_shares)210211212response = {213'status': "Working",214'profit': profit,215'profit_shares': profit_shares,216'balance': balance,217'shares': shares218}219yield response #Вернем телеграмм боту информцию о текущей работе робота220time.sleep(60) #Уснем на 60 секунд. Свечи то, минутные ))221222223else:224market_data_stream.stop()225226client.cancel_all_orders(account_id=account_id) #Закроем все ордера227228balance, shares = account_manager.get_current_balance()229profit = float(balance - start_balance_units + shares - start_shares)230profit_shares = float(shares - start_shares)231232response = {233'status': "Торги сейчас не ведуться",234'profit': profit,235'profit_shares': profit_shares,236'balance': balance,237'shares': shares238}239yield response240241242243244#if direct_action == "stop":245# logger.info(f"Прибыль от сессии робота в кэше = {profit}")246# logger.info(f"Прибыль от сессии робота в акциях = {profit_shares}")247# logger.info(f"Дата окончания тестовой торговли = {start_datetime()}")248249250251if __name__ == "__main__":252main()253254255256257258