Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_tinkoffSDK-master/robot_fatbold.py
5925 views
1
import sys
2
import os
3
from urllib import response
4
5
from grpc import services
6
7
path = os.getcwd()
8
repo_folder = os.path.dirname(os.path.dirname(path))
9
sys.path.append(repo_folder)
10
#!set PATH=%PATH%;%APPDATA%\Python\Scripts
11
#os.chdir(os.path.dirname(os.path.dirname(path)))
12
13
import logging
14
import time
15
16
from tinkoff.invest.mock_services import MockedClient
17
from decimal import Decimal
18
from tinkoff.invest.strategies.moving_average.strategy_settings import (
19
MovingAverageStrategySettings,
20
)
21
from tinkoff.invest import CandleInterval, MoneyValue
22
from tinkoff.invest.strategies.moving_average.signal_executor import (
23
MovingAverageSignalExecutor,
24
)
25
from tinkoff.invest.strategies.moving_average.supervisor import (
26
MovingAverageStrategySupervisor,
27
)
28
from tinkoff.invest.strategies.moving_average.strategy_state import (
29
MovingAverageStrategyState,
30
)
31
from tinkoff.invest.strategies.moving_average.strategy import MovingAverageStrategy
32
from tinkoff.invest.strategies.moving_average.trader import MovingAverageStrategyTrader
33
from datetime import timedelta, datetime, timezone
34
from tinkoff.invest.typedefs import ShareId, AccountId
35
from tinkoff.invest.strategies.base.account_manager import AccountManager
36
from tinkoff.invest.strategies.moving_average.plotter import (
37
MovingAverageStrategyPlotter,
38
)
39
40
from tinkoff.invest import (
41
CandleInstrument,
42
InvestError,
43
Client,
44
InfoInstrument,
45
SubscriptionInterval,
46
)
47
48
from tinkoff.invest.services import MarketDataStreamManager
49
from tinkoff.invest.services import MarketDataService
50
from tinkoff.invest import GetTradingStatusRequest
51
52
import my_account_manager
53
import my_trader
54
import my_strategy
55
import asyncio
56
import my_signal_executor
57
58
59
#Все даты учитываются по всемирному времени
60
def start_datetime() -> datetime:
61
return datetime.now()
62
63
async def main(long_ma = 30, short_ma= 3, std_period = 22):
64
65
TOKEN = os.environ["IIS_INVEST_TOKEN"]
66
67
account_id = os.environ["INVEST_ACCOUNT_ID"]
68
69
candle_interval = SubscriptionInterval.SUBSCRIPTION_INTERVAL_ONE_MINUTE
70
71
default_stock = {"figi": "BBG004730ZJ9"} #Акции ВТБ
72
73
period = 1 # сюда добавить переход от tf к числу или отрекдактировать код снизу
74
75
76
# Загружаем в робота настройки полученные из телеграмма. Наборы настроек для боевого робота и теста в песочнице одинаковые,
77
# чтобы можно было их быстро применить после теста.
78
# Настройки хранятся в словаре, для сохранения унификации кода с песочницей
79
settings_data = {}
80
settings_data['default'] = {
81
"stock": default_stock,
82
'long_ma' : long_ma,
83
'short_ma' : short_ma,
84
'std_period' : std_period, #волотильность пока не учитывается в стратегии
85
'tf' : candle_interval,
86
'period' : period
87
}
88
89
set = 'default' #Ключ настроек робота, настройки хранятся в словаре, для сохранения унификации с песочницей
90
91
figi = ShareId(settings_data[set]['stock']['figi'])
92
93
94
#Начнем логирование здесь:
95
file_name = "Log_mov_aver__shortMA_%s, longMA_%s, stdP_%s,tf_%s.log" %(short_ma,long_ma, std_period, candle_interval)
96
logging.basicConfig(format="%(asctime)s %(levelname)s:%(message)s", level=logging.INFO, filename = file_name)
97
logger = logging.getLogger(__name__)
98
99
logger.info(f'Инструмент = {figi}')
100
logger.info("Параметры Запуска робота _shortMA_%s, longMA_%s, stdP_%s,tf_%s.log" %(short_ma,long_ma, std_period,candle_interval))
101
102
103
settings = MovingAverageStrategySettings(
104
share_id=figi, # figi конкретной ценной бумаги
105
account_id=account_id, # неважно для sandbox
106
max_transaction_price=Decimal(
107
200
108
), # максимальный объем сделки - зависит от размера портфеля. сейчас фиксировано под Акции ВТБ
109
candle_interval=settings_data[set]['tf'], # тф - таймфрейм
110
long_period=timedelta(minutes=settings_data[set]['long_ma'] * settings_data[set]['period']), # длинная скользяшка
111
short_period=timedelta(minutes=settings_data[set]['short_ma'] * settings_data[set]['period']), # короткая скользяшка
112
std_period=timedelta(minutes=settings_data[set]['std_period'] * settings_data[set]['period']), # количество периодов для стд
113
)
114
115
116
k = 0
117
118
my_app_name = "AndreiSoiko.tinkoffSDK" #Название приложения для участия в конкурсе
119
120
start_balance_units = 0
121
122
with Client(TOKEN,app_name=my_app_name) as client: #Присоединяемся к аккаунту для начала работы
123
market_data_stream: MarketDataStreamManager = client.create_market_data_stream()
124
125
#Подписываемся на информацию о свечах инструмента
126
market_data_stream.candles.subscribe(
127
[
128
CandleInstrument(
129
figi,
130
interval=candle_interval,
131
)
132
]
133
)
134
135
market_data_stream.info.subscribe(
136
[default_stock]
137
)
138
139
#Позволяет получать информацию о состоянии счета
140
account_manager = my_account_manager.AccountManager(
141
services=client, strategy_settings=settings
142
)
143
144
#Объект хранит информацию о количестве позиций, которые должны быть открыты/закрыты роботом согласно сигналам стратегии
145
state = MovingAverageStrategyState()
146
147
#Сама стратегия, в которой проводит анализ данных рынка и генерирует сигналы
148
strategy = my_strategy.MovingAverageStrategy(
149
settings=settings,
150
account_manager=account_manager,
151
state=state,
152
)
153
154
#Объект, который накапливает полученные сигналы. В песочнице используется для дальнейшей визуализации. В рабочем режиме пока не используется
155
supervisor = MovingAverageStrategySupervisor()
156
157
158
#Объект, который обрабатывает полученные стратегией сигналы и выставляет ордера на биржу
159
signal_executor = my_signal_executor.MovingAverageSignalExecutor(
160
services=client,
161
state=state,
162
settings=settings,
163
)
164
165
#Объект, который собирает в себе все предыдущие объекты и ими управляет. Его метод trade() выполняет 1 такт торговли.
166
moving_average_strategy_trader = my_trader.MovingAverageStrategyTrader(
167
strategy=strategy,
168
settings=settings,
169
services=client,
170
state=state,
171
signal_executor=signal_executor,
172
account_manager=account_manager,
173
supervisor=supervisor,
174
)
175
176
177
#Зафиксируем баланс на начало работы сессии робота
178
if k == 0:
179
180
start_balance_units, start_shares = account_manager.get_current_balance()
181
k += 1
182
183
profit = 0 #Установим счетчик прибыли сессии в деньгах
184
profit_shares = 0 #Установим счетчик роста портфеля
185
186
187
real_market_data_from = start_datetime() #Зафиксируем время начало работы робота
188
#Рассчитаем время после, которого у робота должно быть достаточно данных для работы стратегии
189
real_market_data_start = start_datetime() + timedelta(minutes=max(std_period,long_ma))
190
191
logger.info(f"Интервал: Дата начала получения свечей = {real_market_data_from}, Дата начала торговли (проверки сигналов) = {real_market_data_start}")
192
logger.info(f"Начальный баланс = {start_balance_units}")
193
logger.info(f"Начальный баланс акций= {start_shares}")
194
195
196
response = {} #Структура для возврата информации телеграмм боту
197
198
for marketdata in market_data_stream:
199
print(marketdata) #Создает ощущение матрицы в терминале
200
market_data_stream.info.subscribe([InfoInstrument(figi)]) #Подписываемся на получение информации о акциях ВТБ
201
202
203
market_order_available_flag = client.market_data.get_trading_status(figi = default_stock['figi']).market_order_available_flag
204
if market_order_available_flag: #Торговля доступна
205
moving_average_strategy_trader.trade()
206
207
208
balance, shares = account_manager.get_current_balance()
209
profit = float(balance - start_balance_units + shares - start_shares)
210
profit_shares = float(shares - start_shares)
211
212
213
response = {
214
'status': "Working",
215
'profit': profit,
216
'profit_shares': profit_shares,
217
'balance': balance,
218
'shares': shares
219
}
220
yield response #Вернем телеграмм боту информцию о текущей работе робота
221
time.sleep(60) #Уснем на 60 секунд. Свечи то, минутные ))
222
223
224
else:
225
market_data_stream.stop()
226
227
client.cancel_all_orders(account_id=account_id) #Закроем все ордера
228
229
balance, shares = account_manager.get_current_balance()
230
profit = float(balance - start_balance_units + shares - start_shares)
231
profit_shares = float(shares - start_shares)
232
233
response = {
234
'status': "Торги сейчас не ведуться",
235
'profit': profit,
236
'profit_shares': profit_shares,
237
'balance': balance,
238
'shares': shares
239
}
240
yield response
241
242
243
244
245
#if direct_action == "stop":
246
# logger.info(f"Прибыль от сессии робота в кэше = {profit}")
247
# logger.info(f"Прибыль от сессии робота в акциях = {profit_shares}")
248
# logger.info(f"Дата окончания тестовой торговли = {start_datetime()}")
249
250
251
252
if __name__ == "__main__":
253
main()
254
255
256
257
258