forked from cia76/QuikPy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathQuikPy.py
592 lines (459 loc) · 42.2 KB
/
QuikPy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
import socket # Обращаться к LUA скриптам QuikSharp будем через соединения
import threading # Результат работы функций обратного вызова будем получать в отдельном потоке
import json # Передавать и принимать данные в QUIK будем через JSON
class Singleton(type):
"""Метакласс для создания Singleton классов"""
def __init__(cls, *args, **kwargs):
"""Инициализация класса"""
super(Singleton, cls).__init__(*args, **kwargs)
cls._singleton = None # Экземпляра класса еще нет
def __call__(cls, *args, **kwargs):
"""Вызов класса"""
if cls._singleton is None: # Если класса нет в экземплярах класса
cls._singleton = super(Singleton, cls).__call__(*args, **kwargs)
return cls._singleton # Возвращаем экземпляр класса
class QuikPy(metaclass=Singleton): # Singleton класс
"""Работа с Quik из Python через LUA скрипты QuikSharp https://github.com/finsight/QUIKSharp/tree/master/src/QuikSharp/lua
На основе Документации по языку LUA в QUIK из https://arqatech.com/ru/support/files/
"""
bufferSize = 1048576 # Размер буфера приема в байтах (1 МБайт)
socketRequests = None # Соединение для запросов
callbackThread = None # Поток обработки функций обратного вызова
def DefaultHandler(self, data):
"""Пустой обработчик события по умолчанию. Его можно заменить на пользовательский"""
pass
def CallbackHandler(self):
"""Поток обработки результатов функций обратного вызова"""
socketCallbacks = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Соединение для функций обратного вызова
socketCallbacks.connect((self.Host, self.CallbacksPort)) # Открываем соединение для функций обратного вызова
currentThread = threading.currentThread() # Получаем текущий поток
fragments = [] # Будем получать ответ в виде списка фрагментов. Они могут быть разной длины. Ответ может состоять из нескольких фрагментов
while getattr(currentThread, 'process', True): # Пока поток нужен
while True: # Пока есть что-то в буфере ответов
fragment = socketCallbacks.recv(self.bufferSize) # Читаем фрагмент из буфера
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
break # то, возможно, это был последний фрагмент, выходим из чтения буфера
data = ''.join(fragments) # Собираем список фрагментов в строку
dataList = data.split('\n') # Одновременно могут прийти несколько функций обратного вызова, разбираем их по одной
fragments = [] # Сбрасываем фрагменты. Если последнюю строку не сможем разобрать, то занесем ее сюда
for data in dataList: # Пробегаемся по всем функциям обратного вызова
if data == '': # Если функция обратного вызова пустая
continue # то ее не разбираем, переходим на следующую функцию, дальше не продолжаем
try: # Пробуем разобрать функцию обратного вызова
data = json.loads(data) # Возвращаем полученный ответ в формате JSON
except json.decoder.JSONDecodeError: # Если разобрать не смогли (пришла не вся строка)
fragments.append(data) # то, что не разобрали ставим в список фрагментов
break # т.к. неполной может быть только последняя строка, то выходим из разбора функций обратного выходва
# Разбираем функцию обратного вызова QUIK LUA
if data['cmd'] == 'OnFirm': # 1. Новая фирма
self.OnFirm(data)
elif data['cmd'] == 'OnAllTrade': # 2. Получение обезличенной сделки
self.OnAllTrade(data)
elif data['cmd'] == 'OnTrade': # 3. Получение новой / изменение существующей сделки
self.OnTrade(data)
elif data['cmd'] == 'OnOrder': # 4. Получение новой / изменение существующей заявки
self.OnOrder(data)
elif data['cmd'] == 'OnAccountBalance': # 5. Изменение позиций по счету
self.OnAccountBalance(data)
elif data['cmd'] == 'OnFuturesLimitChange': # 6. Изменение ограничений по срочному рынку
self.OnFuturesLimitChange(data)
elif data['cmd'] == 'OnFuturesLimitDelete': # 7. Удаление ограничений по срочному рынку
self.OnFuturesLimitDelete(data)
elif data['cmd'] == 'OnFuturesClientHolding': # 8. Изменение позиции по срочному рынку
self.OnFuturesClientHolding(data)
elif data['cmd'] == 'OnMoneyLimit': # 9. Изменение денежной позиции
self.OnMoneyLimit(data)
elif data['cmd'] == 'OnMoneyLimitDelete': # 10. Удаление денежной позиции
self.OnMoneyLimitDelete(data)
elif data['cmd'] == 'OnDepoLimit': # 11. Изменение позиций по инструментам
self.OnDepoLimit(data)
elif data['cmd'] == 'OnDepoLimitDelete': # 12. Удаление позиции по инструментам
self.OnDepoLimitDelete(data)
elif data['cmd'] == 'OnAccountPosition': # 13. Изменение денежных средств
self.OnAccountPosition(data)
# OnNegDeal - 14. Получение новой / изменение существующей внебиржевой заявки
# OnNegTrade - 15. Получение новой / изменение существующей сделки для исполнения
elif data['cmd'] == 'OnStopOrder': # 16. Получение новой / изменение существующей стоп-заявки
self.OnStopOrder(data)
elif data['cmd'] == 'OnTransReply': # 17. Ответ на транзакцию пользователя
self.OnTransReply(data)
elif data['cmd'] == 'OnParam': # 18. Изменение текущих параметров
self.OnParam(data)
elif data['cmd'] == 'OnQuote': # 19. Изменение стакана котировок
self.OnQuote(data)
elif data['cmd'] == 'OnDisconnected': # 20. Отключение терминала от сервера QUIK
self.OnDisconnected(data)
elif data['cmd'] == 'OnConnected': # 21. Соединение терминала с сервером QUIK
self.OnConnected(data)
# OnCleanUp - 22. Смена сервера QUIK / Пользователя / Сессии
elif data['cmd'] == 'OnClose': # 23. Закрытие терминала QUIK
self.OnClose(data)
elif data['cmd'] == 'OnStop': # 24. Остановка LUA скрипта в терминале QUIK / закрытие терминала QUIK
self.OnStop(data)
elif data['cmd'] == 'OnInit': # 25. Запуск LUA скрипта в терминале QUIK
self.OnInit(data)
# Разбираем функции обратного вызова QuikSharp
elif data['cmd'] == 'NewCandle': # Получение новой свечки
self.OnNewCandle(data)
elif data['cmd'] == 'OnError': # Получено сообщение об ошибке
self.OnError(data)
socketCallbacks.close() # Закрываем соединение для ответов
def ProcessRequest(self, Request):
"""Отправляем запрос в QUIK, получаем ответ из QUIK"""
rawData = json.dumps(Request) # Переводим запрос в формат JSON
self.socketRequests.sendall(f'{rawData}\r\n'.encode()) # Отправляем запрос в QUIK
fragments = [] # Гораздо быстрее получать ответ в виде списка фрагментов
while True: # Пока фрагменты есть в буфере
fragment = self.socketRequests.recv(self.bufferSize) # Читаем фрагмент из буфера
fragments.append(fragment.decode('cp1251')) # Переводим фрагмент в Windows кодировку 1251, добавляем в список
if len(fragment) < self.bufferSize: # Если в принятом фрагменте данных меньше чем размер буфера
data = ''.join(fragments) # Собираем список фрагментов в строку
try: # Бывает ситуация, когда данных приходит меньше, но это еще не конец данных
return json.loads(data) # Попробуем вернуть ответ в формате JSON в Windows кодировке 1251
except json.decoder.JSONDecodeError: # Если это еще не конец данных
pass # то ждем фрагментов в буфере дальше
# Инициализация и вход
def __init__(self, Host='127.0.0.1', RequestsPort=34130, CallbacksPort=34131):
"""Инициализация"""
# 2.2. Функции обратного вызова
self.OnFirm = self.DefaultHandler # 1. Новая фирма
self.OnAllTrade = self.DefaultHandler # 2. Получение обезличенной сделки
self.OnTrade = self.DefaultHandler # 3. Получение новой / изменение существующей сделки
self.OnOrder = self.DefaultHandler # 4. Получение новой / изменение существующей заявки
self.OnAccountBalance = self.DefaultHandler # 5. Изменение позиций
self.OnFuturesLimitChange = self.DefaultHandler # 6. Изменение ограничений по срочному рынку
self.OnFuturesLimitDelete = self.DefaultHandler # 7. Удаление ограничений по срочному рынку
self.OnFuturesClientHolding = self.DefaultHandler # 8. Изменение позиции по срочному рынку
self.OnMoneyLimit = self.DefaultHandler # 9. Изменение денежной позиции
self.OnMoneyLimitDelete = self.DefaultHandler # 10. Удаление денежной позиции
self.OnDepoLimit = self.DefaultHandler # 11. Изменение позиций по инструментам
self.OnDepoLimitDelete = self.DefaultHandler # 12. Удаление позиции по инструментам
self.OnAccountPosition = self.DefaultHandler # 13. Изменение денежных средств
# OnNegDeal - 14. Получение новой / изменение существующей внебиржевой заявки
# OnNegTrade - 15. Получение новой / изменение существующей сделки для исполнения
self.OnStopOrder = self.DefaultHandler # 16. Получение новой / изменение существующей стоп-заявки
self.OnTransReply = self.DefaultHandler # 17. Ответ на транзакцию пользователя
self.OnParam = self.DefaultHandler # 18. Изменение текущих параметров
self.OnQuote = self.DefaultHandler # 19. Изменение стакана котировок
self.OnDisconnected = self.DefaultHandler # 20. Отключение терминала от сервера QUIK
self.OnConnected = self.DefaultHandler # 21. Соединение терминала с сервером QUIK
# OnCleanUp - 22. Смена сервера QUIK / Пользователя / Сессии
self.OnClose = self.DefaultHandler # 23. Закрытие терминала QUIK
self.OnStop = self.DefaultHandler # 24. Остановка LUA скрипта в терминале QUIK / закрытие терминала QUIK
self.OnInit = self.DefaultHandler # 25. Запуск LUA скрипта в терминале QUIK
# Функции обратного вызова QuikSharp
self.OnNewCandle = self.DefaultHandler # Получение новой свечки
self.OnError = self.DefaultHandler # Получено сообщение об ошибке
self.Host = Host # IP адрес или название хоста
self.RequestsPort = RequestsPort # Порт для отправки запросов и получения ответов
self.CallbacksPort = CallbacksPort # Порт для функций обратного вызова
self.socketRequests = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Создаем соединение для запросов
self.socketRequests.connect((self.Host, self.RequestsPort)) # Открываем соединение для запросов
self.callbackThread = threading.Thread(target=self.CallbackHandler, name='CallbackThread') # Создаем поток обработки функций обратного вызова
self.callbackThread.start() # Запускаем поток
def __enter__(self):
"""Вход в класс, например, с with"""
return self
# Фукнции связи с QuikSharp
def Ping(self, TransId=0):
"""Проверка соединения. Отправка ping. Получение pong"""
return self.ProcessRequest({'data': 'Ping', 'id': TransId, 'cmd': 'ping', 't': ''})
def Echo(self, Message, TransId=0):
"""Эхо. Отправка и получение одного и того же сообщения"""
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'echo', 't': ''})
def DivideStringByZero(self, TransId=0):
"""Тест обработки ошибок. Выполняется деление на 0 с выдачей ошибки"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'divide_string_by_zero', 't': ''})
def IsQuik(self, TransId=0):
"""Скрипт запущен в Квике"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'is_quik', 't': ''})
# 2.1 Сервисные функции
def IsConnected(self, TransId=0): # 1
"""Состояние подключения терминала к серверу QUIK. Возвращает 1 - подключено / 0 - не подключено"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'isConnected', 't': ''})
def GetScriptPath(self, TransId=0): # 2
"""Путь скрипта без завершающего обратного слэша"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getScriptPath', 't': ''})
def GetInfoParam(self, Params, TransId=0): # 3
"""Значения параметров информационного окна"""
return self.ProcessRequest({'data': Params, 'id': TransId, 'cmd': 'getInfoParam', 't': ''})
# message - 4. Сообщение в терминале QUIK. Реализовано в виде 3-х отдельных функций в QuikSharp
def Sleep(self, Time, TransId=0): # 5
"""Приостановка скрипта. Время в миллисекундах"""
return self.ProcessRequest({'data': Time, 'id': TransId, 'cmd': 'sleep', 't': ''})
def GetWorkingFolder(self, TransId=0): # 6
"""Путь к info.exe, исполняющего скрипт без завершающего обратного слэша"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getWorkingFolder', 't': ''})
def PrintDbgStr(self, Message, TransId=0): # 7
"""Вывод отладочной информации. Можно посмотреть с помощью DebugView"""
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'PrintDbgStr', 't': ''})
# sysdate - 8. Системные дата и время
# isDarkTheme - 9. Тема оформления. true - тёмная, false - светлая
# Сервисные функции QuikSharp
def MessageInfo(self, Message, TransId=0): # В QUIK LUA message icon_type=1
"""Отправка информационного сообщения в терминал QUIK"""
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'message', 't': ''})
def MessageWarning(self, Message, TransId=0): # В QUIK LUA message icon_type=2
"""Отправка сообщения с предупреждением в терминал QUIK"""
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'warning_message', 't': ''})
def MessageError(self, Message, TransId=0): # В QUIK LUA message icon_type=3
"""Отправка сообщения об ошибке в терминал QUIK"""
return self.ProcessRequest({'data': Message, 'id': TransId, 'cmd': 'error_message', 't': ''})
# 3.1. Функции для обращения к строкам произвольных таблиц
# getItem - 1. Строка таблицы
# getOrderByNumber - 2. Заявка
# getNumberOf - 3. Кол-во записей в таблице
# SearchItems - 4. Быстрый поиск по таблице заданной функцией поиска
# Функции для обращения к строкам произвольных таблиц QuikSharp
def GetTradeAccounts(self, TransId=0):
"""Торговые счета, у которых указаны поддерживаемые классы инструментов"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getTradeAccounts', 't': ''})
def GetTradeAccount(self, ClassCode, TransId=0):
"""Торговый счет для запрашиваемого кода класса"""
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getTradeAccount', 't': ''})
def GetAllOrders(self, TransId=0):
"""Таблица заявок (вся)"""
return self.ProcessRequest({'data': f'', 'id': TransId, 'cmd': 'get_orders', 't': ''})
def GetOrders(self, ClassCode, SecCode, TransId=0):
"""Таблица заявок (по инструменту)"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'get_orders', 't': ''})
def GetOrderByNumber(self, OrderId, TransId=0):
"""Заявка по номеру"""
return self.ProcessRequest({'data': OrderId, 'id': TransId, 'cmd': 'getOrder_by_Number', 't': ''})
def GetOrderById(self, ClassCode, SecCode, OrderTransId, TransId=0):
"""Заявка по инструменту и Id транзакции"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{OrderTransId}', 'id': TransId, 'cmd': 'getOrder_by_ID', 't': ''})
def GetOrderByClassNumber(self, ClassCode, OrderId, TransId=0):
"""Заявка по классу инструмента и номеру"""
return self.ProcessRequest({'data': f'{ClassCode}|{OrderId}', 'id': TransId, 'cmd': 'getOrder_by_Number', 't': ''})
def GetMoneyLimits(self, TransId=0):
"""Все денежные лимиты"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getMoneyLimits', 't': ''})
def GetClientCode(self, TransId=0):
"""Основной (первый) код клиента"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getClientCode', 't': ''})
def GetClientCodes(self, TransId=0):
"""Все коды клиента"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getClientCode', 't': ''})
def GetAllDepoLimits(self, TransId=0):
"""Лимиты по бумагам (всем)"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'get_depo_limits', 't': ''})
def GetDepoLimits(self, SecCode, TransId=0):
"""Лимиты по бумагам (по инструменту)"""
return self.ProcessRequest({'data': SecCode, 'id': TransId, 'cmd': 'get_depo_limits', 't': ''})
def GetAllTrades(self, TransId=0):
"""Таблица сделок (вся)"""
return self.ProcessRequest({'data': f'', 'id': TransId, 'cmd': 'get_trades', 't': ''})
def GetTrades(self, ClassCode, SecCode, TransId=0):
"""Таблица сделок (по инструменту)"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'get_trades', 't': ''})
def GetTradesByOrderNumber(self, OrderNum, TransId=0):
"""Таблица сделок по номеру заявки"""
return self.ProcessRequest({'data': OrderNum, 'id': TransId, 'cmd': 'get_Trades_by_OrderNumber', 't': ''})
def GetAllStopOrders(self, TransId=0):
"""Стоп заявки (все)"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'get_stop_orders', 't': ''})
def GetStopOrders(self, ClassCode, SecCode, TransId=0):
"""Стоп заявки (по инструменту)"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'get_stop_orders', 't': ''})
def GetAllTrade(self, TransId=0):
"""Таблица обезличенных сделок (вся)"""
return self.ProcessRequest({'data': f'', 'id': TransId, 'cmd': 'get_all_trades', 't': ''})
def GetTrade(self, ClassCode, SecCode, TransId=0):
"""Таблица обезличенных сделок (по инструменту)"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'get_all_trades', 't': ''})
# 3.2 Функции для обращения к спискам доступных параметров
def GetClassesList(self, TransId=0): # 1
"""Список классов"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getClassesList', 't': ''})
def GetClassInfo(self, ClassCode, TransId=0): # 2
"""Информация о классе"""
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getClassInfo', 't': ''})
def GetClassSecurities(self, ClassCode, TransId=0): # 3
"""Список инструментов класса"""
return self.ProcessRequest({'data': ClassCode, 'id': TransId, 'cmd': 'getClassSecurities', 't': ''})
# Функции для обращения к спискам доступных параметров QuikSharp
def GetOptionBoard(self, ClassCode, SecCode, TransId=0):
"""Доска опционов"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'getOptionBoard', 't': ''})
# 3.3 Функции для получения информации по денежным средствам
def GetMoney(self, ClientCode, FirmId, Tag, CurrCode, TransId=0): # 1
"""Денежные позиции"""
return self.ProcessRequest({'data': f'{ClientCode}|{FirmId}|{Tag}|{CurrCode}', 'id': TransId, 'cmd': 'getMoney', 't': ''})
def GetMoneyEx(self, FirmId, ClientCode, Tag, CurrCode, LimitKind, TransId=0): # 2
"""Денежные позиции указанного типа"""
return self.ProcessRequest({'data': f'{FirmId}|{ClientCode}|{Tag}|{CurrCode}|{LimitKind}', 'id': TransId, 'cmd': 'getMoneyEx', 't': ''})
# 3.4 Функции для получения позиций по инструментам
def GetDepo(self, ClientCode, FirmId, SecCode, Account, TransId=0): # 1
"""Позиции по инструментам"""
return self.ProcessRequest({'data': f'{ClientCode}|{FirmId}|{SecCode}|{Account}', 'id': TransId, 'cmd': 'getDepo', 't': ''})
def GetDepoEx(self, FirmId, ClientCode, SecCode, Account, LimitKind, TransId=0): # 2
"""Позиции по инструментам указанного типа"""
return self.ProcessRequest({'data': f'{FirmId}|{ClientCode}|{SecCode}|{Account}|{LimitKind}', 'id': TransId, 'cmd': 'getDepoEx', 't': ''})
# 3.5 Функция для получения информации по фьючерсным лимитам
def GetFuturesLimit(self, FirmId, AccountId, LimitType, CurrCode, TransId=0): # 1
"""Фьючерсные лимиты"""
return self.ProcessRequest({'data': f'{FirmId}|{AccountId}|{LimitType}|{CurrCode}', 'id': TransId, 'cmd': 'getFuturesLimit', 't': ''})
# Функция для получения информации по фьючерсным лимитам QuikSharp
def GetFuturesClientLimits(self, TransId=0):
"""Все фьючерсные лимиты"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getFuturesClientLimits', 't': ''})
# 3.6 Функция для получения информации по фьючерсным позициям
def GetFuturesHolding(self, FirmId, AccountId, SecCode, PositionType, TransId=0): # 1
"""Фьючерсные позиции"""
return self.ProcessRequest({'data': f'{FirmId}|{AccountId}|{SecCode}|{PositionType}', 'id': TransId, 'cmd': 'getFuturesHolding', 't': ''})
# Функция для получения информации по фьючерсным позициям QuikSharp
def GetFuturesHoldings(self, TransId=0):
"""Все фьючерсные позиции"""
return self.ProcessRequest({'data': '', 'id': TransId, 'cmd': 'getFuturesHolding', 't': ''})
# 3.7 Функция для получения информации по инструменту
def GetSecurityInfo(self, ClassCode, SecCode, TransId=0): # 1
"""Информация по инструменту"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'getSecurityInfo', 't': ''})
# Функция для получения информации по инструменту QuikSharp
def GetSecurityInfoBulk(self, ClassCodes, SecCodes, TransId=0):
"""Информация по инструментам"""
return self.ProcessRequest({'data': f'{ClassCodes}|{SecCodes}', 'id': TransId, 'cmd': 'getSecurityInfoBulk', 't': ''})
def GetSecurityClass(self, ClassesList, SecCode, TransId=0):
"""Класс по коду инструмента из заданных классов"""
return self.ProcessRequest({'data': f'{ClassesList}|{SecCode}', 'id': TransId, 'cmd': 'getSecurityClass', 't': ''})
# 3.8 Функция для получения даты торговой сессии
# getTradeDate - 1. Дата текущей торговой сессии
# 3.9 Функция для получения стакана по указанному классу и инструменту
def GetQuoteLevel2(self, ClassCode, SecCode, TransId=0): # 1
"""Стакан по классу и инструменту"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'GetQuoteLevel2', 't': ''})
# 3.10 Функции для работы с графиками
# getLinesCount - 1. Кол-во линий в графике
def GetNumCandles(self, Tag, TransId=0): # 2
"""Кол-во свечей по тэгу"""
return self.ProcessRequest({'data': Tag, 'id': TransId, 'cmd': 'get_num_candles', 't': ''})
# getCandlesByIndex - 3. Информация о свечках (реализовано в get_candles)
# CreateDataSource - 4. Создание источника данных c функциями: (реализовано в get_candles_from_data_source)
# - SetUpdateCallback - Привязка функции обратного вызова на изменение свечи
# - O, H, L, C, V, T - Функции получения цен, объемов и времени
# - Size - Функция кол-ва свечек в источнике данных
# - Close - Функция закрытия источника данных. Терминал прекращает получать данные с сервера
# - SetEmptyCallback - Функция сброса функции обратного вызова на изменение свечи
# Функции для работы с графиками QuikSharp
def GetCandles(self, Tag, Line, FirstCandle, Count, TransId=0):
"""Свечки по идентификатору графика"""
return self.ProcessRequest({'data': f'{Tag}|{Line}|{FirstCandle}|{Count}', 'id': TransId, 'cmd': 'get_candles', 't': ''})
def GetCandlesFromDataSource(self, ClassCode, SecCode, Interval, Count): # ichechet - Добавлен выход по таймауту
"""Свечки"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{Interval}|{Count}', 'id': '1', 'cmd': 'get_candles_from_data_source', 't': ''})
def SubscribeToCandles(self, ClassCode, SecCode, Interval, TransId=0):
"""Подписка на свечки"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{Interval}', 'id': TransId, 'cmd': 'subscribe_to_candles', 't': ''})
def IsSubscribed(self, ClassCode, SecCode, Interval, TransId=0):
"""Есть ли подписка на свечки"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{Interval}', 'id': TransId, 'cmd': 'is_subscribed', 't': ''})
def UnsubscribeFromCandles(self, ClassCode, SecCode, Interval, TransId=0):
"""Отмена подписки на свечки"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{Interval}', 'id': TransId, 'cmd': 'unsubscribe_from_candles', 't': ''})
# 3.11 Функции для работы с заявками
def SendTransaction(self, Transaction, TransId=0): # 1
"""Отправка транзакции в торговую систему"""
return self.ProcessRequest({'data': Transaction, 'id': TransId, 'cmd': 'sendTransaction', 't': ''})
# CalcBuySell - 2. Максимальное кол-во лотов в заявке
# 3.12 Функции для получения значений таблицы "Текущие торги"
def GetParamEx(self, ClassCode, SecCode, ParamName, TransId=0): # 1
"""Таблица текущих торгов"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{ParamName}', 'id': TransId, 'cmd': 'getParamEx', 't': ''})
def GetParamEx2(self, ClassCode, SecCode, ParamName, TransId=0): # 2
"""Таблица текущих торгов по инструменту с возможностью отказа от получения"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{ParamName}', 'id': TransId, 'cmd': 'getParamEx2', 't': ''})
# Функция для получения значений таблицы "Текущие торги" QuikSharp
def GetParamEx2Bulk(self, ClassCodes, SecCodes, ParamNames, TransId=0):
"""Таблица текущих торгов по инструментам с возможностью отказа от получения"""
return self.ProcessRequest({'data': f'{ClassCodes}|{SecCodes}|{ParamNames}', 'id': TransId, 'cmd': 'getParamEx2Bulk', 't': ''})
# 3.13 Функции для получения параметров таблицы "Клиентский портфель"
def GetPortfolioInfo(self, FirmId, ClientCode, TransId=0): # 1
"""Клиентский портфель"""
return self.ProcessRequest({'data': f'{FirmId}|{ClientCode}', 'id': TransId, 'cmd': 'getPortfolioInfo', 't': ''})
def GetPortfolioInfoEx(self, FirmId, ClientCode, LimitKind, TransId=0): # 2
"""Клиентский портфель по сроку расчетов"""
return self.ProcessRequest({'data': f'{FirmId}|{ClientCode}|{LimitKind}', 'id': TransId, 'cmd': 'getPortfolioInfoEx', 't': ''})
# 3.14 Функции для получения параметров таблицы "Купить/Продать"
# getBuySellInfo - 1. Параметры таблицы купить/продать
# getBuySellInfoEx - 2. Параметры таблицы купить/продать с дополнительными полями вывода
# 3.15 Функции для работы с таблицами Рабочего места QUIK
# AddColumn - 1. Добавление колонки в таблицу
# AllocTable - 2. Структура, описывающая таблицу
# Clear - 3. Удаление содержимого таблицы
# CreateWindow - 4. Создание окна таблицы
# DeleteRow - 5. Удаление строки из таблицы
# DestroyTable - 6. Закрытие окна таблицы
# InsertRow - 7. Добавление строки в таблицу
# IsWindowClosed - 8. Закрыто ли окно с таблицей
# GetCell - 9. Данные ячейки таблицы
# GetTableSize - 10. Кол-во строк и столбцов таблицы
# GetWindowCaption - 11. Заголовок окна таблицы
# GetWindowRect - 12. Координаты верхнего левого и правого нижнего углов таблицы
# SetCell - 13. Установка значения ячейки таблицы
# SetWindowCaption - 14. Установка заголовка окна таблицы
# SetWindowPos - 15. Установка верхнего левого угла, и размеры таблицы
# SetTableNotificationCallback - 16. Установка функции обратного вызова для обработки событий в таблице
# RGB - 17. Преобразование каждого цвета в одно число для функци SetColor
# SetColor - 18. Установка цвета ячейки, столбца или строки таблицы
# Highlight - 19. Подсветка диапазона ячеек цветом фона и цветом текста на заданное время с плавным затуханием
# SetSelectedRow - 20. Выделение строки таблицы
# 3.16 Функции для работы с метками
def AddLabel(self, Price, CurDate, CurTime, Qty, Path, LabelId, Alignment, Background, TransId=0): # 1
"""Добавление метки на график"""
return self.ProcessRequest({'data': f'{Price}|{CurDate}|{CurTime}|{Qty}|{Path}|{LabelId}|{Alignment}|{Background}', 'id': TransId, 'cmd': 'AddLabel', 't': ''})
def DelLabel(self, ChartTag, LabelId, TransId=0): # 2
"""Удаление метки с графика"""
return self.ProcessRequest({'data': f'{ChartTag}|{LabelId}', 'id': TransId, 'cmd': 'DelLabel', 't': ''})
def DelAllLabels(self, ChartTag, TransId=0): # 3
"""Удаление всех меток с графика"""
return self.ProcessRequest({'data': ChartTag, 'id': TransId, 'cmd': 'DelAllLabels', 't': ''})
def GetLabelParams(self, ChartTag, LabelId, TransId=0): # 4
"""Получение параметров метки"""
return self.ProcessRequest({'data': f'{ChartTag}|{LabelId}', 'id': TransId, 'cmd': 'GetLabelParams', 't': ''})
# SetLabelParams - 5. Установка параметров метки
# 3.17 Функции для заказа стакана котировок
def SubscribeLevel2Quotes(self, ClassCode, SecCode, TransId=0): # 1
"""Подписка на стакан по Классу|Коду бумаги"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'Subscribe_Level_II_Quotes', 't': ''})
def UnsubscribeLevel2Quotes(self, ClassCode, SecCode, TransId=0): # 2
"""Отмена подписки на стакан по Классу|Коду бумаги"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'Unsubscribe_Level_II_Quotes', 't': ''})
def IsSubscribedLevel2Quotes(self, ClassCode, SecCode, TransId=0): # 3
"""Есть ли подписка на стакан по Классу|Коду бумаги"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}', 'id': TransId, 'cmd': 'IsSubscribed_Level_II_Quotes', 't': ''})
# 3.18 Функции для заказа параметров Таблицы текущих торгов
def ParamRequest(self, ClassCode, SecCode, ParamName, TransId=0): # 1
"""Заказ получения таблицы текущих торгов по инструменту"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{ParamName}', 'id': TransId, 'cmd': 'paramRequest', 't': ''})
def CancelParamRequest(self, ClassCode, SecCode, ParamName, TransId=0): # 2
"""Отмена заказа получения таблицы текущих торгов по инструменту"""
return self.ProcessRequest({'data': f'{ClassCode}|{SecCode}|{ParamName}', 'id': TransId, 'cmd': 'cancelParamRequest', 't': ''})
# Функции для заказа параметров Таблицы текущих торгов QuikSharp
def ParamRequestBulk(self, ClassCodes, SecCodes, ParamNames, TransId=0):
"""Заказ получения таблицы текущих торгов по инструментам"""
return self.ProcessRequest({'data': f'{ClassCodes}|{SecCodes}|{ParamNames}', 'id': TransId, 'cmd': 'paramRequestBulk', 't': ''})
def CancelParamRequestBulk(self, ClassCodes, SecCodes, ParamNames, TransId=0):
"""Отмена заказа получения таблицы текущих торгов по инструментам"""
return self.ProcessRequest({'data': f'{ClassCodes}|{SecCodes}|{ParamNames}', 'id': TransId, 'cmd': 'cancelParamRequestBulk', 't': ''})
# 3.19 Функции для получения информации по единой денежной позиции
def GetTrdAccByClientCode(self, FirmId, ClientCode, TransId=0): # 1
"""Торговый счет срочного рынка по коду клиента фондового рынка"""
return self.ProcessRequest({'data': f'{FirmId}|{ClientCode}', 'id': TransId, 'cmd': 'getTrdAccByClientCode', 't': ''})
def GetClientCodeByTrdAcc(self, FirmId, TradeAccountId, TransId=0): # 2
"""Код клиента фондового рынка с единой денежной позицией по торговому счету срочного рынка"""
return self.ProcessRequest({'data': f'{FirmId}|{TradeAccountId}', 'id': TransId, 'cmd': 'getClientCodeByTrdAcc', 't': ''})
def IsUcpClient(self, FirmId, Client, TransId=0): # 3
"""Имеет ли клиент единую денежную позицию"""
return self.ProcessRequest({'data': f'{FirmId}|{Client}', 'id': TransId, 'cmd': 'IsUcpClient', 't': ''})
# Выход и закрытие
def CloseConnectionAndThread(self):
"""Закрытие соединения для запросов и потока обработки функций обратного вызова"""
self.socketRequests.close() # Закрываем соединение для запросов
self.callbackThread.process = False # Поток обработки функций обратного вызова больше не нужен
def __exit__(self, exc_type, exc_val, exc_tb):
"""Выход из класса, например, с with"""
self.CloseConnectionAndThread() # Закрываем соединение для запросов и поток обработки функций обратного вызова
def __del__(self):
self.CloseConnectionAndThread() # Закрываем соединение для запросов и поток обработки функций обратного вызова