Пример скрипта QLua (Lua), выполняющего торговые операции в терминале QUIK

Автор записи: Дмитрий (Admin)

OpenClose
Скрипт позволяет открывать и закрывать позиции следующего типа:
- покупается 2, выбранных при помощи кнопок, колл-опциона на фьючерс на индекс РТС,
- продается 1, выбранный при помощи кнопок, фьючерс на индекс РТС.

Когда есть открытая данным скриптом позиция, в таблице отображается информация о ней (профит, баланс, ср.цена, дата открытия).

Профит вычисляется по формуле: "Текущая цена, по которой можно закрыть позицию" - "Цена открытия позиции" - "Комиссия 8 р. на каждый лот".

Так же, выполняется запись в лог-файл ("Log.txt") выполняемых скриптом операций и в файле состояния ("State.txt") хранится информация о текущих выбранных инструментах и о текущей, открытой скриптом позиции.

ВАЖНО!!! При выборе опциона, кнопками "/\","\/" меняется страйк опциона с шагом 500, убедитесь в том, что такой опцион существует!!!

Код скрипта
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
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
-- Скрипт позволяет открывать и закрывать позиции следующего типа:
-- покупается 2, выбранных при помощи кнопок, колл-опциона на фьючерс на индекс РТС,
-- продается 1, выбранный при помощи кнопок, фьючерс на индекс РТС.
-- Когда есть открытая данным скриптом позиция, в таблице отображается информация о ней (профит, баланс, ср.цена, дата открытия).
-- Профит вычисляется по формуле: "Текущая цена, по которой можно закрыть позицию" - "Цена открытия позиции" - "Комиссия 8 р. на каждый лот"
-- Так же, выполняется запись в лог-файл ("Log.txt") выполняемых скриптом операций
-- и в файле состояния ("State.txt") хранится информация о текущих выбранных инструментах и о текущей, открытой скриптом позиции
-- ВАЖНО!!! При выборе опциона, кнопками «/\»,»\/» меняется страйк опциона с шагом 500, убедитесь в том, что такой опцион существует!!!
-- (c) QuikLuaCSharp.ru
 
-- Флаг поддержания работы скрипта
IsRun = true;
 
COMMISSION = 4;   -- Комиссия (примерно) (биржа + брокер) за 1-у торговую операцию по 1-му лоту опциона, или фьючерса
 
 
TRADE_ACC               = "SPBFUT00136";     -- Торговый счет
CLIENT_CODE             = "SPBFUT00136";     -- Код клиента
CLASS_CODE_OPT          = "SPBOPT";          -- Класс ОПЦИОНОВ
CLASS_CODE_FUT          = "SPBFUT";          -- Класс ФЬЮЧЕРСОВ
 
SEC_CODE_FUT_FOR_OPEN   = "RIM5";            -- Код ФЬЮЧЕРСА для открытия
SEC_CODE_OPT_FOR_OPEN   = "RI110000BF5";     -- Код ОПЦИОНА для открытия
SEC_CODE_OPT_IN_POS     = "";                -- Код ОПЦИОНА в позиции
OPEN_BALANCE_OPT        = 0;                 -- Баланс позиции по ОПЦИОНАМ
OPEN_PRICE_OPT          = 0;                 -- Средняя цена открытия позиции по ОПЦИОНАМ
OPEN_DATE_OPT           = "";                -- Дата открытия позиции по ОПЦИОНАМ
SEC_CODE_FUT_IN_POS     = "";                -- Код ФЬЮЧЕРСА в позиции
OPEN_BALANCE_FUT        = 0;                 -- Баланс позиции по ФЬЮЧЕРСАМ
OPEN_PRICE_FUT          = 0;                 -- Средняя цена открытия позиции по ФЬЮЧЕРСАМ
OPEN_DATE_FUT           = "";                -- Дата открытия позиции по ФЬЮЧЕРСАМ
 
-- Флаг для поддержания работы функции main
IsRun = true;
 
trans_id_OPT = nil;	-- ID заявки на опционы
OrderNum_OPT = nil; 	-- Номер заявки на опционы в торговой системе
trans_id_FUT = nil; 	-- ID заявки на фьючерс
OrderNum_FUT = nil; 	-- Номер заявки на фьючерс в торговой системе
 
-- Константы для строк таблицы
BUTTON_UP_FUTCODE_LINE     = 1;  -- Строка кнопки увеличения даты фьючерса
SEC_CODE_FUT_LINE          = 2;  -- Строка кода фьючерса
BUTTON_DOWN_FUTCODE_LINE   = 3;  -- Строка кнопки уменьшения даты фьючерса
                          -- 4;  -- Пустая строка
BUTTON_UP_STRIKE_LINE      = 5;  -- Строка кнопки увеличения значений страйка опциона
SEC_CODE_OPT_LINE          = 6;  -- Строка кода опциона
BUTTON_DOWN_STRIKE_LINE    = 7;  -- Строка кнопки уменьшения значений страйка опциона
                          -- 8;  -- Пустая строка
BUTTON_OPEN_LINE           = 9;  -- Строка с кнопкой "Открыть"
                          -- 10; -- Пустая строка
                          -- 11; -- Пустая строка
INFO_TITLE_LINE            = 12; -- Строка заголовков информации по позиции
OPT_PROFIT_LINE            = 13; -- Строка профита по опционам
FUT_PROFIT_LINE            = 14; -- Строка профита по фьючерсу
ALL_PROFIT_LINE            = 15; -- Строка суммарного профита
                          -- 16; -- Пустая строка
BUTTON_CLOSE_LINE          = 17; -- Строка с кнопкой "Закрыть"
 
-- Флаги возможности открытия/закрытия позиции
MayOpen = true;
MayClose = false;
 
STATE = nil;               -- Флаг текущего процесса ("OPEN"/"CLOSE")
 
trans_id_OPT = nil;        -- ID транзакции на покупку ОПЦИОНОВ
trans_id_FUT = nil;        -- ID транзакции на продажу ФЬЮЧЕРСА
 
NotBuy_OPT = true;         -- Флаг, что ОПЦИОНЫ еще не куплены
NotSell_OPT = true;        -- Флаг, что ОПЦИОНЫ еще не проданы
NotBuy_FUT = true;         -- Флаг, что ФЬЮЧЕРСЫ еще не куплены
NotSell_FUT = true;        -- Флаг, что ФЬЮЧЕРСЫ еще не проданы
OpenPosProcessed = false;  -- Флаг, что открытие позиций обработано
ClosePosProcessed = false; -- Флаг, что закрытие позиций обработано
 
OrderNum_OPT = nil;        -- Номер заявки на ОПЦИОНЫ в торговой системе
OrderNum_FUT = nil;        -- Номер заявки на ФЬЮЧЕРС в торговой системе
 
function OnInit()
   -- Пытается открыть лог-файл в режиме "чтения/записи"
   Log = io.open(getScriptPath().."//Log.txt","r+");
   -- Если файл не существует
   if Log == nil then
      -- Создает файл в режиме "записи"
      Log = io.open(getScriptPath().."//Log.txt","w");
      -- Закрывает файл
      Log:close();
      -- Открывает уже существующий файл в режиме "чтения/записи"
      Log = io.open(getScriptPath().."//Log.txt","r+");
   end;
   -- Встает в конец файла
   Log:seek("end",0);
   -- Добавляет пустую строку-разрыв
   Log:write("\n");Log:flush();
 
   -- Пытается открыть файл состояния в режиме "чтения/записи"
   local f = io.open(getScriptPath().."//State.txt","r+");
   -- Если файл существует
   if f ~= nil then
      -- Перебирает строки файла, считывает содержимое в соответствующие переменные
      local Count = 0; -- Счетчик строк
      for line in f:lines() do
         Count = Count + 1;
         if Count == 1 then SEC_CODE_FUT_FOR_OPEN = line;         -- Код ФЬЮЧЕРСА для открытия
         elseif Count == 2 then SEC_CODE_OPT_FOR_OPEN = line;     -- Код ОПЦИОНА для открытия
         elseif Count == 3 then SEC_CODE_OPT_IN_POS = line;       -- Код ОПЦИОНА в позиции
            -- ЕСЛИ есть открытая позиция, ТО разрешается закрывать позицию, ИНАЧЕ, разрешается открывать позицию
            if SEC_CODE_OPT_IN_POS ~= "" then
               MayOpen = false;
               MayClose = true;
               NotBuy_OPT = true;
               NotSell_FUT = true;
            else MayOpen = true; end;
         elseif Count == 4 then OPEN_BALANCE_OPT = tonumber(line);   -- Количество лотов в позиции по ОПЦИОНАМ
         elseif Count == 5 then OPEN_PRICE_OPT = tonumber(line);  -- Средняя цена открытия позиции по ОПЦИОНАМ
         elseif Count == 6 then OPEN_DATE_OPT = line;             -- Дата открытия позиции по ОПЦИОНАМ
         elseif Count == 7 then SEC_CODE_FUT_IN_POS = line;       -- Код ФЬЮЧЕРСА в позиции
         elseif Count == 8 then OPEN_BALANCE_FUT = tonumber(line);   -- Количество лотов в позиции по ФЬЮЧЕРСАМ
         elseif Count == 9 then OPEN_PRICE_FUT = tonumber(line);  -- Средняя цена открытия позиции по ФЬЮЧЕРСАМ
         elseif Count == 10 then OPEN_DATE_FUT = line;            -- Дата открытия позиции по ФЬЮЧЕРСАМ
         end;
      end;
      -- Закрывает файл
      f:close();
   end;
 
   -- Создает таблицу
   CreateTable();
   -- Назначает таблице t_id функцию обработки событий event_callback_message
   SetTableNotificationCallback(t_id, event_callback_message);
 
   -- Инициализирует генератор
   math.randomseed(os.date("*t",os.time()).sec); -- Инициализирует генератор псевдослучайных чисел параметром, каждый параметр порождает соответствующую (но одну и ту же) последовательность псевдослучайных чисел.
end;
 
function main()
   -- Цикл будет выполнятся, пока IsRun == true
   while IsRun do
 
   -- ЕСЛИ текущий процесс ОТКРЫТИЕ позиции и ОПЦИОНЫ куплены и ФЬЮЧЕРС продан и открытие позиций еще не обработано, ТО
   if STATE == "OPEN" and not NotBuy_OPT and not NotSell_FUT and not OpenPosProcessed then
      -- Функция обработки открытия позиций
      OpenPosProcess();
   end;
 
   -- ЕСЛИ текущий процесс ЗАКРЫТИЕ позиции и ОПЦИОНЫ проданы и ФЬЮЧЕРС куплен и закрытие позиций еще не обработано, ТО
   if STATE == "CLOSE" and not NotSell_OPT and not NotBuy_FUT and not ClosePosProcessed then
      -- Функция обработки закрытия позиций
      ClosePosProcess();
   end;
 
      sleep(100);
   end;
end;
 
-- Функция для записи в лог действий скрипта
function ToLog(str)
   local datetime = os.date("*t",os.time()); -- Текущие дата/время
   local sec_mcs_str = tostring(os.clock()); -- Секунды с микросекундами
   local mcs_str = string.sub(sec_mcs_str, sec_mcs_str:find("%.") + 1);   -- Микросекунды
   -- Записывает в лог-файл переданную строку, добавляя в ее начало время с точностью до микросекунд
   Log:write(tostring(datetime.day).."-"
            ..tostring(datetime.month).."-"
            ..tostring(datetime.year).." "
            ..tostring(datetime.hour)..":"
            ..tostring(datetime.min)..":"
            ..tostring(datetime.sec).."."
            ..mcs_str.." "
            ..str.."\n");  -- Записывает в лог-файл
   Log:flush();   -- Сохраняет изменения в лог-файле
end;
 
-- Функция ОТКРЫВАЕТ позицию
function OpenPosition()
   ToLog("OpenPosition"); -- Записывает в лог-файл
   -- Устанавливает флаг текущего процесса в ОТКРЫТИЕ позиции
   STATE = "OPEN";
   -- Сбрасывает флаг обработки открытия позиций
   OpenPosProcessed = false;
 
   trans_id_OPT = math.random(1,9999);
   ToLog("trans_id_OPT = "..tostring(trans_id_OPT)); -- Записывает в лог-файл
   -- Заполняет структуру для отправки транзакции на покупку 2-х ОПЦИОНОВ
   local Transaction={
      ["TRANS_ID"]   = tostring(trans_id_OPT),
      ["ACTION"]     = "NEW_ORDER",
      ["CLASSCODE"]  = CLASS_CODE_OPT,
      ["SECCODE"]    = SEC_CODE_OPT_FOR_OPEN,
      ["OPERATION"]  = "B", -- покупка (BUY)
      ["TYPE"]       = "M", -- по рынку (MARKET)
      ["QUANTITY"]   = "2", -- количество
      ["ACCOUNT"]    = TRADE_ACC,
      ["PRICE"]      = tostring(getParamEx(CLASS_CODE_OPT, SEC_CODE_OPT_FOR_OPEN, "offer").param_value + 10*getParamEx(CLASS_CODE_OPT, SEC_CODE_OPT_FOR_OPEN, "SEC_PRICE_STEP").param_value), -- по цене, завышенной на 10 мин. шагов цены
      ["COMMENT"]    = "Покупка опционов скриптом"
   }
   -- Флаг, что ОПЦИОНЫ еще не куплены
   NotBuy_OPT = true;
   local Result = sendTransaction(Transaction);
   ToLog("Заявка на покупку ОПЦИОНОВ отправлена"); -- Записывает в лог-файл
   ToLog("Result = "..Result); -- Записывает в лог-файл
   -- ЕСЛИ функция вернула строку диагностики ошибки, ТО значит транзакция не прошла
   if Result ~= "" then
      -- Выводит сообщение с ошибкой
      message("Покупка ОПЦИОНОВ не удалась!\nОШИБКА: "..Result);
      -- Завершает выполнение функции
      return(0);
   end;
 
   -- Генерирует случайный ID транзакции на продажу ФЬЮЧЕРСОВ
   trans_id_FUT = math.random(1,9999);
   ToLog("trans_id_FUT = "..tostring(trans_id_FUT)); -- Записывает в лог-файл
   -- Заполняет структуру для отправки транзакции на продажу ФЬЮЧЕРСОВ
   local Transaction={
      ["TRANS_ID"]   = tostring(trans_id_FUT),
      ["ACTION"]     = "NEW_ORDER",
      ["CLASSCODE"]  = CLASS_CODE_FUT,
      ["SECCODE"]    = SEC_CODE_FUT_FOR_OPEN,
      ["OPERATION"]  = "S", -- продажа (SELL)
      ["TYPE"]       = "M", -- по рынку (MARKET)
      ["QUANTITY"]   = "1", -- количество
      ["ACCOUNT"]    = TRADE_ACC,
      ["PRICE"]      = tostring(getParamEx(CLASS_CODE_FUT, SEC_CODE_FUT_FOR_OPEN, "bid").param_value - 10*getParamEx(CLASS_CODE_FUT, SEC_CODE_FUT_FOR_OPEN, "SEC_PRICE_STEP").param_value), -- по цене, заниженной на 10 мин. шагов цены
      ["COMMENT"]    = "Продажа фьючерсов скриптом"
   }
   -- Флаг, что ФЬЮЧЕРСЫ еще не проданы
   NotSell_FUT = true;
   local Result = sendTransaction(Transaction);
   ToLog("Заявка на продажу ФЬЮЧЕРСОВ отправлена"); -- Записывает в лог-файл
   ToLog("Result = "..Result); -- Записывает в лог-файл
   -- ЕСЛИ функция вернула строку диагностики ошибки, ТО значит транзакция не прошла
   if Result ~= "" then
      -- Выводит сообщение с ошибкой
      message("Продажа ФЬЮЧЕРСОВ не удалась!\nОШИБКА: "..Result);
      -- Завершает выполнение функции
      return(0);
   end;
end;
-- Функция ЗАКРЫВАЕТ позицию
function ClosePosition()
   ToLog("ClosePosition"); -- Записывает в лог-файл
   -- Устанавливает флаг текущего процесса  в ЗАКРЫТИЕ позиции
   STATE = "CLOSE";
   -- Сбрасывает флаг обработки закрытия позиций
   ClosePosProcessed = false;
 
   trans_id_OPT = math.random(1,9999);
   ToLog("trans_id_OPT = "..tostring(trans_id_OPT)); -- Записывает в лог-файл
   -- Заполняет структуру для отправки транзакции на продажу 2-х ОПЦИОНОВ
   local Transaction={
      ["TRANS_ID"]   = tostring(trans_id_OPT),
      ["ACTION"]     = "NEW_ORDER",
      ["CLASSCODE"]  = CLASS_CODE_OPT,
      ["SECCODE"]    = SEC_CODE_OPT_IN_POS,
      ["OPERATION"]  = "S", -- продажа (SELL)
      ["TYPE"]       = "M", -- по рынку (MARKET)
      ["QUANTITY"]   = "2", -- количество
      ["ACCOUNT"]    = TRADE_ACC,
      ["PRICE"]      = tostring(getParamEx(CLASS_CODE_OPT, SEC_CODE_OPT_FOR_OPEN, "bid").param_value - 10*getParamEx(CLASS_CODE_OPT, SEC_CODE_OPT_FOR_OPEN, "SEC_PRICE_STEP").param_value), -- по цене, заниженной на 10 мин. шагов цены
      ["COMMENT"]    = "Продажа опционов скриптом"
   }
   -- Флаг, что ОПЦИОНЫ еще не проданы
   NotSell_OPT = true;
   local Result = sendTransaction(Transaction);
   ToLog("Заявка на продажу ОПЦИОНОВ отправлена"); -- Записывает в лог-файл
   ToLog("Result = "..Result); -- Записывает в лог-файл
   -- ЕСЛИ функция вернула строку диагностики ошибки, ТО значит транзакция не прошла
   if Result ~= "" then
      -- Выводит сообщение с ошибкой
      message("Продажа ОПЦИОНОВ не удалась!\nОШИБКА: "..Result);
      -- Завершает выполнение функции
      return(0);
   end;
 
   -- Генерирует случайный ID транзакции на покупку ФЬЮЧЕРСОВ
   trans_id_FUT = math.random(1,9999);
   ToLog("trans_id_FUT = "..tostring(trans_id_FUT)); -- Записывает в лог-файл
   -- Заполняет структуру для отправки транзакции на покупку ФЬЮЧЕРСОВ
   local Transaction={
      ["TRANS_ID"]   = tostring(trans_id_FUT),
      ["ACTION"]     = "NEW_ORDER",
      ["CLASSCODE"]  = CLASS_CODE_FUT,
      ["SECCODE"]    = SEC_CODE_FUT_IN_POS,
      ["OPERATION"]  = "B", -- покупка (BUY)
      ["TYPE"]       = "M", -- по рынку (MARKET)
      ["QUANTITY"]   = "1", -- количество
      ["ACCOUNT"]    = TRADE_ACC,
      ["PRICE"]      = tostring(getParamEx(CLASS_CODE_FUT, SEC_CODE_FUT_FOR_OPEN, "offer").param_value + 10*getParamEx(CLASS_CODE_FUT, SEC_CODE_FUT_FOR_OPEN, "SEC_PRICE_STEP").param_value), -- по цене, завышенной на 10 мин. шагов цены
      ["COMMENT"]    = "Покупка фьючерсов скриптом"
   }
   -- Флаг, что ФЬЮЧЕРСЫ еще не куплены
   NotBuy_FUT = true;
   local Result = sendTransaction(Transaction);
   ToLog("Заявка на покупку ФЬЮЧЕРСОВ отправлена"); -- Записывает в лог-файл
   ToLog("Result = "..Result); -- Записывает в лог-файл
   -- ЕСЛИ функция вернула строку диагностики ошибки, ТО значит транзакция не прошла
   if Result ~= "" then
      -- Выводит сообщение с ошибкой
      message("Покупка ФЬЮЧЕРСОВ не удалась!\nОШИБКА: "..Result);
      -- Завершает выполнение функции
      return(0);
   end;
end;
-- Функция обработки открытия позиций
function OpenPosProcess()
   OPEN_BALANCE_OPT = 2;   -- Запоминает баланс позиции ОПЦИОНОВ
   OPEN_BALANCE_FUT = -1;  -- Запоминает баланс позиции ФЬЮЧЕРСОВ
 
   -- Получает среднюю цену позиции по ОПЦИОНАМ
   local LotSumOPT = 0; -- Общее количество лотов ОПЦИОНОВ в сделке(ах) по данной заявке
   local LotSumFUT = 0; -- Общее количество лотов ФЬЮЧЕРСОВ в сделке(ах) по данной заявке
   -- Бесконечный цикл, на случай, если информация о сделке придет позже
   while true do
      -- Обнуляет перед каждым новым проходом по таблице сделок
      OPEN_PRICE_OPT = 0;
      OPEN_PRICE_FUT = 0;
      LotSumOPT = 0;
      LotSumFUT = 0;
      -- Перебирает все строки в таблице сделок
      for i = 0,getNumberOf("TRADES") - 1 do
         -- ЕСЛИ сделка по ОПЦИОННОЙ заявке, ТО
         if getItem("TRADES",i).order_num == OrderNum_OPT then
            -- Считает сумму цен в сделках
            OPEN_PRICE_OPT = OPEN_PRICE_OPT + getItem("TRADES",i).price * getItem("TRADES",i).qty;
            -- Считает количество лотов в сделках
            LotSumOPT = LotSumOPT + getItem("TRADES",i).qty;
            -- Запоминает дату открытия позиции по ОПЦИОНАМ
            OPEN_DATE_OPT = tostring(getItem("TRADES",i).datetime.day).."-"..tostring(getItem("TRADES",i).datetime.month).."-"..tostring(getItem("TRADES",i).datetime.year);
         elseif getItem("TRADES",i).order_num == OrderNum_FUT then -- ЕСЛИ сделка по ФЬЮЧЕРСНОЙ заявке, ТО
            -- Считает сумму цен в сделках
            OPEN_PRICE_FUT = OPEN_PRICE_FUT + getItem("TRADES",i).price * getItem("TRADES",i).qty;
            -- Считает количество лотов в сделках
            LotSumFUT = LotSumFUT + getItem("TRADES",i).qty;
            -- Запоминает дату открытия позиции по ФЬЮЧЕРСАМ
            OPEN_DATE_FUT = tostring(getItem("TRADES",i).datetime.day).."-"..tostring(getItem("TRADES",i).datetime.month).."-"..tostring(getItem("TRADES",i).datetime.year);
         end;
      end;
      -- ЕСЛИ все лоты найдены в сделках по ОПЦИОННОЙ и ФЬЮЧЕРСНОЙ заявкам, ТО
      if LotSumOPT == math.abs(OPEN_BALANCE_OPT) and LotSumFUT == math.abs(OPEN_BALANCE_FUT) then
         ToLog("LotSumOPT = "..tostring(LotSumOPT).." LotSumFUT = "..tostring(LotSumFUT));
         -- Запоминает код ОПЦИОНА в позиции
         SEC_CODE_OPT_IN_POS = SEC_CODE_OPT_FOR_OPEN;
         -- Запоминает код ФЬЮЧЕРСА в позиции
         SEC_CODE_FUT_IN_POS = SEC_CODE_FUT_FOR_OPEN;
 
         -- Вычисляет среднюю цену по ОПЦИОНАМ
         OPEN_PRICE_OPT = OPEN_PRICE_OPT/math.abs(OPEN_BALANCE_OPT);
         -- Вычисляет среднюю цену по ФЬЮЧЕРСАМ
         OPEN_PRICE_FUT = OPEN_PRICE_FUT/math.abs(OPEN_BALANCE_FUT);
 
         -- Меняет флаги возможности открытия/закрытия позиции
         MayOpen = false;
         MayClose = true;
         -- Событие открытия позиций обработано
         OpenPosProcessed = true;
         -- Текущий процесс отсутствует
         STATE = nil;
 
         -- Выводит в таблицу новые данные
         SetCell(t_id, OPT_PROFIT_LINE, 2, tostring(OPEN_BALANCE_OPT));   SetCell(t_id, OPT_PROFIT_LINE, 3, tostring(OPEN_PRICE_OPT));   SetCell(t_id, OPT_PROFIT_LINE, 4, tostring(OPEN_DATE_OPT));
         SetCell(t_id, FUT_PROFIT_LINE, 2, tostring(OPEN_BALANCE_FUT));   SetCell(t_id, FUT_PROFIT_LINE, 3, tostring(OPEN_PRICE_FUT));   SetCell(t_id, FUT_PROFIT_LINE, 4, tostring(OPEN_DATE_FUT));
         -- Меняет подсветку кнопок
         Gray(BUTTON_OPEN_LINE, 1);
         Green(BUTTON_CLOSE_LINE, 1);
 
         break;   -- Завершает бесконечный цикл
      end;
      sleep(100);
   end;
end;
-- Функция обработки закрытия позиций
function ClosePosProcess()
   -- Обнуляет все флаги
   SEC_CODE_OPT_IN_POS     = "";                -- Код ОПЦИОНА в позиции
   OPEN_BALANCE_OPT        = 0;                 -- Баланс позиции по ОПЦИОНАМ
   OPEN_PRICE_OPT          = 0;                 -- Средняя цена открытия позиции по ОПЦИОНАМ
   OPEN_DATE_OPT           = "";                -- Дата открытия позиции по ОПЦИОНАМ
   SEC_CODE_FUT_IN_POS     = "";                -- Код ФЬЮЧЕРСА в позиции
   OPEN_BALANCE_FUT        = 0;                 -- Баланс позиции по ФЬЮЧЕРСАМ
   OPEN_PRICE_FUT          = 0;                 -- Средняя цена открытия позиции по ФЬЮЧЕРСАМ
   OPEN_DATE_FUT           = "";                -- Дата открытия позиции по ФЬЮЧЕРСАМ
 
   -- Меняет флаги возможности открытия/закрытия позиции
   MayOpen = true;
   MayClose = false;
 
   -- Событие открытия позиций обработано
   ClosePosProcessed = true;
   -- Текущий процесс отсутствует
   STATE = nil;
 
   -- Выводит в таблицу новые данные
   SetCell(t_id, OPT_PROFIT_LINE, 1, tostring(0)); SetCell(t_id, OPT_PROFIT_LINE, 2, tostring(OPEN_BALANCE_OPT)); SetCell(t_id, OPT_PROFIT_LINE, 3, tostring(OPEN_PRICE_OPT));   SetCell(t_id, OPT_PROFIT_LINE, 4, tostring(OPEN_DATE_OPT));
   SetCell(t_id, FUT_PROFIT_LINE, 1, tostring(0)); SetCell(t_id, FUT_PROFIT_LINE, 2, tostring(OPEN_BALANCE_FUT)); SetCell(t_id, FUT_PROFIT_LINE, 3, tostring(OPEN_PRICE_FUT));   SetCell(t_id, FUT_PROFIT_LINE, 4, tostring(OPEN_DATE_FUT));
   SetCell(t_id, ALL_PROFIT_LINE, 1, tostring(0));
   -- Меняет подсветку кнопок
   Green(BUTTON_OPEN_LINE, 1);
   Gray(BUTTON_CLOSE_LINE, 1);
end;
 
-- Функция обработки событий в таблице
function event_callback_message(t_id, msg, par1, par2)
   -- ЕСЛИ нажата кнопка "/\" для ФЬЮЧЕРСА, ТО
   if msg == QTABLE_LBUTTONUP and par1 == BUTTON_UP_FUTCODE_LINE and par2 == 1 then
      -- Получает символьную часть ФЬЮЧЕРСА (RIH->RIM->RIU->RIZ)
      local FutSecCode_STR = string.sub(SEC_CODE_FUT_FOR_OPEN, 1, 3);
      -- Получает числовую часть (0-9)
      local FutSecCode_NUM = tonumber(string.sub(SEC_CODE_FUT_FOR_OPEN, 4, 4));
      -- Увеличивает значение
      if FutSecCode_STR == "RIH" then FutSecCode_STR = "RIM";
      elseif FutSecCode_STR == "RIM" then FutSecCode_STR = "RIU";
      elseif FutSecCode_STR == "RIU" then FutSecCode_STR = "RIZ";
      elseif FutSecCode_STR == "RIZ" then
         FutSecCode_STR = "RIH";
         FutSecCode_NUM = FutSecCode_NUM + 1;
         if FutSecCode_NUM == 10 then FutSecCode_NUM = 0; end;
      end;
 
      -- Запоминает новое значение ФЬЮЧЕРСА для открытия
      SEC_CODE_FUT_FOR_OPEN = FutSecCode_STR..tostring(FutSecCode_NUM);
      -- Выводит новое значение ФЬЮЧЕРСА в таблицу
      SetCell(t_id, SEC_CODE_FUT_LINE, 1, SEC_CODE_FUT_FOR_OPEN.."      ");
 
      -- Подстраивает значение ОПЦИОНА под выбранный ФЬЮЧЕРС и запоминает его
      SEC_CODE_OPT_FOR_OPEN = string.sub(SEC_CODE_OPT_FOR_OPEN, 1, #SEC_CODE_OPT_FOR_OPEN - 1)..tostring(FutSecCode_NUM);
      -- Выводит новое значение ОПЦИОНА в таблицу
      SetCell(t_id, SEC_CODE_OPT_LINE, 1, SEC_CODE_OPT_FOR_OPEN);
   end;
 
   -- ЕСЛИ нажата кнопка "\/" для ФЬЮЧЕРСА, ТО
   if msg == QTABLE_LBUTTONUP and par1 == BUTTON_DOWN_FUTCODE_LINE and par2 == 1 then
      -- Получает текущее значение
      local FutSecCode = GetCell(t_id, SEC_CODE_FUT_LINE, 1);
      -- Получает символьную часть (RIH->RIM->RIU->RIZ)
      local FutSecCode_STR = string.sub(FutSecCode.image, 1, 3);
      -- Получает числовую часть (0-9)
      local FutSecCode_NUM = tonumber(string.sub(FutSecCode.image, 4, 4));
      -- Уменьшает значение
      if FutSecCode_STR == "RIZ" then FutSecCode_STR = "RIU";
      elseif FutSecCode_STR == "RIU" then FutSecCode_STR = "RIM";
      elseif FutSecCode_STR == "RIM" then FutSecCode_STR = "RIH";
      elseif FutSecCode_STR == "RIH" then
         FutSecCode_STR = "RIZ";
         FutSecCode_NUM = FutSecCode_NUM - 1;
         if FutSecCode_NUM == -1 then FutSecCode_NUM = 9; end;
      end;
 
      -- Запоминает новое значение ФЬЮЧЕРСА для открытия
      SEC_CODE_FUT_FOR_OPEN = FutSecCode_STR..tostring(FutSecCode_NUM);
      -- Выводит новое значение ФЬЮЧЕРСА в таблицу
      SetCell(t_id, SEC_CODE_FUT_LINE, 1, SEC_CODE_FUT_FOR_OPEN.."      ");
 
      -- Подстраивает значение ОПЦИОНА под выбранный ФЬЮЧЕРС и запоминает его
      SEC_CODE_OPT_FOR_OPEN = string.sub(SEC_CODE_OPT_FOR_OPEN, 1, #SEC_CODE_OPT_FOR_OPEN - 1)..tostring(FutSecCode_NUM);
      -- Выводит новое значение ОПЦИОНА в таблицу
      SetCell(t_id, SEC_CODE_OPT_LINE, 1, SEC_CODE_OPT_FOR_OPEN);
   end;
 
   -- ЕСЛИ нажата кнопка "/\" для ОПЦИОНА, ТО
   if msg == QTABLE_LBUTTONUP and par1 == BUTTON_UP_STRIKE_LINE and par2 == 1 then
      -- Получает цифры СТРАЙКА из кода ОПЦИОНА
      local OptSecCode_STRIKE = tonumber(string.sub(SEC_CODE_OPT_FOR_OPEN, 3, #SEC_CODE_OPT_FOR_OPEN - 3));
      -- Увеличивает СТРАЙК (здесь задан шаг 500, смотрите, чтобы такой опцион существовал!!!)
      OptSecCode_STRIKE = OptSecCode_STRIKE + 500;
 
      -- Подстраивает значение ОПЦИОНА, запоминает
      SEC_CODE_OPT_FOR_OPEN = string.sub(SEC_CODE_OPT_FOR_OPEN, 1, 2)..tostring(OptSecCode_STRIKE)..string.sub(SEC_CODE_OPT_FOR_OPEN, #SEC_CODE_OPT_FOR_OPEN - 2, #SEC_CODE_OPT_FOR_OPEN);
      -- Выводит новое значение ОПЦИОНА в таблицу
      SetCell(t_id, SEC_CODE_OPT_LINE, 1, SEC_CODE_OPT_FOR_OPEN);
   end;
 
   -- ЕСЛИ нажата кнопка "\/" для ОПЦИОНА, ТО
   if msg == QTABLE_LBUTTONUP and par1 == BUTTON_DOWN_STRIKE_LINE and par2 == 1 then
      -- Получает цифры СТРАЙКА из кода ОПЦИОНА
      local OptSecCode_STRIKE = tonumber(string.sub(SEC_CODE_OPT_FOR_OPEN, 3, #SEC_CODE_OPT_FOR_OPEN - 3));
      -- Уменьшает СТРАЙК (здесь задан шаг 500, смотрите, чтобы такой опцион существовал!!!)
      OptSecCode_STRIKE = OptSecCode_STRIKE - 500;
 
      -- Подстраивает значение ОПЦИОНА, запоминает
      SEC_CODE_OPT_FOR_OPEN = string.sub(SEC_CODE_OPT_FOR_OPEN, 1, 2)..tostring(OptSecCode_STRIKE)..string.sub(SEC_CODE_OPT_FOR_OPEN, #SEC_CODE_OPT_FOR_OPEN - 2, #SEC_CODE_OPT_FOR_OPEN);
      -- Выводит новое значение ОПЦИОНА в таблицу
      SetCell(t_id, SEC_CODE_OPT_LINE, 1, SEC_CODE_OPT_FOR_OPEN);
   end;
 
   -- ЕСЛИ нажата кнопка "Открыть", ТО
   if msg == QTABLE_LBUTTONUP and par1 == BUTTON_OPEN_LINE and par2 == 1 then
      -- ЕСЛИ нет возможности открыть позицию (уже открыта), ТО
      if not MayOpen then
         -- Выводит сообщение
         message("ЗАПРЕЩЕНО! Позиция уже открыта!!!", 3);
      else -- ИНАЧЕ
         -- Открывает позицию
         OpenPosition();
      end;
   end;
 
   -- ЕСЛИ нажата кнопка "Закрыть"
   if msg == QTABLE_LBUTTONUP and par1 == BUTTON_CLOSE_LINE and par2 == 1 then
      -- ЕСЛИ нет возможности закрыть позицию (еще не открыта), ТО
      if not MayClose then
         -- Выводит сообщение
         message("НЕВОЗМОЖНО! Позиция еще не открыта!!!", 3);
      else -- ИНАЧЕ
         -- Закрывает позицию
         ClosePosition();
      end;
   end;
end;
 
--- Функция создает таблицу
function CreateTable()
   -- Получает доступный id для создания
   t_id = AllocTable();
   -- Добавляет 5 колонок
   AddColumn(t_id, 0, "", true, QTABLE_STRING_TYPE, 24);
   AddColumn(t_id, 1, "", true, QTABLE_INT_TYPE, 15);
   AddColumn(t_id, 2, "", true, QTABLE_STRING_TYPE, 15);
   AddColumn(t_id, 3, "", true, QTABLE_STRING_TYPE, 15);
   AddColumn(t_id, 4, "", true, QTABLE_STRING_TYPE, 15);
   -- Создает таблицу
   t = CreateWindow(t_id);
   -- Устанавливает заголовок
   SetWindowCaption(t_id, "Открыть/закрыть +2 ОПЦИОНА -1 ФЬЮЧЕРС");
   -- Задает положение и размеры окна таблицы
   SetWindowPos(t_id, 100, 100, 472, 325);
   -- Добавляет строки
   InsertRow(t_id, BUTTON_UP_FUTCODE_LINE);  -- Строка кнопки увеличения даты фьючерса
   InsertRow(t_id, SEC_CODE_FUT_LINE);       -- Строка кода фьючерса
   InsertRow(t_id, BUTTON_DOWN_FUTCODE_LINE);-- Строка кнопки уменьшения даты фьючерса
   InsertRow(t_id, 4);                       -- Пустая строка
   InsertRow(t_id, BUTTON_UP_STRIKE_LINE);   -- Строка кнопки увеличения значений страйка опциона
   InsertRow(t_id, SEC_CODE_OPT_LINE);       -- Строка кода опциона
   InsertRow(t_id, BUTTON_DOWN_STRIKE_LINE); -- Строка кнопки уменьшения значений страйка опциона
   InsertRow(t_id, 8);                       -- Пустая строка
   InsertRow(t_id, BUTTON_OPEN_LINE);        -- Строка с кнопкой "Открыть"
   InsertRow(t_id, 10);                      -- Пустая строка
   InsertRow(t_id, 11);                      -- Пустая строка
   InsertRow(t_id, INFO_TITLE_LINE);         -- Строка заголовков информации по позиции
   InsertRow(t_id, OPT_PROFIT_LINE);         -- Строка профита по опционам
   InsertRow(t_id, FUT_PROFIT_LINE);         -- Строка профита по фьючерсу
   InsertRow(t_id, ALL_PROFIT_LINE);         -- Строка суммарного профита
   InsertRow(t_id, 16);                      -- Пустая строка
   InsertRow(t_id, BUTTON_CLOSE_LINE);       -- Строка с кнопкой "Закрыть"
   -- Добавляет значения в ячейки, окрашивает кнопки
                                                         SetCell(t_id, BUTTON_UP_FUTCODE_LINE, 1, "/\\         ");Green(BUTTON_UP_FUTCODE_LINE, 1);
   SetCell(t_id, SEC_CODE_FUT_LINE, 0, "Код ФЬЮЧЕРСА");  SetCell(t_id, SEC_CODE_FUT_LINE, 1, SEC_CODE_FUT_FOR_OPEN.."      ");
                                                         SetCell(t_id, BUTTON_DOWN_FUTCODE_LINE, 1, "\\/         ");Green(BUTTON_DOWN_FUTCODE_LINE, 1);
 
                                                         SetCell(t_id, BUTTON_UP_STRIKE_LINE, 1, "/\\         ");Green(BUTTON_UP_STRIKE_LINE, 1);
   SetCell(t_id, SEC_CODE_OPT_LINE, 0, "Код ОПЦИОНА");   SetCell(t_id, SEC_CODE_OPT_LINE, 1, SEC_CODE_OPT_FOR_OPEN);
                                                         SetCell(t_id, BUTTON_DOWN_STRIKE_LINE, 1, "\\/         ");Green(BUTTON_DOWN_STRIKE_LINE, 1);
 
                                                         SetCell(t_id, BUTTON_OPEN_LINE, 1, "ОТКРЫТЬ   ");
                                                         if MayOpen then Green(BUTTON_OPEN_LINE, 1);
                                                         else Gray(BUTTON_OPEN_LINE, 1);
                                                         end;
 
                                                         SetCell(t_id, INFO_TITLE_LINE, 1, "Профит");    SetCell(t_id, INFO_TITLE_LINE, 2, "Кол-во откр.");            SetCell(t_id, INFO_TITLE_LINE, 3, "Ср.цена поз.");             SetCell(t_id, INFO_TITLE_LINE, 4, "Дата откр.");
   SetCell(t_id, OPT_PROFIT_LINE, 0, "ОПЦИОНЫ");         SetCell(t_id, OPT_PROFIT_LINE, 1, tostring(0)); SetCell(t_id, OPT_PROFIT_LINE, 2, tostring(OPEN_BALANCE_OPT));   SetCell(t_id, OPT_PROFIT_LINE, 3, tostring(OPEN_PRICE_OPT));   SetCell(t_id, OPT_PROFIT_LINE, 4, tostring(OPEN_DATE_OPT));
   SetCell(t_id, FUT_PROFIT_LINE, 0, "ФЬЮЧЕРСЫ");        SetCell(t_id, FUT_PROFIT_LINE, 1, tostring(0)); SetCell(t_id, FUT_PROFIT_LINE, 2, tostring(OPEN_BALANCE_FUT));   SetCell(t_id, FUT_PROFIT_LINE, 3, tostring(OPEN_PRICE_FUT));   SetCell(t_id, FUT_PROFIT_LINE, 4, tostring(OPEN_DATE_FUT));
   SetCell(t_id, ALL_PROFIT_LINE, 0, "ИТОГО");           SetCell(t_id, ALL_PROFIT_LINE, 1, tostring(0));
 
                                                         SetCell(t_id, BUTTON_CLOSE_LINE, 1, "ЗАКРЫТЬ   ");
                                                         if MayClose then Green(BUTTON_CLOSE_LINE, 1);
                                                         else Gray(BUTTON_CLOSE_LINE, 1);
                                                         end;
 
end;
 
--- Функции по раскраске строк/ячеек таблицы
function Red(Line, Col)    -- Красный
   -- Если индекс столбца не указан, окрашивает всю строку
   if Col == nil then Col = QTABLE_NO_INDEX; end;
   SetColor(t_id, Line, Col, RGB(255,168,164), RGB(0,0,0), RGB(255,168,164), RGB(0,0,0));
end;
function Gray(Line, Col)   -- Серый
   -- Если индекс столбца не указан, окрашивает всю строку
   if Col == nil then Col = QTABLE_NO_INDEX; end;
   SetColor(t_id, Line, Col, RGB(200,200,200), RGB(0,0,0), RGB(200,200,200), RGB(0,0,0));
end;
function Green(Line, Col)  -- Зеленый
   -- Если индекс столбца не указан, окрашивает всю строку
   if Col == nil then Col = QTABLE_NO_INDEX; end;
   SetColor(t_id, Line, Col, RGB(165,227,128), RGB(0,0,0), RGB(165,227,128), RGB(0,0,0));
end;
 
--- Функция вызывается терминалом QUIK при получении новой заявки или при изменении параметров существующей заявки.
function OnOrder(order)
   -- ЕСЛИ текущий процесс ОТКРЫТИЕ позиции, ТО
   if STATE == "OPEN" then
      -- Если исполнилась заявка на покупку ОПЦИОНОВ
      if order.trans_id == trans_id_OPT and order.balance == 0 and NotBuy_OPT then
         ToLog("OnOrder");
         ToLog("trans_id = "..tostring(order.trans_id).." balance = "..tostring(order.balance).." order_num = "..tostring(order.order_num));
         -- Меняет значение флагов
         NotBuy_OPT = false;
         NotSell_OPT = true;
         ToLog("ОПЦИОНЫ куплены"); -- Записывает в лог-файл
         -- Запоминает номер заявки на опционы в торговой системе
         OrderNum_OPT = order.order_num;
      end;
 
      -- Если исполнилась заявка на продажу ФЬЮЧЕРСОВ
      if order.trans_id == trans_id_FUT and order.balance == 0 and NotSell_FUT then
         ToLog("OnOrder");
         ToLog("trans_id = "..tostring(order.trans_id).." balance = "..tostring(order.balance).." order_num = "..tostring(order.order_num));
         -- Меняет значение флага
         NotSell_FUT = false;
         NotBuy_FUT = true;
         ToLog("ФЬЮЧЕРСЫ проданы"); -- Записывает в лог-файл
         -- Запоминает номер заявки на фьючерсы в торговой системе
         OrderNum_FUT = order.order_num;
      end;
   elseif  STATE == "CLOSE" then -- ЕСЛИ текущий процесс ЗАКРЫТИЕ позиции, ТО
      -- Если исполнилась заявка на продажу ОПЦИОНОВ
      if order.trans_id == trans_id_OPT and order.balance == 0 and NotSell_OPT then
         ToLog("OnOrder");
         ToLog("trans_id = "..tostring(order.trans_id).." balance = "..tostring(order.balance).." order_num = "..tostring(order.order_num));
         -- Меняет значение флага
         NotSell_OPT = false;
         NotBuy_OPT = true;
         ToLog("ОПЦИОНЫ проданы"); -- Записывает в лог-файл
         -- Запоминает номер заявки на опционы в торговой системе
         OrderNum_OPT = order.order_num;
      end;
 
      -- Если исполнилась заявка на покупку ФЬЮЧЕРСОВ
      if order.trans_id == trans_id_FUT and order.balance == 0 and NotBuy_FUT then
         ToLog("OnOrder");
         ToLog("trans_id = "..tostring(order.trans_id).." balance = "..tostring(order.balance).." order_num = "..tostring(order.order_num));
         -- Меняет значение флага
         NotBuy_FUT = false;
         NotSell_FUT = true;
         ToLog("ФЬЮЧЕРСЫ куплены"); -- Записывает в лог-файл
         -- Запоминает номер заявки на фьючерсы в торговой системе
         OrderNum_FUT = order.order_num;
      end;
   end;
end;
 
-- Функция вызывается терминалом QUIK при изменении текущих параметров
function OnParam(class, sec)
   -- Если скрипт в позиции по ОПЦИОНАМ и изменение пришло по этому ОПЦИОНУ
   if OPEN_BALANCE_OPT ~= 0 and class == CLASS_CODE_OPT and sec == SEC_CODE_OPT_IN_POS then
      -- Получает текущий СПРОС(bid) по ОПЦИОНУ
      local OptBid =  tonumber(getParamEx(CLASS_CODE_OPT,  SEC_CODE_OPT_IN_POS, "bid").param_value);
 
      -- Считает текущий профит по ОПЦИОННОЙ позиции
      local OptProfit = (OptBid - OPEN_PRICE_OPT) * math.abs(OPEN_BALANCE_OPT) - COMMISSION * 2 * math.abs(OPEN_BALANCE_OPT);
      -- Выводит значение в таблицу
      SetCell(t_id, OPT_PROFIT_LINE, 1, tostring(OptProfit));
      -- Окрашивает строку в зависимости от профита
      if OptProfit < 0 then Red(OPT_PROFIT_LINE);
      elseif OptProfit == 0 then Gray(OPT_PROFIT_LINE);
      else Green(OPT_PROFIT_LINE);
      end;
 
      -- Считает ИТОГО
      local ProfitTotal = tonumber(GetCell(t_id, OPT_PROFIT_LINE, 1).image) + tonumber(GetCell(t_id, FUT_PROFIT_LINE, 1).image);
      -- Выводит значение в таблицу
      SetCell(t_id, ALL_PROFIT_LINE, 1, tostring(ProfitTotal));
      -- Окрашивает строку в зависимости от профита
      if ProfitTotal < 0 then Red(ALL_PROFIT_LINE);
      elseif ProfitTotal == 0 then Gray(ALL_PROFIT_LINE);
      else Green(ALL_PROFIT_LINE);
      end;
   end;
 
   -- Если скрипт в позиции по ФЬЮЧЕРСАМ и изменение пришло по этому ОПЦИОНУ
   if OPEN_BALANCE_FUT ~= 0 and class == CLASS_CODE_FUT and sec == SEC_CODE_FUT_IN_POS then
      -- Получает текущее ПРЕДЛОЖЕНИЕ(offer) по ФЬЮЧЕРСУ
      local FutOffer =  tonumber(getParamEx(CLASS_CODE_FUT,  SEC_CODE_FUT_IN_POS, "offer").param_value);
 
      -- Считает текущий профит по ФЬЮЧЕРСНОЙ позиции
      local FutProfit = (OPEN_PRICE_FUT - FutOffer) * math.abs(OPEN_BALANCE_FUT) - COMMISSION * 2 * math.abs(OPEN_BALANCE_FUT);
      -- Выводит значение в таблицу
      SetCell(t_id, FUT_PROFIT_LINE, 1, tostring(FutProfit));
      -- Окрашивает строку в зависимости от профита
      if FutProfit < 0 then Red(FUT_PROFIT_LINE);
      elseif FutProfit == 0 then Gray(FUT_PROFIT_LINE);
      else Green(FUT_PROFIT_LINE);
      end;
 
      -- Считает ИТОГО
      local ProfitTotal = tonumber(GetCell(t_id, OPT_PROFIT_LINE, 1).image) + tonumber(GetCell(t_id, FUT_PROFIT_LINE, 1).image);
      -- Выводит значение в таблицу
      SetCell(t_id, ALL_PROFIT_LINE, 1, tostring(ProfitTotal));
      -- Окрашивает строку в зависимости от профита
      if ProfitTotal < 0 then Red(ALL_PROFIT_LINE);
      elseif ProfitTotal == 0 then Gray(ALL_PROFIT_LINE);
      else Green(ALL_PROFIT_LINE);
      end;
   end;
end;
 
function OnStop()
-- Сохранение текущего состояния в файл
   -- Пытается открыть файл в режиме "чтения/записи"
   local f = io.open(getScriptPath().."//State.txt","r+");
   -- Если файл не существует
   if f == nil then
      -- Создает файл в режиме "записи"
      f = io.open(getScriptPath().."//State.txt","w");
      -- Закрывает файл
      f:close();
      -- Открывает уже существующий файл в режиме "чтения/записи"
      f = io.open(getScriptPath().."//State.txt","r+");
   end;
   -- Записывает в файл текущие состояния (каждое значение в новой строке)
   f:write(SEC_CODE_FUT_FOR_OPEN.."\n");     -- Код ФЬЮЧЕРСА для открытия
   f:write(SEC_CODE_OPT_FOR_OPEN.."\n");     -- Код ОПЦИОНА для открытия
   f:write(SEC_CODE_OPT_IN_POS.."\n");       -- Код ОПЦИОНА в позиции
   f:write(tostring(OPEN_BALANCE_OPT).."\n");-- Количество лотов в позиции по ОПЦИОНАМ
   f:write(tostring(OPEN_PRICE_OPT).."\n");  -- Средняя цена открытия позиции по ОПЦИОНАМ
   f:write(OPEN_DATE_OPT.."\n");             -- Дата открытия позиции по ОПЦИОНАМ
   f:write(SEC_CODE_FUT_IN_POS.."\n");       -- Код ФЬЮЧЕРСА в позиции
   f:write(tostring(OPEN_BALANCE_FUT).."\n");-- Количество лотов в позиции по ФЬЮЧЕРСАМ
   f:write(tostring(OPEN_PRICE_FUT).."\n");  -- Средняя цена открытия позиции по ФЬЮЧЕРСАМ
   f:write(OPEN_DATE_FUT.."\n");             -- Дата открытия позиции по ФЬЮЧЕРСАМ
   -- Сохраняет изменения в файле
   f:flush();
   -- Закрывает файл
   f:close();
 
   Log:close();
 
   IsRun = false;
end;

СКАЧАТЬ ДАННЫЙ СКРИПТ

Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!