Отладчик, статистика для теста робота и непонятный висяк, C++ интеграция

Страницы: 1
RSS
Отладчик, статистика для теста робота и непонятный висяк, C++ интеграция
 
Здравствуйте, помогите пожалуйста новичку со стартом.

1) Посоветуйте пожалуйста отладчик для Lua

2) Есть ли возможность загрузить данные за предыдущие, скажем 10 лет, для тренировки робота?

3) Как интегрировать Quik c C++, и как дебагинг делать?

4) У меня учебный Quik Junior, почему-то не получается выставить алго заявку, сообщений об ошибке тоже нет, отправляю транзакцию и ничего не происходит. Если кому не трудно посмотрите пожалуйста участок кода. Или может я должен что-то в квике настроить?
Собственно ничего не происходит после  sendTransaction(Transaction);



--[[ Простой MA-робот ©QuikLuaCSharp.ru
!!! ДЛЯ ИСПОЛЬЗОВАНИЯ ТОЛЬКО В ОБРАЗОВАТЕЛЬНЫХ ЦЕЛЯХ НА ДЕМО-СЧЕТЕ !!!

Робот торгует по 2-м простым(simple) скользящим средним (MA).
1.Если нет открытых роботом позиций выполняется следующий алгоритм:
  1.Если быстрая скользящая пересекает медленную снизу вверх и на текущей свече еще не открывались позиции, совершается покупка.
  2.Если быстрая скользящая пересекает медленную сверху вниз и на текущей свече еще не открывались позиции, совершается продажа.
2.Если открылась позиция, выставляется "Тэйк-профит и Стоп-лимит"
3.Робот ждет, пока закроется позичия по Стоп-лоссу, либо Тэйк-профиту, после чего переходит к пункту №1

Особенности:
1.Робот выводит в текстовых сообщениях информацию о ключевых моментах алгоритма, у всех его сообщений префикс "Простой MA-робот:".
2.Робот всегда находится в 1-м из 2-х состояний(ROBOT_STATE):'В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА'.
3.Если при выставлении заявки на продажу робот узнает, что операции шорт запрещены по данному инструменту, он больше не будет открывать шорт, только лонг.
4.Когда робот получает сигнал на открытие сделки, он совершает 10 попыток с прмежутками в 100 мс открыть позицию, если этого не удается, останавливает скрипт.
5.После открытия позиции робот совершает 10 попыток с прмежутками в 100 мс выставить Тэйк-профит и Стоп-лимит, а затем дождаться закрытия позиции,
 если этого не удается, останавливает скрипт.
6.Если стоп-заявка сработала, но позиция не закрылась в течении 10 секунд, пытается за 10 попыток принудительно закрыть позицию встречной сделкой.
 Если позицию удалось закрыть (даже принудительно), продолжает работать, иначе скрипт останавливается.
]]

--/*НАСТРАИВАЕМЫЕ ПАРАМЕТРЫ*/

ACCOUNT           = '11306';       -- Идентификатор счета
CLASS_CODE        = 'QJSIM';             -- Код класса
SEC_CODE          = 'SBER';               -- Код бумаги
INTERVAL          = INTERVAL_M1;          -- Таймфрейм графика (для построения скользящих)
SLOW_MA_PERIOD    = 12;                   -- ПЕРИОД МЕДЛЕННОЙ скользящей
SLOW_MA_SOURCE    = 'C';                  -- ИСТОЧНИК МЕДЛЕННОЙ скользящей [O - open, C - close, H - hi, L - low]
FAST_MA_PERIOD    = 4;                    -- ПЕРИОД БЫСТРОЙ скользящей
FAST_MA_SOURCE    = 'C';                  -- ИСТОЧНИК БЫСТРОЙ скользящей [O - open, C - close, H - hi, L - low]
STOP_LOSS         = 10;                   -- Размер СТОП-ЛОССА (в шагах цены)
TAKE_PROFIT       = 30;                   -- Размер ТЭЙК-ПРОФИТА (в шагах цены)

--/*РАБОЧИЕ ПЕРЕМЕННЫЕ РОБОТА (менять не нужно)*/
SEC_PRICE_STEP    = 0;                    -- ШАГ ЦЕНЫ ИНСТРУМЕНТА
SEC_NO_SHORT      = false;                -- Флаг, что по данному инструменту запрещены операции шорт
DS                = nil;                  -- Источник данных графика (DataSource)
ROBOT_STATE       ='В ПОИСКЕ ТОЧКИ ВХОДА';-- СОСТОЯНИЕ робота ['В ПРОЦЕССЕ СДЕЛКИ', либо 'В ПОИСКЕ ТОЧКИ ВХОДА']
trans_id          = os.time();            -- Задает начальный номер ID транзакций
trans_Status      = nil;                  -- Статус текущей транзакции из функции OnTransPeply
trans_result_msg  = '';                   -- Сообщение по текущей транзакции из функции OnTransPeply
CurrentDirect     = 'BUY';                -- Текущее НАПРАВЛЕНИЕ ['BUY', или 'SELL']
LastOpenBarIndex  =  0;                   -- Индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще одну позицию)

Run               = true;                 -- Флаг поддержания работы бесконечного цикла в main

-- Функция первичной инициализации скрипта (ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK в самом начале)
function OnInit()
  -- Получает доступ к свечам графика
  local Error = '';
  DS,Error = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL);
  -- Если график, к которому нужно подключиться не открыт в терминале, то данные заказываются с сервера, на их получение нужно время,
  -- по этому, рекомендуется добавлять вот такое ожидание, прежде, чем обращаться к DS:
  -- Ждет, пока данные будут получены с сервера (на случай, если такой график не открыт)
  while (Error == "" or Error == nil) and DS:Size() == 0 do sleep(1) end
  if Error ~= "" and Error ~= nil then message("Ошибка подключения к графику: "..Error) return end

  -- Подписывается на обновления графика
  DS:SetEmptyCallback()

  -- Получает ШАГ ЦЕНЫ ИНСТРУМЕНТА
  SEC_PRICE_STEP = getParamEx(CLASS_CODE, SEC_CODE, "SEC_PRICE_STEP").param_value;
end;

function main()
  -- Выводит сообщение
  message('Простой MA-робот: '..ROBOT_STATE);
  -- "Бесконечный" цикл
  while Run do
     --Если СОСТОЯНИЕ робота "В ПРОЦЕССЕ СДЕЛКИ"
     if ROBOT_STATE == 'В ПРОЦЕССЕ СДЕЛКИ' then
        -- Выводит сообщение
        message('Простой MA-робот: В ПРОЦЕССЕ СДЕЛКИ');
        -- Делает 10 попыток открыть сделку
        local Price = false; -- Переменная для получения результата открытия позиции (цена, либо ошибка(false))
        for i=1,10 do
           if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс
           -- Если первый раз пытается открыть SELL, а операции шорт по данному инструменту запрещены
           if CurrentDirect == "SELL" and SEC_NO_SHORT then
              -- Прерывает цикл FOR
              break;
           end;
           -- Совершает СДЕЛКУ указанного типа ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот,
           --- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку
           Price = Trade(CurrentDirect);
           -- Если сделка открылась
           if Price ~= false then
              -- Прерывает цикл FOR
              break;
           end;
           sleep(100); -- Пауза в 100 мс между попытками открыть сделку
        end;
        if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс
        -- Если сделка открыта
        if Price ~= false then
           -- Запоминает индекс свечи, на которой была открыта последняя позиция (нужен для того, чтобы после закрытия по стопу тут же не открыть еще одну позицию)
           LastOpenBarIndex = DS:Size();
           -- Выводит сообщение
           message('Простой MA-робот: Открыта сделка '..CurrentDirect..' по цене '..Price);
           -- Делает 10 попыток выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, и дождаться закрытия сделки
           message('Простой MA-робот: Делает 10 попыток выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, и дождаться закрытия сделки');
           local Result = nil; -- Переменная для получения результата выставления и срабатывания СТОП-ЛОСС и ТЭЙК-ПРОФИТ
           for i=1,10 do
              if not Run then return; end; -- Если скрипт останавливается, не затягивает процесс
              -- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ и ТИП ["BUY", или "SELL"] открытой сделки,
              --- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, или TRUE, если сделка закрылась,
              --- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию
              Result = SL_TP(Price, CurrentDirect);
              -- Если сделка закрылась
              if Result == true then
                 -- Прерывает цикл FOR
                 break;
              end;
           end;
           -- Если за 10 попыток не удалось закрыть позицию
           if Result == nil or Result == false then
              -- Выводит сообщение
              message('Простой MA-робот: После 10-и попыток не удалось закрыть сделку!!! Завершение скрипта!!!');
              -- Завершает выполнение скрипта
              Run = false;
              -- Прерывает основной цикл WHILE
              break;
           else -- УДАЛОСЬ ЗАКРЫТЬ СДЕЛКУ              
              -- Выводит сообщение
              message('Простой MA-робот: Сделка закрыта по СТОП-ЛОССУ, либо ТЭЙК-ПРОФИТУ');
              --Меняет СОСТОЯНИЕ робота на "В ПОИСКЕ ТОЧКИ ВХОДА"
              ROBOT_STATE = 'В ПОИСКЕ ТОЧКИ ВХОДА';
              -- Выводит сообщение
              message('Простой MA-робот: В ПОИСКЕ ТОЧКИ ВХОДА');
           end;
        else -- Сделку не удалось открыть
           -- Если первый раз пытался открыть SELL, а операции шорт по данному инструменту запрещены
           if CurrentDirect == "SELL" and SEC_NO_SHORT then
              -- Выводит сообщение
              message('Простой MA-робот: Была первая попытка совершить запрещенную операцию шорт! Больше этого не повторится:)');
              --Меняет СОСТОЯНИЕ робота на "В ПОИСКЕ ТОЧКИ ВХОДА"
              ROBOT_STATE = 'В ПОИСКЕ ТОЧКИ ВХОДА';
              -- Выводит сообщение
              message('Простой MA-робот: В ПОИСКЕ ТОЧКИ ВХОДА');
           else
              -- Выводит сообщение
              message('Простой MA-робот: После 10-и попыток не удалось открыть сделку!!! Завершение скрипта!!!');
              -- Завершает выполнение скрипта
              Run = false;
           end;
        end;
     else        
        -- СОСТОЯНИЕ робота 'В ПОИСКЕ ТОЧКИ ВХОДА'
        -- Если на этой свече еще не было открыто позиций
        if DS:Size() > LastOpenBarIndex then
           -- Если быстрая пересекла медленную СНИЗУ ВВЕРХ
           if FastMA(DS:Size()-1) <= SlowMA(DS:Size()-1) and FastMA() > SlowMA() then
              -- Задает направление НА ПОКУПКУ
              CurrentDirect = 'BUY';
              message('CurrentDirect = "BUY"');
              -- Меняет СОСТОЯНИЕ робота на "В ПРОЦЕССЕ СДЕЛКИ"
              ROBOT_STATE = 'В ПРОЦЕССЕ СДЕЛКИ';
           -- Если быстрая пересекла медленную СВЕРХУ ВНИЗ
           elseif FastMA(DS:Size()-1) >= SlowMA(DS:Size()-1) and FastMA() < SlowMA() then
              -- Если по данному инструменту не запрещены операции шорт
              if not SEC_NO_SHORT then
                 -- Задает направление НА ПРОДАЖУ
                 CurrentDirect = 'SELL';
                 message('CurrentDirect = "SELL"');
                 -- Меняет СОСТОЯНИЕ робота на "В ПРОЦЕССЕ СДЕЛКИ"
                 ROBOT_STATE = 'В ПРОЦЕССЕ СДЕЛКИ';
              end;
           end;
        end;
     end;
     sleep(10);--Пауза 10 мс, для того, чтобы не перегружать процессор компьютера
  end;
end;

-- Функция вызывается терминалом QUIK при получении ответа на транзакцию пользователя
function OnTransReply(trans_reply)
  -- Если поступила информация по текущей транзакции
  if trans_reply.trans_id == trans_id then
     -- Передает статус в глобальную переменную
     trans_Status = trans_reply.status;
     -- Передает сообщение в глобальную переменную
     trans_result_msg  = trans_reply.result_msg;
  end;
end;

-- Функция ВЫЗЫВАЕТСЯ ТЕРМИНАЛОМ QUIK при остановке скрипта
function OnStop()
  Run = false;
end;

-----------------------------
-- ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ --
-----------------------------

-- Совершает СДЕЛКУ указанного типа (Type) ["BUY", или "SELL"] по рыночной(текущей) цене размером в 1 лот,
--- возвращает цену открытой сделки, либо FALSE, если невозможно открыть сделку
function Trade(Type)
  --Получает ID транзакции
  trans_id = trans_id + 1;

  local Price = 0;
  local Operation = '';
  --Устанавливает цену и операцию, в зависимости от типа сделки и от класса инструмента
  if Type == 'BUY' then
     if CLASS_CODE ~= 'QJSIM' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'offer').param_value + 10*SEC_PRICE_STEP;end; -- по цене, завышенной на 10 мин. шагов цены
     Operation = 'B';
  else
     if CLASS_CODE ~= 'QJSIM' then Price = getParamEx(CLASS_CODE, SEC_CODE, 'bid').param_value - 10*SEC_PRICE_STEP;end; -- по цене, заниженной на 10 мин. шагов цены
     Operation = 'S';
  end;
message('point 1');
  -- Заполняет структуру для отправки транзакции
  local Transaction={
     ['TRANS_ID']   = tostring(trans_id),
     ['ACTION']     = 'NEW_ORDER',
     ['CLASSCODE']  = CLASS_CODE,
     ['SECCODE']    = SEC_CODE,
     ['OPERATION']  = Operation, -- операция ("B" - buy, или "S" - sell)
     --['TYPE']       = 'M', -- по рынку (MARKET)
     ['QUANTITY']   = '1', -- количество
     ['ACCOUNT']    = ACCOUNT,
     ['PRICE']      = tostring(Price),
     ['CLIENT_CODE']= 11306
  }
  -- Отправляет транзакцию
  sendTransaction(Transaction);
message('point 2');
  -- Ждет, пока получит статус текущей транзакции (переменные "trans_Status" и "trans_result_msg" заполняются в функции OnTransReply())
  while Run and trans_Status == nil do sleep(1); end;
  -- Запоминает значение
  local Status = trans_Status;
  -- Очищает глобальную переменную
  trans_Status = nil;
  -- Если транзакция не выполнена по какой-то причине
  if Status ~= 3 then
     -- Если данный инструмент запрещен для операции шорт
     if Status == 6 then
        -- Выводит сообщение
        message('Простой MA-робот: Данный инструмент запрещен для операции шорт!');
        SEC_NO_SHORT = true;
     else
        -- Выводит сообщение с ошибкой
        message('Простой MA-робот: Транзакция не прошла!\nОШИБКА: '..trans_result_msg);
     end;
     -- Возвращает FALSE
     return false;
  else --Транзакция отправлена
     local OrderNum = nil;
     --ЖДЕТ пока ЗАЯВКА на ОТКРЫТИЕ сделки будет ИСПОЛНЕНА полностью
     --Запоминает время начала в секундах
     local BeginTime = os.time();
     while Run and OrderNum == nil do
        --Перебирает ТАБЛИЦУ ЗАЯВОК
        for i=0,getNumberOf('orders')-1 do
           local order = getItem('orders', i);
           --Если заявка по отправленной транзакции ИСПОЛНЕНА ПОЛНОСТЬЮ
           if order.trans_id == trans_id and order.balance == 0 then
              --Запоминает номер заявки
              OrderNum  = order.order_num;
              --Прерывает цикл FOR
              break;
           end;
        end;
        --Если прошло 10 секунд, а заявка не исполнена, значит произошла ошибка
        if os.time() - BeginTime > 9 then
           -- Выводит сообщение с ошибкой
           message('Простой MA-робот: Прошло 10 секунд, а заявка не исполнена, значит произошла ошибка');
           -- Возвращает FALSE
           return false;
        end;
        sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера
     end;

     --ЖДЕТ пока СДЕЛКА ОТКРЫТИЯ позиции будет СОВЕРШЕНА
     --Запоминает время начала в секундах
     BeginTime = os.time();
     while Run do
        --Перебирает ТАБЛИЦУ СДЕЛОК
        for i=0,getNumberOf('trades')-1 do
           local trade = getItem('trades', i);
           --Если сделка по текущей заявке
           if trade.order_num == OrderNum then
              --Возвращает фАКТИЧЕСКУЮ ЦЕНУ открытой сделки
              return trade.price;
           end;
        end;
        --Если прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка
        if os.time() - BeginTime > 9 then
           -- Выводит сообщение с ошибкой
           message('Простой MA-робот: Прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка');
           -- Возвращает FALSE
           return false;
        end;
        sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера
     end;
  end;
end;

-- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ переданного типа (Type) ["BUY", или "SELL"]
function KillPos(Type)
  -- Дается 10 попыток
  local Count = 0; -- Счетчик попыток
  if Type == 'BUY' then
     -- Пока скрипт не остановлен и позиция не закрыта
     while Run and not Trade('SELL') do -- Открывает SELL, тем самым закрывая BUY, если Trade('SELL') вернет TRUE, цикл прекратится
        Count = Count + 1; -- Увеличивает счетчик
        -- Если за 10 попыток не удалось закрыть позицию
        if Count == 10 then
           -- Возвращает NIL
           return nil;
        end;
        sleep(100); -- Пауза 100 мс, чтобы изменилась ситуация на сервере
     end;
  else
     -- Пока скрипт не остановлен и позиция не закрыта
     while Run and not Trade('BUY') do -- Открывает BUY, тем самым закрывая SELL, если Trade('BUY') вернет TRUE, цикл прекратится
        Count = Count + 1; -- Увеличивает счетчик
        -- Если за 10 попыток не удалось закрыть позицию
        if Count == 10 then
           -- Возвращает NIL
           return nil;
        end;
        sleep(100); -- Пауза 100 мс, чтобы изменилась ситуация на сервере
     end;
  end;
  -- Возвращает TRUE, если удалось принудительно закрыть позицию
  return true;
end;

-- Выставляет СТОП-ЛОСС и ТЭЙК-ПРОФИТ, ЖДЕТ пока он сработает, принимает ЦЕНУ (Price) и ТИП (Type) ["BUY", или "SELL"] открытой сделки,
--- возвращает FALSE, если не удалось выставить СТОП-ЛОСС и ТЭЙК-ПРОФИТ, либо TRUE, если сделка закрылась,
--- либо NIL, если при ошибке за 10 попыток не удалось принудительно закрыть позицию
function SL_TP(Price, Type)
  -- ID транзакции
  trans_id = trans_id + 1;

-- Находит направление для заявки
local operation = "";
local price = "0"; -- Цена, по которой выставится заявка при срабатывании Стоп-Лосса (для рыночной заявки по акциям должна быть 0)
local stopprice = ""; -- Цена Тэйк-Профита
local stopprice2 = ""; -- Цена Стоп-Лосса
  local market = "YES"; -- После срабатывания Тэйка, или Стопа, заявка сработает по рыночной цене
-- Если открыт BUY, то направление стоп-лосса и тэйк-профита SELL, иначе направление стоп-лосса и тэйк-профита BUY
if Type == 'BUY' then
operation = "S"; -- Тэйк-профит и Стоп-лосс на продажу(чтобы закрыть BUY, нужно открыть SELL)
     -- Если не акции
     if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then
        price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMIN').param_value)); -- Цена выставляемой заявки после страбатывания Стопа минимально возможная, чтобы не проскользнуло
        market = "NO";  -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене
     end;
stopprice = tostring(Price + TAKE_PROFIT*SEC_PRICE_STEP); -- Уровень цены, когда активируется Тэйк-профит
stopprice2 = tostring(Price - STOP_LOSS*SEC_PRICE_STEP); -- Уровень цены, когда активируется Стоп-лосс
else -- открыт SELL
operation = "B"; -- Тэйк-профит и Стоп-лосс на покупку(чтобы закрыть SELL, нужно открыть BUY)
     -- Если не акции
if CLASS_CODE ~= 'QJSIM' and CLASS_CODE ~= 'TQBR' then
        price = tostring(math.floor(getParamEx(CLASS_CODE, SEC_CODE, 'PRICEMAX').param_value)); -- Цена выставляемой заявки после страбатывания Стопа максимально возможная, чтобы не проскользнуло
        market = "NO";  -- После срабатывания Тэйка, или Стопа, заявка сработает НЕ по рыночной цене
     end;
stopprice = tostring(Price - TAKE_PROFIT*SEC_PRICE_STEP); -- Уровень цены, когда активируется Тэйк-профит
stopprice2 = tostring(Price + STOP_LOSS*SEC_PRICE_STEP); -- Уровень цены, когда активируется Стоп-лосс
end;
-- Заполняет структуру для отправки транзакции на Стоп-лосс и Тэйк-профит
local Transaction = {
["ACTION"]              = "NEW_STOP_ORDER", -- Тип заявки
["TRANS_ID"]            = tostring(trans_id),
["CLASSCODE"]           = CLASS_CODE,
["SECCODE"]             = SEC_CODE,
["ACCOUNT"]             = ACCOUNT,
["OPERATION"]           = operation, -- Операция ("B" - покупка(BUY), "S" - продажа(SELL))
["QUANTITY"]            = "1", -- Количество в лотах
["PRICE"]               = price, -- Цена, по которой выставится заявка при срабатывании Стоп-Лосса (для рыночной заявки по акциям должна быть 0)
["STOPPRICE"]           = stopprice, -- Цена Тэйк-Профита
["STOP_ORDER_KIND"]     = "TAKE_PROFIT_AND_STOP_LIMIT_ORDER", -- Тип стоп-заявки
["EXPIRY_DATE"]         = "TODAY", -- Срок действия стоп-заявки ("GTC" – до отмены,"TODAY" - до окончания текущей торговой сессии, Дата в формате "ГГММДД")
     -- "OFFSET" - (ОТСТУП)Если цена достигла Тэйк-профита и идет дальше в прибыль,
     -- то Тэйк-профит сработает только когда цена вернется минимум на 2 шага цены назад,
     -- это может потенциально увеличить прибыль
["OFFSET"]              = tostring(2*SEC_PRICE_STEP),
["OFFSET_UNITS"]        = "PRICE_UNITS", -- Единицы измерения отступа ("PRICE_UNITS" - шаг цены, или "PERCENTS" - проценты)
     -- "SPREAD" - Когда сработает Тэйк-профит, выставится заявка по цене хуже текущей на 100 шагов цены,
     -- которая АВТОМАТИЧЕСКИ УДОВЛЕТВОРИТСЯ ПО ТЕКУЩЕЙ ЛУЧШЕЙ ЦЕНЕ,
     -- но то, что цена значительно хуже, спасет от проскальзывания,
     -- иначе, сделка может просто не закрыться (заявка на закрытие будет выставлена, но цена к тому времени ее уже проскочит)
["SPREAD"]              = tostring(100*SEC_PRICE_STEP),
["SPREAD_UNITS"]        = "PRICE_UNITS", -- Единицы измерения защитного спрэда ("PRICE_UNITS" - шаг цены, или "PERCENTS" - проценты)
     -- "MARKET_TAKE_PROFIT" = ("YES", или "NO") должна ли выставится заявка по рыночной цене при срабатывании Тэйк-Профита.
     -- Для рынка FORTS рыночные заявки, как правило, запрещены,
     -- для лимитированной заявки на FORTS нужно указывать заведомо худшую цену, чтобы она сработала сразу же, как рыночная
["MARKET_TAKE_PROFIT"]  = market,
["STOPPRICE2"]          = stopprice2, -- Цена Стоп-Лосса
["IS_ACTIVE_IN_TIME"]   = "NO",
     -- "MARKET_TAKE_PROFIT" = ("YES", или "NO") должна ли выставится заявка по рыночной цене при срабатывании Стоп-Лосса.
     -- Для рынка FORTS рыночные заявки, как правило, запрещены,
     -- для лимитированной заявки на FORTS нужно указывать заведомо худшую цену, чтобы она сработала сразу же, как рыночная
["MARKET_STOP_LIMIT"]   = market,
["CLIENT_CODE"]         = "Простой MA-робот ТЭЙК-ПРОФИТ и СТОП-ЛОСС"
}
  -- Отправляет транзакцию на установку ТЭЙК-ПРОФИТ и СТОП-ЛОСС
sendTransaction(Transaction);  
  -- Ждет, пока не получит статус текущей транзакции (переменные "trans_Status" и "trans_result_msg" заполняются в функции OnTransReply())
  while Run and trans_Status == nil do sleep(10); end;
  -- Запоминает значение
  local Status = trans_Status;
  -- Очищает глобальную переменную
  trans_Status = nil;
  -- Если транзакция не выполнена по какой-то причине
  if Status ~= 3 then
     -- Выводит сообщение с ошибкой
     message('Простой MA-робот: Установка ТЭЙК-ПРОФИТ и СТОП-ЛОСС не удалась!\nОШИБКА: '..trans_result_msg);
     -- Возвращает FALSE
     return false;
  else
     -- Выводит сообщение
     message('Простой MA-робот: ВЫСТАВЛЕНА заявка ТЭЙК-ПРОФИТ и СТОП-ЛОСС: '..trans_id);
     local OrderNum_CLOSE = nil;
     -- ЖДЕТ пока СТОП-ЗАЯВКА на СТОП-ЛОСС и ТЭЙК-ПРОФИТ будет ИСПОЛНЕНА полностью
     while Run and OrderNum_CLOSE == nil do
        -- Перебирает ТАБЛИЦУ СТОП-ЗАЯВОК
        for i=0,getNumberOf("stop_orders")-1 do
           local stop_order = getItem("stop_orders", i);
           -- Если заявка по текущей транзакции СТОП-ЛОСС и ТЭЙК-ПРОФИТ
           if stop_order.trans_id == trans_id then
              -- Если заявка по отправленной СТОП-ЛОСС и ТЭЙК-ПРОФИТ транзакции ИСПОЛНЕНА ПОЛНОСТЬЮ
              if stop_order.balance == 0 then
                 -- Если по наступлению стоп-цены выставлена заявка
                 if stop_order.linkedorder > 0 then
                    -- Запоминает номер заявки, которая была создана при срабатывании СТОП-ЛОСС, или ТЭЙК-ПРОФИТ
                    OrderNum_CLOSE  = stop_order.linkedorder;
                    -- Прерывает цикл FOR
                    break;
                 -- Стоп-заявка сработала, но была отвергнута торговой системой
                 elseif CheckBit(stop_order.flags, 10) == 1 then
                    -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ и выходит из функции
                    return KillPos(Type);
                 end;
              end;
           end;
        end;
        sleep(10); -- Пауза 10 мс, чтобы не перегружать процессор компьютера
     end;
     --ЖДЕТ пока СДЕЛКА ЗАКРЫТИЯ позиции будет СОВЕРШЕНА
     --Запоминает время начала в секундах
     BeginTime = os.time();
     while Run do
        --Перебирает ТАБЛИЦУ СДЕЛОК
        for i=0,getNumberOf("trades")-1 do
           local trade = getItem("trades", i);
           --Если сделка по текущей заявке на СТОП-ЛОСС и ТЭЙК-ПРОФИТ
           if trade.order_num == OrderNum_CLOSE then
              -- Возвращает TRUE
              return true;
           end;
        end;
        --Если прошло 10 секунд, а сделка не совершена, значит на демо-счете произошла ошибка сервера "Обработка кросс-заявок блокирована"
        if os.time() - BeginTime > 9 then
           -- ПРИНУДИТЕЛЬНО ЗАКРЫВАЕТ ОТКРЫТУЮ ПОЗИЦИЮ и выходит из функции
           return KillPos(Type);
        end;
        sleep(1);
     end;
  end;
end;

-- Возвращает ЗНАЧЕНИЕ МЕДЛЕННОЙ скользящей по индексу свечи (по умолчанию: последняя)
function SlowMA(Index)
  -- Если индекс свечи не указан, то устанавливает индекс последней свечи
  if Index == nil then Index = DS:Size(); end;
  -- Сумма значений SLOW_MA_SOURCE на SLOW_MA_PERIOD свечах
  local Sum = 0;
  -- Перебирает последние SLOW_MA_PERIOD свечей
  for i=Index, Index - (SLOW_MA_PERIOD - 1), -1 do      
     -- Считает сумму, исходя из выбранного источника для медленной скользящей
     if SLOW_MA_SOURCE == 'O' then
        Sum = Sum + DS:O(i);
     elseif SLOW_MA_SOURCE == 'C' then
        Sum = Sum + DS:C(i);
     elseif SLOW_MA_SOURCE == 'H' then
        Sum = Sum + DS:H(i);
     elseif SLOW_MA_SOURCE == 'L' then
        Sum = Sum + DS:L(i);
     else
        message('Простой MA-робот:ОШИБКА! Не верно указан источник для медленной скользящей!');
        -- Останавливает скрипт
        OnStop();
     end;
  end;
  -- Возвращает значение
  return Sum/SLOW_MA_PERIOD;
end;
-- Возвращает ЗНАЧЕНИЕ БЫСТРОЙ скользящей по индексу свечи (по умолчанию: последняя)
function FastMA(Index)
  -- Если индекс свечи не указан, то устанавливает индекс последней свечи
  if Index == nil then Index = DS:Size(); end;
  -- Сумма значений FAST_MA_SOURCE на FAST_MA_PERIOD свечах
  local Sum = 0;
  -- Перебирает последние FAST_MA_PERIOD свечей
  for i=Index, Index - (FAST_MA_PERIOD - 1), -1 do
     -- Считает сумму, исходя из выбранного источника для быстрой скользящей
     if FAST_MA_SOURCE == 'O' then
        Sum = Sum + DS:O(i);
     elseif FAST_MA_SOURCE == 'C' then
        Sum = Sum + DS:C(i);
     elseif FAST_MA_SOURCE == 'H' then
        Sum = Sum + DS:H(i);
     elseif FAST_MA_SOURCE == 'L' then
        Sum = Sum + DS:L(i);
     else
        message('Простой MA-робот:ОШИБКА! Не верно указан источник для быстрой скользящей!');
        -- Останавливает скрипт
        OnStop();
     end;
  end;
  -- Возвращает значение
  return Sum/FAST_MA_PERIOD;
end;

-- Функция возвращает значение бита (число 0, или 1) под номером bit (начинаются с 0) в числе flags, если такого бита нет, возвращает nil
function CheckBit(flags, bit)
  -- Проверяет, что переданные аргументы являются числами
  if type(flags) ~= "number" then error("Предупреждение!!! Checkbit: 1-й аргумент не число!"); end;
  if type(bit) ~= "number" then error("Предупреждение!!! Checkbit: 2-й аргумент не число!"); end;
  local RevBitsStr  = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags)
  local Fmod = 0; -- Остаток от деления
  local Go = true; -- Флаг работы цикла
  while Go do
     Fmod = math.fmod(flags, 2); -- Остаток от деления
     flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления
     RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления
     if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл
  end;
  -- Возвращает значение бита
  local Result = RevBitsStr :sub(bit+1,bit+1);
  if Result == "0" then return 0;
  elseif Result == "1" then return 1;
  else return nil;
  end;
end;
 
Цитата
Denis написал:
Собственно ничего не происходит после  sendTransaction(Transaction);
Добрый день.
Анализируйте результат работы функции sendTransaction(), т.к. некоторые проверки выполняются на стороне терминала Quik в момент отправки транзакции и ожидать OnTransReply() в этом случае нет смысла, т.к. транзакция не отправляется на сервер Quik. Вот пример обработки результата работы функции sendTransaction():
Код
result = sendTransaction(transaction)

if result ~= "" then
  message(string.format("Транзакция %s не прошла проверку на стороне терминала QUIK [%s]", transaction.TRANS_ID, result))
else
  message(string.format("Транзакция %s отправлена", transaction.TRANS_ID))
end
Более подробная информация есть в официальном мануале (см. ссылку у меня в подписи)
Перед тем как задать вопрос, убедитесь, что решение Вашей задачи не описано в официальном мануале - 'Использование Lua в Рабочем месте QUIK.pdf' https://arqatech.com/upload/Public/quik_lua.zip
 
Пытаюсь запустить test_trans из указанного мануала, используя номер клиентского счета из регистрационного мейла, но получаю сообщения

Вам запрещена торговля по указанному счету.
 
Цитата
Denis написал:
Пытаюсь запустить test_trans из указанного мануала, используя номер клиентского счета из регистрационного мейла, но получаю сообщения

Вам запрещена торговля по указанному счету.


Для начала рекомендуем вообще забыть про программирование и разобраться с тем какие именно параметры транзакций надо использовать.
Для этого через обычный терминал QUIK отправьте нужную Вам транзакцию.
Если транзакция успешно выполнится, значит в коде Вы указали не те параметры. Посмотрите в терминале какие нужно указать.
Если будет та же ошибка, значит нужно разбираться с настройками на стороне сервера.
 
Цитата
Denis написал:
Пытаюсь запустить test_trans из указанного мануала, используя номер клиентского счета из регистрационного мейла, но получаю сообщения
Не совсем понимаю про какой test_trans Вы имеете ввиду.
Сергей Вам правильно рекомендует сначала добиться выставления необходимой транзакции через интерфейс терминала Quik, а далее уже с такими же параметрами пытаться подать транзакцию из QLua.
Как посмотреть все параметры транзакции через таблицу Карман транзакций так же рассказано в мануале.
Перед тем как задать вопрос, убедитесь, что решение Вашей задачи не описано в официальном мануале - 'Использование Lua в Рабочем месте QUIK.pdf' https://arqatech.com/upload/Public/quik_lua.zip
 
Вы в одну кучу свалили множество самостоятельных задачи и пытаетесь их разом решить.
их надо решать последовательно и независимо друг от друга.
Тогда решите за обозримое будущее и с меньшими потерями.
==========
QLUA  -это лишь библиотека  для VM Lua
----------------------
В  своем посте вы обозначили следующие задачи:
1) Изучение языка луа
2) изучение API С для lua
3) оболочка API C для C++
4) изучение функций библиотеки QLua
5) методы исследования рынков
6)  методы построения систем реального времени  обработки сигналов
------------
Подумайте над этим
 
Цитата
Николай Камынин написал:
6)  методы построения систем реального времени  обработки сигналов
прям реального? :)

запугали бедолагу ... а зря - эдак всех распугаете и на завод идти придется :)
 
Цитата
новичок написал:
запугали бедолагу ... а зря - эдак всех распугаете и на завод идти придется :)
Так ему и надо запугать клиента. А потом широким жестом предложить свои услуги :)
 
Цитата
Imersio Arrigo написал:
Цитата
новичок написал:
запугали бедолагу ... а зря - эдак всех распугаете и на завод идти придется :)
Так ему и надо запугать клиента. А потом широким жестом предложить свои услуги :)
а...а, точно.
поторопился. был неправ.  
 
Спасибо всем за подсказки, простенький робот запустил. Как dll на C++ подключить, тоже понятно.
У меня только один вопрос остался, мне для теста робота нужны данные, ну скажем за 10 лет (в приближении что мой робот никакого влияния на рынок не оказывает), как их можно заполучить?  
 
Цитата
Denis написал:
нужны данные
это как - "нужна обувь - что посоветуете?"
 
Цитата
новичок написал:
это как - "нужна обувь - что посоветуете?"
Не понял шутки...совета я не спрашивал.
Вопрос вполне конкретный к разработчикам терминала, есть ли возможность не в реалтайме получать моделирование (или что там на демо счете), а прогнать данные торгов, ну скажем фьючерс сбер или ртс за предыдущие годы. Интересует тесты робота и нейронной сети.
 

Какие именно данные нужны? Список всех сделок или нарезка на временные промежутки (к примеру, 5 минутки, дневки и т.п.)

Данные получить можно несколькими способами. Везде куча нюансов.
1. Скачать с финама (https://www.finam.ru/profile/moex-akcii/gazprom/export/). Тут есть и сделки, и временные "нарезки". Общий совет - чем больше объем данных, тем меньше выбирайте временной промежуток запроса. Т.е. сделки лучше скачивать отдельными запросами по каждому торговому дню. 5-ти минутки, например, можно сразу забрать отдельными запросами по годам. А "дневки", думаю, можно сразу запрашивать за несколько лет.
2. Использовать ИСС Московской биржи https://www.moex.com/a2193. Можно получить и сделки по дням и свечи. Что-то бесплатно, что-то за деньги. Есть ограничения по глубине данных (возможно только для бесплатных вариантов, платные не пробовал).
3. http://export.rbc.ru/ - тут можно получить бесплатно только дневные данные, но есть валютные пары и международные индексы и т.п.

Конкретно по фьючам с московской биржи, проще и быстрее скачать данные с финама. Там есть уже склеенные варианты:
https://www.finam.ru/profile/mosbirzha-fyuchersy/rts/export/?market=14&em=17455&code=RTS&apply=0&df=15&mf=5&yf=2019&from=15.06.2019&dt=15&mt=5&yt=2019&to=15.06.2019&p=7&f=RTS_190615_190615&e=.txt&cn=RTS&dtf=1&tmf=1&MSOR=1&mstime=on&mstimever=1&sep=1&sep2=1&datf=1&at=1

 
Цитата
Denis написал:
Вопрос вполне конкретный
морозите глупости Вы конкретно

https://www.moex.com/ru/orders?historicaldata

"учиться, учиться и еще раз учиться ..." (с)
 
Цитата
Алексей Ч написал:
Список всех сделок или нарезка на временные промежутки
точнее сказать: реально состоявшиеся события или взгляд из-за угла раз в 1, 5, 15 мин. :)
 
Алексей Ч, спасибо, то что нужно!
Страницы: 1
Читают тему
Наверх