Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_tinkoffSDK-master/my_moving_average.py
5925 views
1
import sys
2
import os
3
from urllib import response
4
5
path = os.getcwd()
6
repo_folder = os.path.dirname(os.path.dirname(path))
7
sys.path.append(repo_folder)
8
#!set PATH=%PATH%;%APPDATA%\Python\Scripts
9
#os.chdir(os.path.dirname(os.path.dirname(path)))
10
11
import logging
12
import operator
13
14
from tinkoff.invest.mock_services import MockedClient
15
from decimal import Decimal
16
from tinkoff.invest.strategies.moving_average.strategy_settings import (
17
MovingAverageStrategySettings,
18
)
19
from tinkoff.invest import CandleInterval, MoneyValue
20
from tinkoff.invest.strategies.moving_average.signal_executor import (
21
MovingAverageSignalExecutor,
22
)
23
from tinkoff.invest.strategies.moving_average.supervisor import (
24
MovingAverageStrategySupervisor,
25
)
26
from tinkoff.invest.strategies.moving_average.strategy_state import (
27
MovingAverageStrategyState,
28
)
29
from tinkoff.invest.strategies.moving_average.strategy import MovingAverageStrategy
30
from tinkoff.invest.strategies.moving_average.trader import MovingAverageStrategyTrader
31
from datetime import timedelta, datetime, timezone
32
from tinkoff.invest.typedefs import ShareId, AccountId
33
from tinkoff.invest.strategies.base.account_manager import AccountManager
34
from tinkoff.invest.strategies.moving_average.plotter import (
35
MovingAverageStrategyPlotter,
36
)
37
38
import my_account_manager
39
import my_trader
40
import my_strategy
41
42
#Все даты учитываются по всемирному времени
43
def start_datetime() -> datetime:
44
return datetime(year=2022, month=5, day=23, hour=7, tzinfo=timezone.utc)
45
46
def main(start_balance_units = 100000, long_ma_min = 30, long_ma_max = 30, short_ma_min = 3, short_ma_max = 3, std_period_min = 22, std_period_max = 22) -> dict:
47
48
print("Start")
49
50
# sandbox token
51
token = os.environ["SANDBOX_TOKEN"]
52
53
54
55
d_long_ma = [] #Диапазон настроек long_ma
56
for i in range(long_ma_min, long_ma_max+1):
57
d_long_ma.append(i)
58
59
d_short_ma = []
60
for i in range(short_ma_min, short_ma_max+1):
61
d_short_ma.append(i)
62
63
d_std_period = []
64
for i in range(std_period_min, std_period_max+1):
65
d_std_period.append(i)
66
67
d_candle_interval = []
68
d_candle_interval.append(CandleInterval.CANDLE_INTERVAL_1_MIN)
69
# d_candle_interval.append(CandleInterval.CANDLE_INTERVAL_5_MIN)
70
# d_candle_interval.append(CandleInterval.CANDLE_INTERVAL_15_MIN)
71
# d_candle_interval.append(CandleInterval.CANDLE_INTERVAL_HOUR)
72
73
long_ma = 15
74
short_ma = 3
75
std_period = 30
76
timaframe = CandleInterval.CANDLE_INTERVAL_1_MIN
77
n, m, s, tf = long_ma, short_ma, std_period, timaframe
78
period = 1 # сюда добавить переход от tf к числу или отрекдактировать код снизу
79
80
stocks = {
81
#"AAPL": {"figi": "BBG000B9XRY4"},
82
#"GAZP": {"figi": "BBG004730RP0"}
83
"VTB": {"figi": "BBG004730ZJ9"}
84
#"MSFT": {"figi": "BBG000BPH459"},
85
# "GOOG":{"figi":"BBG009S3NB30"}, гугл не работает
86
#"AMZN": {"figi": "BBG000BVPV84"},
87
#"TSLA": {"figi": "BBG000N9MNX3"},
88
# "NGK2": {"figi": os.environ["FIGI"]}
89
}
90
91
default_stock = {"figi": "BBG004730ZJ9"}
92
93
settings_data = {} # в этот словарь будут записываться сгенерированные настройки.
94
settings_data['default'] = {
95
"stock": default_stock,
96
'long_ma' : long_ma,
97
'short_ma' : short_ma,
98
'std_period' : std_period,
99
'tf' : timaframe,
100
'period' : period
101
}
102
103
k = 0
104
settings_name = "set" + str(k) #Переменная будет хранить ключи настроек
105
106
#Сгенерируем все наборы настроек:
107
for ci in d_candle_interval:
108
for dlm in d_long_ma:
109
for dsm in d_short_ma:
110
for dsp in d_std_period:
111
settings_data[settings_name] = {
112
"stock": default_stock,
113
'long_ma' : dlm,
114
'short_ma' : dsm,
115
'std_period' : dsp,
116
'tf' : ci,
117
'period' : period # пока константа
118
}
119
k += 1
120
settings_name = "set" + str(k)
121
122
123
124
125
126
127
# тут надо проставлять сдвиг даты в зависимости от выбранного тф
128
# что-то вроде CandleInterval.CANDLE_INTERVAL_1_MIN.seconds * (m+n) для real_market_data_test_from
129
real_market_data_test_from = start_datetime() # с какой даты начинают считаться индикаторы
130
#real_market_data_test_start = start_datetime() + timedelta(minutes=(n + m) * 20) # с какой даты начинает работать стратегия
131
real_market_data_test_start = start_datetime() + timedelta(hours=1)
132
#real_market_data_test_end = start_datetime() + timedelta(days=1)
133
real_market_data_test_end = start_datetime() + timedelta(hours=8) # когда все заканчивается
134
135
takts_count = 420 #Количество тактов робота в минутах, если интервал свеч Минута
136
137
start_balance = MoneyValue(currency="rub", units = start_balance_units, nano=000000000)
138
139
#Начнем логирование здесь:
140
file_name = "Log_mov_aver__shortMA_%s, longMA_%s, stdP_%s,tf_%s.log" %(short_ma,long_ma, std_period,timaframe)
141
logging.basicConfig(format="%(asctime)s %(levelname)s:%(message)s", level=logging.INFO, filename = file_name)
142
logger = logging.getLogger(__name__)
143
144
logger.info("Параметры теста _shortMA_%s, longMA_%s, stdP_%s,tf_%s.log" %(short_ma,long_ma, std_period,timaframe))
145
logger.info(f"Интервал: Дата начала получения свечей = {real_market_data_test_from}, Дата начала торговли (проверки сигналов) = {real_market_data_test_start}, Дата окончания тестовой торговли = {real_market_data_test_end}")
146
logger.info(f"Начальный баланс = {start_balance}")
147
148
149
balances = {}
150
results = []
151
maxprofit = 0
152
best_settings = "none"
153
#results["none"] = {'profit': "none"}
154
155
for set in settings_data:
156
157
figi = ShareId(settings_data[set]['stock']['figi'])
158
159
logger.info(f'Инструмент = {figi}')
160
161
balance = MoneyValue(currency="rub", units = start_balance_units, nano=000000000)
162
163
164
165
#account_id = AccountId("1337007228")
166
account_id = os.environ["INVEST_ACCOUNT_ID"]
167
settings = MovingAverageStrategySettings(
168
share_id=figi, # figi конкретной ценной бумаги
169
account_id=account_id, # неважно для sandbox
170
max_transaction_price=Decimal(
171
100000
172
), # максимальный объем сделки - зависит от размера портфеля. сейчас фиксировано
173
candle_interval=settings_data[set]['tf'], # тф - таймфрейм
174
long_period=timedelta(minutes=settings_data[set]['long_ma'] * settings_data[set]['period']), # длинная скользяшка
175
short_period=timedelta(minutes=settings_data[set]['short_ma'] * settings_data[set]['period']), # короткая скользяшка
176
std_period=timedelta(minutes=settings_data[set]['std_period'] * settings_data[set]['period']), # количество периодов для стд
177
)
178
179
with MockedClient(
180
token=token,
181
settings=settings,
182
real_market_data_test_from=real_market_data_test_from,
183
real_market_data_test_start=real_market_data_test_start,
184
real_market_data_test_end=real_market_data_test_end,
185
balance=balance,
186
) as mocked_services:
187
account_manager = my_account_manager.AccountManager(
188
services=mocked_services, strategy_settings=settings
189
)
190
state = MovingAverageStrategyState()
191
strategy = my_strategy.MovingAverageStrategy(
192
settings=settings,
193
account_manager=account_manager,
194
state=state,
195
)
196
supervisor = MovingAverageStrategySupervisor()
197
signal_executor = MovingAverageSignalExecutor(
198
services=mocked_services,
199
state=state,
200
settings=settings,
201
)
202
moving_average_strategy_trader = my_trader.MovingAverageStrategyTrader(
203
strategy=strategy,
204
settings=settings,
205
services=mocked_services,
206
state=state,
207
signal_executor=signal_executor,
208
account_manager=account_manager,
209
supervisor=supervisor,
210
)
211
212
213
214
plotter = MovingAverageStrategyPlotter(settings=settings)
215
216
217
initial_balance = account_manager.get_current_balance()
218
219
for i in range(takts_count):
220
logger.info("Trade %s", i)
221
moving_average_strategy_trader.trade()
222
223
balance, shares = account_manager.get_current_balance()
224
225
balances[set] = {'cash': balance, 'shares': shares}
226
227
profit = balance - start_balance_units + shares
228
229
results.append({"settings": settings_data[set], "balance": balances[set], "profit": profit})
230
231
if profit > maxprofit:
232
maxprofit = profit
233
best_settings = set
234
235
logger.info(f"РЕЗУЛЬТАТЫ:")
236
logger.info(f"Конечный баланс = {balance}")
237
logger.info(f"Инструмент = {default_stock}")
238
logger.info("Параметры теста _shortMA_%s, longMA_%s, stdP_%s,tf_%s.log" %(settings_data[set]['short_ma'],settings_data[set]['long_ma'] , settings_data[set]['std_period'],settings_data[set]['tf']))
239
logger.info(f"Интервал: Дата начала получения свечей = {real_market_data_test_from}, Дата начала торговли (проверки сигналов) = {real_market_data_test_start}, Дата окончания тестовой торговли = {real_market_data_test_end}")
240
logger.info(f"Начальный баланс = {start_balance_units}")
241
242
if balance + shares - start_balance_units > 0:
243
logger.info(f"Результат = Успешная торговля! Прибыль = {balance - start_balance_units}")
244
#result = f"Результат = Успешная торговля! Прибыль = {balance.units - start_balance.units}"
245
#elif state.long_open:
246
# logger.info(f"Есть открытые позиции. Количество открытых позиций {state.position}")
247
# result = f"Есть открытые позиции. Количество открытых позиций {state.position}"
248
elif balance.units + shares.units - start_balance_units == 0:
249
logger.info(f"Результат = Нейтральный! Прибыль = {balance - start_balance_units}")
250
else:
251
logger.info(f"Результат = Убыток! Убыток = {balance - start_balance_units}")
252
253
254
#best_stock = max(balances, key=balances.get)
255
#best_stock = max(results, key=results.get)
256
257
258
259
# events = supervisor.get_events()
260
# plotter.plot(events)
261
262
#current_balance = account_manager.get_current_balance()
263
# assert initial_balance != current_balance
264
# logger.info("Initial balance %s", initial_balance)
265
# logger.info("Current balance %s", current_balance)
266
267
268
269
270
sorted_results = sorted(results, key = operator.itemgetter('profit'),reverse=True)
271
272
273
return sorted_results
274
275
276
if __name__ == "__main__":
277
main()
278