finstrateg
finstrateg личный блог
22 мая 2016, 19:01

Открытый Универсальный Робот – Основа робота

Продолжаем разработку универсального робота!

Выкладываю код OUR-0.3, который в настоящий момент еще далеко не полный – это только основа, скачать можно здесь https://yadi.sk/d/l3uic67yruCxa

Код прокомментирован подробно, но дам дополнительное описание общего плана, чтобы логику работы робота можно было представить.

Итак, по порядку:

Робот состоит из двух файлов: OUR.lua содержит основные функции (OnInit, main, коолбэки – пока только один OnStop), FunOUR.lua содержит вспомогательные функции – все остальные. Дополнительно приложен файл с информацией и файл с образцом котировок.

Функция OnInit

1 Первоначально котировки с сервера поступают в источник – таблицу с барами TBar (там все заполняется автоматически при подключении источника).

2 Далее робот делает различные вычисления, результаты которых он помещает в таблицу с данными TDat (также туда копируются параметры баров из TBar), эту таблицу нужно заполнять самому, ключи таблицы на свое усмотрение, но конечно часть ключей в алгоритм уже заложены, это «key»,«O»,«H»,«L»,«C»,«V»,«T» от них идут все вычисления. TDat – это таблица, содержащая таблицы по каждому бару, ключ соответствует номеру бара в источнике. Структура такого типа:

TDat = {
[1321] = {"O","H","L","C","SMAf","SMAs"…},
[1322] = {"O","H","L","C","SMAf","SMAs"…},
…
}

Робот на каждом шаге смотрит индекс последнего бара в таблице TBar и проверяет проведены для него вычисления в таблице TDat или нет, в зависимости от этого делает необходимые вычисления.

3 Задаваемые значения (типа периодов индикаторов, настроек робота и т.п.) помещаются в таблицу значений TVal. Ниже вызывается фунция funVal, которая дополняет таблицу значений – сделал, чтобы задавать значения, касающиеся моей личной стратегии – так удобней, в открытой версии функция пуста).

4 Таблица TSrv – содержит время сервера в трех форматах, в коде все описано. Таблица TStm содержит параметры сигналов времени – последовательно разбиваете сутки на периоды (начиная от 00:00:00), в которые указываете, что можно делать роботу, сигналы расписаны в файле с информацией (можно добавлять дополнительно строки, но надо чтобы время шло последовательно – разнобой пока не обрабатывается). Время и дата в роботе представляется в 3-х видах: обычная текстовая строка (стараюсь в имени переменной добавлять префикс St), таблица формата DateTime (стараюсь в имени переменной добавлять префикс DT), целое число формата Posix – количество секунд прошедшее с какой-то даты (стараюсь в имени переменной добавлять префикс Px). Префиксы кажется есть везде, кроме Bar:T(i) (здесь DateTime по умолчанию создает квик) и Dat[i].T (здесь не стал менять традицию и использую обозначение T, но формат Posix).

5 Таблица TSec содержит параметры инструмента, вероятно в ней же будут помещаться параметры позиций, так как они относятся к инструменту.

6 Во вспомогательных функциях имена указанных таблиц представляются без буквы «T», ну и по тексту могу где-то «T» не указывать. Имена вспомогательных функций начинаются с символов Fun…

Функция main

1 Сначала подключаем источник данных, потом делаем проверки, далее идет основной цикл робота, который «крутится» с заданной задержкой.

2 Внутри цикла робот определяет количество баров в источнике данных TVal.N и вызывает две функции – одна осуществляет расчет на истории FunCompleted (рассчитывает каждый бар до текущего незавершенного бара), другая осуществляет расчет только для текущего бара FunCurrent. В этих функциях никакой код менять не надо, но они вызывают другие 4 функции (FunNewBar1, FunNewBar2, FunOldBar1, FunOldBar2) в которые и нужно вносить необходимый вам код.

3 Указанные функции выполняют следующее (после окончания паузы конечно):

FunNewBar1 – выполняется один раз при появлении нового незавершенного текущего бара (например, если торговля будет вестись от цены открытия бара, то расчеты надо делать в этой функции).

FunNewBar2 – выполняется каждый раз при снятии с паузы для незавершенного текущего бара (если необходимо что-то контролировать постоянно – с максимальной скоростью, например стакан, то это надо делать в этой функции).

FunOldBar1 – выполняется всего один раз при запуске робота для вычисления предистории (при вычислениях часто идет обращение к вычислениям на предыдущих барах, поэтому при начале вычислений на первых барах истории надо задать значения к которым будет обращаться робот — предистория, обычно хотя бы нули, чтобы у робота алгоритм сошелся, здесь это и задается). Количество баров предистории задается параметром TVal.Hpre – обычно это как минимум 1 бар.

FunOldBar2 – выполняется один раз для каждого бара на истории и для только что завершенного текущего бара. Когда текущий бар завершается, то он становится историей и для него один раз вызывается эта функция. Количество баров истории, для которых надо все рассчитать задается параметром TVal.H – обычно это количество, необходимое для того, чтобы все сигналы стратегии адекватно определились. Если торговать по завершенным барам, то основной алгоритм надо расположить в этой функции – это кстати будет и наш случай наверное, будем осуществлять анализ по закрытым барам (но это еще обсудим).

В функциях параметр i – это номер бара для которого проводится вычисление – бар для которого вызвана функция. Функции для каждого бара, если выполняются условия требующие вызова и описанные выше, вызываются автоматически, при написании кода не надо беспокоиться о вызове, надо просто оперировать индексом бара i для которого вызвана функция.

4 Еще есть параметр TVal.Hplus – он задает количество баров на которые растягивается «хвост» индикаторов – нужно чтобы эти бары были в источнике данных. Сумма TVal.H + TVal.Hplus + TVal.Hpre – это то минимально необходимое количество баров, которое требуется для запуска робота.

5 Таким образом, весь процесс задания стратегии в роботе будет происходить в указанных в п.3 четырех функциях, в них надо вычислить необходимые параметры (сигналы) и вызвать торговые функции с этими сигналами. Если для вычисления понадобится какая-то особенная функция, то её надо написать и добавить в код робота, после чего вызывать в указанных четырех функциях.

Сигналы

Первичный сигнал пересечения скользящих средних использующий 8 бит вычисляется в переменной Dat[i].beepFS, его биты описывал в этой статье http://smart-lab.ru/blog/325075.php .

Сигнал Dat[i].beepFS пересчитывается в сигнал Dat[i].beepTr использующий 4 бита (это будет сигнал тренда) этот сигнал попроще – определяет только направления низ и верх, а равенство исключает, для нашего случая заморачиваться на равенстве линий нет смысла:

(1000) = состояние в
(0100) - событие в
(0010) - событие н
(0001) = состояние н

Далее

1 По индикаторам. Я сторонник, чтобы используемые индикаторы вычислялись в роботе, поэтому значения быстрой и медленной скользящих средних вычисляются отдельной функцией FunSMA, которая записывает значения SMAf и SMAs в массив Dat для бара с индексом i. При желании конечно можно брать значения индикаторов с графиков, но это более муторно – появляется привязка к графику и для этого все равно понадобится какая-нибудь функция.

2 По быстродействию. Планирую отрабатывать робота на минутных таймфреймах с паузой не менее 1 секунды, думаю для терминала квик достаточно раз в секунду анализировать ситуацию, если нужна скорость, то это уже не квик ))), для таймфреймов побольше наверное проблем не должно быть.

3 Контроль. После запуска и остановки робота в папке создается файлик в который сбрасывается содержимое таблицы TDat – это чтобы можно было анализировать, что у него там внутри происходит. Каждый раз создаются новый файл – к имени добавляется время.

4 Остальное описание можно посмотреть в коде, если что не понятно, спрашивайте.

5 Для запуска робота надо выполнить в квике файл OUR.lua (квик к серверу можно и не подключать, конечно, надо обратить внимание на настройки робота – например, на инструмент, котировки которого должны быть в наличии), все файлы должны находиться в одной папке. Как запускать – можно посмотреть здесь http://smart-lab.ru/blog/325678.php .

Последние дни занимался функцией, которая будет парсить котировки, чтобы сделать возможность тестирования стратегий на истории. Затем эти котировки будут заливаться в таблицу TBar и робот сможет по ним прогонять алгоритм. Далее надо разрабатывать функции, которые будут вычислять торговый сигнал и обрабатывать его – торговать, а также подсчитывать профит (хаха…) при тестировании на истории.

Подумал, что к пересечению скользящих средних нужно еще что-нибудь добавить – какие будут предложения – какие сигналы/индикаторы еще использовать в стратегии для примера?

30 Комментариев
  • Байкал
    22 мая 2016, 19:39
    Один там накупил уже роботов) матерится теперь
      • Байкал
        22 мая 2016, 21:57
        finstrateg, да я не про ваш топик а про другой был здесь днем сегодня как парень купил робота)
        • емеля
          22 мая 2016, 21:58
          Байкал, роботы серьезна зарабатывают?
  • T-800
    22 мая 2016, 20:37
    На самом деле Вы изобретаете велосипед. Пользуюсь конструктором торговых роботов 3CBot http://www.saturn-capital.info/#!blank/zpgpl
    Знания программирования не нужны, проще, чем тслаб.
    В робот можно загнать до 50-ти различных систем на разных тикерах для диверсификации.
  • Владимир
    22 мая 2016, 20:37
    пересечение скользяшек это не сигнал, это то что Вы видите и принимаете решение на покупку продажу, пересечение — это лишь стечение обстоятельсв)))
  • Владимир
    22 мая 2016, 20:40
    или http://ensed.org/
  • Владимир
    22 мая 2016, 20:52
    в любом случае Вы стоите на правильном пути, хотя и тернистом, если хочешь сделать что то хорошо — сделай это сам! Предложенные ссылки просто сокращают Ваш путь. 
  • uginnk
    22 мая 2016, 21:11
    робот? хуёбот!
  • Чужой
    22 мая 2016, 21:24
    спасибо, выкладывай больше примеров и посложнее)
    • Чужой, тяжелый алгоритм получается, примеры посложней могут утонуть в сложности алгоритма.
  • Nemo_2000
    22 мая 2016, 21:32
    вообще, я за пол часа с закрытыми глазами (ну почти) вобью в квик рабочего бота  на двух машках. Это если стоит задача запилить что-то для торговли… Но здесь, как я понял идёт упражнение в программировании… Но тоже вопрос неоднозначный, стоит ли организовывать различные потоки, обрабатывать события в колбеках, структурировать данные и перекидывать их из одной функции в другую… Всё это, на мой взгляд, ухудшает работу… учитывая ещё то, что большинство процедур требуют обращения к серверу, а это часть работы ботом никак не контролируется и можно только надеется на корректный ответ в приемлемое время… Для себя решил всё упрощать… Колбеки вообще — зло. Их использование влечёт многократное увеличение кода для обеспечения хоть какой то корректной работы… поэтому в торговые функции их вообще включать не стоит… может для анализа или обработки какого то форсмажора… В идеале мой робот должен войти и выйти две функции по двум условиям ))) но и это стремлюсь упростить . 
    )
      • Nemo_2000
        23 мая 2016, 10:19
        finstrateg, я пыталсямиспользовать онтрейд, онордер… чуть не поседел… не знаешь вообще сколько и в какой момент они влезут к тебе и всё испортят )))
        Пытался использовать такую функцию, которая только один раз обрабатывает событие по трейду, всё остальное игнорирует..

        nction OnTrade(Trade)
        if Flag_OnTrade == true then
        --message(tostring(os.time(Trade.datetime)).." "..tostring(T),1)
        — TT = os.date("*t",T)
        — message(tostring(Trade.datetime.min)..":"..tostring(Trade.datetime.sec).." "..tostring(TT.min)..":"..tostring(TT.sec),1)
        end
        if Trade.trade_num == TradeNum or Flag_OnTrade == false or T >= os.time(Trade.datetime) then
        return
        end
        --message(«TradeNum = »..tostring(Trade.trade_num),1)
        Flag_OnTrade = false
        TradeNum = Trade.trade_num
        NEW_STOP_ORDER(p_classcode, p_seccode, p_account, Position)
        end

        и это даже работало и хорошо работало, но только на демке, на сервере разработчиков ) на реале у брокера функция врубалась в самые неожиданные моменды, что доставляло мне много радости ))) (ведь на реале) .

        Поэтому я эти колбеки больше не использую, и не видел ни одного примера их удачного использования. Все реакции бота основаны на изменение баланса, чистой позиции по инструменту. так проще, но конечно медленнее, но у меня в сбере отложка иногда по пчть секунд исполняется, поэтому задержки в пределах секунды для такого режима торговли вообще несущественны..

      • SergeyJu
        23 мая 2016, 12:23
        finstrateg, заявки можно контролировать по последствиям, если они встали и если они исполнились, меняются лимиты по деньгам и по бумагам. 
        Проблема возникает, если заявку послал —  и ни ответа, ни привета. Разобраться, в чем была проблема, достаточно сложно. Если была ошибка в заявке, колбек поможет. А если проблема на линии связи, у брокера или на бирже — фиииг знает, что делать.
  • френк френков
    22 мая 2016, 22:21
    сможешь написать наа луа!?.. переписать.без файла лога надежней. через лог файл 2 робота работать будут с разными значениями.всё собьётся.для каждого свой файл данных тэикстэ.
  • френк френков
    22 мая 2016, 22:22
     вот код на купиэль

    PORTFOLIO_EX(15)(треллинг)(MMM6); DESCRIPTION (15)(треллинг) (MMM6); CLIENTS_LIST ALL_CLIENTS; FIRMS_LIST ALL_FIRMS;

    USE_CASE_SENSITIVE_CONSTANTS;

    PROGRAM

    ACCOUNT = "...." MARKET = «SPBFUT» TICKER = «MMM6»

    NEW_GLOBAL(«TRANS_ID», 0)

    STOP_FACTOR = 5 SPREAD_FACTOR =15

    NEW_GLOBAL(«LAST_ORDER», 0)

    IF LAST_ORDER == 0     BALANCE = GET_BALANCE(MARKET, TICKER)+0     IF BALANCE != 0         LAST_ORDER = NEW_STOP_ORDER(MARKET, TICKER, ACCOUNT, BALANCE)+0     END IF END IF

    TOTAL = GET_NUMBER_OF(«STOP_ORDERS») FOR INDEX FROM 0 TO (TOTAL-1)     RINDEX = TOTAL — INDEX     ORDER = GET_ITEM(«STOP_ORDERS», RINDEX)     IF (GET_VALUE(ORDER, «NUMBER»)+0) == LAST_ORDER         STATUS = GET_VALUE(ORDER, «STATUS»)         IF STATUS == «ACTIVE»             HAVE_CHANGE = 0             QUANTITY = GET_VALUE(ORDER, «QUANTITY»)+0             BALANCE = GET_BALANCE(MARKET, TICKER)             IF QUANTITY !=ABS(BALANCE)                 HAVE_CHANGE =1                 LOG(«Количество изменилось: » & BALANCE)             ELSE                 PRICES = CREATE_MAP()                 PRICES = SET_STOPPRICE(PRICES, MARKET, TICKER, QUANTITY)                 SPRICE = GET_VALUE(PRICES, «STOPPRICE»)+0                 OPRICE = GET_VALUE(ORDER, «CONDITION_PRICE»)+0                 IF GET_VALUE(ORDER, «OPERATION») == «BUY»                                   IF SPRICE < OPRICE                         LOG(«Цена стопа продажи уменьшилась: » & SPRICE)                         HAVE_CHANGE =1                                              END IF                                 IF SPRICE > OPRICE                         LOG(«Цена стопа продажи увеличилась: » & SPRICE)                     END IF                                ELSE                     IF SPRICE < OPRICE                         LOG(«Цена стопа покупки уменьшилась: » & SPRICE)                     END IF                                    IF SPRICE > OPRICE                         LOG(«Цена стопа покупки увеличилась: » & SPRICE)                         HAVE_CHANGE =1                     END IF

                    END IF             END IF             IF HAVE_CHANGE == 1                 KILL_STOP_ORDER(MARKET, TICKER, ACCOUNT, LAST_ORDER)             END IF         ELSE             LAST_ORDER = 0         END IF            END IF    END FOR

    FUNC KILL_STOP_ORDER(_MARKET, _TICKER, _ACCOUNT, _NUMBER)     T = CREATE_MAP()     TRANS_ID = TRANS_ID + 1     T = SET_VALUE(T, «TRANS_ID», TRANS_ID)     T = SET_VALUE(T, «ACTION», «KILL_STOP_ORDER»)     T = SET_VALUE(T, «STOP_ORDER_KEY», _NUMBER)        T = SET_VALUE(T, «CLASSCODE», _MARKET)     T = SET_VALUE(T, «SECCODE», _TICKER)     T = SET_VALUE(T, «ACCOUNT», ACCOUNT)     R = SEND_TRANSACTION(30, T)     RESULT = GET_VALUE(R, «RESULT»)+0     LOG(GET_VALUE(R, «DESCRIPTION»)) END FUNC

    FUNC NEW_STOP_ORDER(_MARKET, _TICKER, _ACCOUNT, _SIZE)     T = CREATE_MAP()     TRANS_ID = TRANS_ID + 1     T = SET_VALUE(T, «TRANS_ID», TRANS_ID)     T = SET_VALUE(T, «ACTION», «NEW_STOP_ORDER»)       T = SET_VALUE(T, «CLASSCODE», _MARKET)     T = SET_VALUE(T, «SECCODE», _TICKER)     T = SET_VALUE(T, «ACCOUNT», ACCOUNT)     T = SET_STOPPRICE(T, _MARKET, _TICKER, _SIZE)     IF BALANCE > 0         T = SET_VALUE(T, «OPERATION», «S»)     ELSE         T = SET_VALUE(T, «OPERATION», «B»)     END IF        T = SET_VALUE(T, «QUANTITY», ABS(_SIZE))     R = SEND_TRANSACTION(30, T)     LOG(GET_VALUE(R, «DESCRIPTION»))     RESULT = GET_VALUE(R, «ORDER_NUMBER») END FUNC

    FUNC LOG(_MSG)     ROW = CREATE_MAP()     DT = GET_DATETIME()     ROW = SET_VALUE(ROW, «DT», GET_VALUE(DT, «DATETIME»))     ROW = SET_VALUE(ROW, «MSG», _MSG)     ADD_ITEM(1, ROW)    END FUNC

    FUNC GET_BALANCE(_MARKET, _TICKER)     RESULT = 0     _TOTAL = GET_NUMBER_OF(«FUTURES_CLIENT_HOLDINGS»)     FOR _INDEX FROM 1 TO _TOTAL         DEPO = GET_ITEM(«FUTURES_CLIENT_HOLDINGS», _INDEX)            IF GET_VALUE(DEPO, «SECCODE») == TICKER             IF GET_VALUE(DEPO, «TRDACCID») == ACCOUNT                 RESULT = GET_VALUE(DEPO, «TOTAL_NET»)+0                 BREAK             END IF         END IF     END FOR    END FUNC

    FUNC SET_STOPPRICE(_MAP, _MARKET, _TICKER, _SIZE)     _PRICE = GET_PARAM(_MARKET, _TICKER, «LAST»)+0     _STEP = GET_VALUE(GET_PARAM_EX(_MARKET, _TICKER, «SEC_PRICE_STEP»), «PARAM_VALUE»)+0        IF BALANCE > 0         _STOPPRICE = _PRICE — (STOP_FACTOR)' * _STEP)         _PRICE = _STOPPRICE — (SPREAD_FACTOR)' * _STEP)     ELSE         _STOPPRICE = _PRICE + (STOP_FACTOR)' * _STEP)         _PRICE = _STOPPRICE + (SPREAD_FACTOR)' * _STEP)     END IF     _R = CREATE_MAP(_MAP)     _R = SET_VALUE(_R, «PRICE», _PRICE)     _R = SET_VALUE(_R, «STOPPRICE», _STOPPRICE)     RESULT = _R END FUNC

    FUNC ROUND_PRICE(_PRICE, _STEP)        RESULT = APPLY_SCALE(_PRICE / _STEP, 0) * _STEP END FUNC

    END_PROGRAM

    PARAMETER DT; PARAMETER_TITLE Дата и Время; PARAMETER_DESCRIPTION Дата и Время; PARAMETER_TYPE STRING(30); END

    PARAMETER MSG; PARAMETER_TITLE Сообщение; PARAMETER_DESCRIPTION Сообщение; PARAMETER_TYPE STRING(300); END

    END_PORTFOLIO_EX

  • френк френков
    22 мая 2016, 22:28
     этот автостоп на qpl сначала ставит стоп. потом запись в переменную значения стопа и с каждым изменением стоп сдвигается или на месте.переменная прибавляет шаг.
    есть другой способ.
      • френк френков
        22 мая 2016, 22:43
        finstrateg, это лучший код.он короче.сначала ставит стоп.потом шаг и передвигает.
        вот код робота на рси. к нему стоп скользящий. и толку. здесь стоп большой. и нужен файл лога.

        --Параметры: p_classcode=«SPBFUT01» --Код класса p_seccode=«BRJ6» --Код инструмента p_account="...." --Код счета p_clientcode="...." --Клиенткий код p_count=1 --Размер позиции p_spread=0.15 --Проскальзывание p_sell_level_RSI=60 --уровень RSI, при котором продаем p_buy_level_RSI=40 --уровень RSI, при котором покупаем p_TRANS_ID=«2» --идентифкатор транзакций робота, нужен для того, что бы робот отличал свои транзакции от транзакций других роботов и ручных транзакций p_TRANS_ID_STOP=«3» --по работе со стоп ордерами p_stop_loss_level=0.15 --Уровень стоп лосса p_traling_stop_level=0.3 --Уровень стоп лосса, при котором мы «подтягиваем» стоп лосс p_file = io.open(«C:\\BRJ6\\userlog.txt», «w») — тут надо указать путь к файлу лога

        --Служебные переменные is_run = true count = 0 in_trade = false --признак того, что мы в позиции order_num = "" --номер заявки по открытой сделке stop_loss_num = "" --номер стоп заявик по открытой сделке direction=""  --последний тип операции last_price=0 --цена последней сделки по стратегии in_set_stop_loss = false --признак, что мы в данный момнет ожидаем результата выставления стоп лосса

        function main()  while is_run do   sleep(200)   robot()  end end

        function to_log(a_msg)  p_file:write(os.date().."   "..a_msg.."\n") end

        function robot()  local RSI=getNumCandles(«RSI»)  local N=getNumCandles(«Price»)  t,n,i=getCandlesByIndex(«Price», 0, N-1, 1)  RSI_t,RSI_n,RSI_i=getCandlesByIndex(«RSI», 0, RSI-3, 2)    --сигнла обрабатываем только если мы не в позиции  if not(in_trade) then   --сигнал на продажу (RSI пересекает уровень продажи сверху вниз)   if RSI_t[0].close>p_sell_level_RSI and RSI_t[1].close<p_sell_level_RSI then    Trade(«S»,count+p_count,t[0].close-p_spread)   end      --сигнал на покупку (RSI пересекает уровень покупки снизу вверх)   if RSI_t[0].close<p_buy_level_RSI and RSI_t[1].close>p_buy_level_RSI then    Trade(«B»,p_count-count,t[0].close+p_spread)   end     else    --проверить состояние стопа, не надо ли его сдвигать или изменить количество   stop_loss_control()  end    end

        function fn(par1)  if stop_loss_num=="" then   return false  end  if tonumber(par1) — tonumber(stop_loss_num)==0 then   return true  else   return false  end end

        function stop_loss_control()

         local N=getNumCandles(«Price»)  if N==nil or N==0 then return end  p_t,p_n,p_i=getCandlesByIndex(«Price», 0, N-1, 1)    local NO=getNumberOf(«stop_orders»)  local is_stop_order=true  if NO==nil or NO==0 then   is_stop_order=false  else   t_so =  SearchItems(«stop_orders», 0, NO-1, fn, «order_num»)  end    --если стоп лосса нет, то возможно, его надо выставить  if t_so==nil and is_stop_order then   is_stop_order = false  end  if is_stop_order then   if t_so[1]==nil then    is_stop_order = false   end  end    if not(is_stop_order) then     if in_trade and count~=0 then    if count>0 then     send_stop_loss(«B»,count,last_price)    else     send_stop_loss(«S»,count,last_price)    end   end   return  end

         to_log(«stop_loss_control найден стоп ордер count=»..count)  t_so_item=getItem(«stop_orders», t_so[1])  delta_price=0;    if count>0 then   to_log(«count>0»)   delta_price=p_t[0].close-t_so_item.condition_price;   l_direction=«B»  else   to_log(«count<=0»)   delta_price=t_so_item.condition_price-p_t[0].close    l_direction=«S»  end  to_log(«delta_price=»..delta_price.."    t_so[0].qty="..t_so_item.qty.."      p_t[0].close="..p_t[0].close)    if delta_price>=p_traling_stop_level or count~=t_so_item.qty then   to_log(«Послылаем новую стоп заявку price=»..p_t[0].close.." количество "..count)   send_stop_loss(l_direction,count,p_t[0].close)  end   end

        function Trade(a_oper,a_count,a_price)  if a_count>0 then     --Сначала пошлем обычную заявку   t = {     [«CLASSCODE»]=p_classcode,     [«SECCODE»]=p_seccode,     [«ACTION»]=«NEW_ORDER»,     [«ACCOUNT»]=p_account,     [«CLIENT_CODE»]=p_clientcode,     [«TYPE»]=«L»,     [«OPERATION»]=a_oper,     [«QUANTITY»]=tostring(a_count),     [«PRICE»]=tostring(a_price),     [«EXPIRY_DATE»]=«TODAY»,     [«TRANS_ID»]=p_TRANS_ID    }   res=sendTransaction(t)      --заявку послали и сразу же мы оказались в позиции и будем в ней до тех пор, пока не закроется сделка   --или пока не будет доказано обратное (мы узнаем, что сделка не прошла)   in_trade=true      direction=a_oper   message(«Количество сделки »..tostring(a_count).."  тип операции "..a_oper.." Цена "..a_price,1)  end end

        --Обработчик события сделки function OnTrade(trade)  nord=trade[«order_num»] --номер заявки  price=trade[«price»] --цена сделки  to_log(«Совершена сделка: номер заявки »..tostring(nord).."; цена "..tostring(price)..": количество "..tostring(trade[«qty»]))  if nord==order_num then   qty=trade[«qty»] --Количество бумаг в последней сделке в лотах   if direction==«B» then    count=count+qty   else    count=count-qty   end   send_stop_loss(direction,count,price)   last_price=price  end end

        --Обработчик события создания стоп заявки function OnStopOrder(stop_order)      --бит 0 (0x1) Заявка активна, иначе не активна  if stop_order[«order_num»]==stop_loss_num and bit.band(stop_order[«flags»],0x1)==0x1 then   to_log(«сняли признак что мы в процессе выставления стоп оредра»)   in_set_stop_loss=false  end    --бит 0 (0x1) Заявка активна, иначе не активна,  --бит 1 (0x2) Заявка снята. Если не установлен и значение бита 0 равно 0, то заявка исполнена  --в этом случае мы считаем, что позция закрыта по стоп лоссу  if stop_order[«order_num»]==stop_loss_num and bit.band(stop_order[«flags»],0x1)==0x0 and bit.band(stop_order[«flags»],0x2)==0x0 then   in_set_stop_loss=false   in_trade=false   count=0  end end

        --Удалить стоп лосс function delete_stop_loss(a_num)  t = {    [«CLASSCODE»]=p_classcode,    [«SECCODE»]=p_seccode,    [«ACTION»]=«KILL_STOP_ORDER»,    [«ACCOUNT»]=p_account,    [«CLIENT_CODE»]=p_clientcode,    [«TYPE»]=«L»,    [«OPERATION»]=l_oper,    [«STOP_ORDER_KIND»]=«SIMPLE_STOP_ORDER»,    [«TRANS_ID»]=p_TRANS_ID_STOP,    [«STOP_ORDER_KEY»]=tostring(a_num)   }  res=sendTransaction(t)  message(«Удаляем стоп лосс: сообщение »..res.."; номер "..a_num,1) end

        --Послать стоп заявку function send_stop_loss(a_direction,a_count,a_price)

         to_log(«send_stop_loss in_set_stop_loss=»..tostring(in_set_stop_loss))

         if not(in_set_stop_loss) then     if stop_loss_num~="" then    delete_stop_loss(stop_loss_num)   end     if a_direction==«B» then    l_oper=«S»    l_count=a_count    dir=-1   else    l_oper=«B»    l_count=-a_count    dir=1   end      l_price=a_price+p_stop_loss_level*dir

          if l_count>0 then       to_log(«send_stop_loss Зашли сюда»,1)    in_set_stop_loss=true       --Пошлем стоп заявку    t = {      [«CLASSCODE»]=p_classcode,      [«SECCODE»]=p_seccode,      [«ACTION»]=«NEW_STOP_ORDER»,      [«ACCOUNT»]=p_account,      [«CLIENT_CODE»]=p_clientcode,      [«TYPE»]=«L»,      [«OPERATION»]=l_oper,      [«QUANTITY»]=tostring(l_count),      [«PRICE»]=tostring(l_price+p_spread*dir),      [«EXPIRY_DATE»]=«TODAY»,      [«STOPPRICE»]=tostring(l_price),      [«STOP_ORDER_KIND»]=«SIMPLE_STOP_ORDER»,      [«TRANS_ID»]=p_TRANS_ID_STOP     }    res=sendTransaction(t)    message(res,1)    to_log(«Выставли стоп заявку »..l_oper)   end  end

        end

        --обработка события транзакции function OnTransReply(trans_reply)  id=tostring(trans_reply[«trans_id»]) --Пользовательский идентификатор транзакции    to_log(«Обработка транзакции »..id)    --если это наша транзакция, обработаем ее  if id==p_TRANS_ID then   nord=trans_reply[«order_num»] --Номер заявки      to_log(«Обработка транзакции номер заявки »..nord)      --если заявка выставилась — запоминаем ее номер, иначе считаем, что мы не в сделке   if nord==nil or nord==0 or nord==«0» then    message(«Заявка не выставилась »,1)    in_trade=false   else    order_num=nord   end  end    if id==p_TRANS_ID_STOP then   message(«Сообщение транзакции стоп ордера »..trans_reply[«result_msg»],1)   nord=trans_reply[«order_num»] --Номер заявки      --если заявка выставилась — запоминаем ее номер, иначе считаем, что мы закончили выставлять стоп заявку   if nord==nil then    message(«Стоп заявка не выставилась »,1)    in_set_stop_loss=false    stop_loss_num=""   else    stop_loss_num=nord   end  end end

        function OnStop(stop_flag)  is_run=false  stop_flag=1  p_file:close(); end

         

         

      • френк френков
        22 мая 2016, 22:58
        finstrateg, что переходить? ты пишешь блог. что умеешь.  не умеешь это!
  • френк френков
    22 мая 2016, 22:45
     пока 2 способа. в луа синтаксис привёл. но робот не работает. надо нил обрабатывать. не ноль так нил
  • френк френков
    22 мая 2016, 22:58
     finstrateg, что переходить? ты пишешь блог. что умеешь.  не умеешь это!

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн