Есть у меня в роботе один косяк, который отлавливал наверное с начала года. Нет, не потому что тупой Просто подобная ситуация крайне редка, особенно на демо счете, где торги ну крайне вялые. Просьба помочь. Косяк связан с частичным исполнением сделки при определенных условиях. Когда частичные покупки по одной и тойже заявке происходят относительно медленно, алгоритм работает идеально. Но стоит покупкам совершаться настолько быстро, что не успел отработать один OnDepoLimit(dlimit) как отрабатывает уже следующий, алгоритм дает сбой. Попытаюсь продемонстрировать на примере. Есть функция KillOrder(), по моему алгоритму если свершилась частичная покупка и уже есть неполная заявка на продажу(т.е. частичная покупка по одной и той же заявке совершилась во 2 и более раз), то KillOrder() просто напросто не находит эту заявку на продажу в таблице заявок.
function KillOrder(sec)
local n = getNumberOf("orders")
local y = 0
message("KillOrder() от " .. tool[sec].NAME .. ": Записей в таблице заявок " .. n)
for y = 0, n-1 do
local order = getItem("orders", y) -- Перебираем все строки таблицы
if (order.client_code == settings["common"].CLIENT_CODE) and
(order.sec_code == settings[sec].SEC) and
((order.flags & 0x7) == 5) then -- Если есть совпадение
message("KillOrder(): Найдена активная заявка на продажу")
-- tool[sec].uniq_trans_id = tool[sec].uniq_trans_id + 0x1
local Trade = settings["common"].TRADE_ACC
if settings[sec].CLASS == "CETS" then Trade = settings["common"].TRADE_ACC_1 end
local trans = {
["ACTION"] = "KILL_ORDER",
["CLASSCODE"] = settings[sec].CLASS,
["SECCODE"] = settings[sec].SEC,
["ACCOUNT"] = Trade,
["ORDER_KEY"] = tostring(order.order_num),
["TRANS_ID"] = tostring(tool[sec].uniq_trans_id),
}
local res = sendTransaction(trans) -- и убиваем заявку
message("KillOrder(): Приговор заявке от " .. tool[sec].NAME .. " вынесен! " .. res, 2)
elseif (order.sec_code == settings[sec].SEC) then -- Если есть совпадение
message("KillOrder(): от " .. tool[sec].NAME .. " Значения: Код клиента - " .. order.client_code .. ", Код инструмента - " .. order.sec_code .. ", Флаги - " .. tostring(string.format("0x%X", order.flags)) .. " ID - " .. tostring(tool[sec].uniq_trans_id))
end
end
end
А вот вывод диагностических сообщений. Где:
1. OnDepoLimit() in: начало(вход) коллбэка OnDepoLimit(). Здесь не производится никаких действий, просто вывод необходимых мне значений таблицы dlimit, возвращаемой OnDepoLimit().
2. После пункта 1 идет следующее сообщение OnDepoLimit() out х:, где х означает условие по которому завершился коллбэк из первого пункта.
Т.е. пара этих сообщений это один и тот же коллбэк, все что между ними это действия внутри коллбэка от вызова до выхода
12:11:39 ВТБ ао Берем повторно по стратегии
12:11:39 SendOrder(): Заявка B от ВТБ ао отправлена! Цена = 0.02161
12:11:39 OnDepoLimit() in: ВТБ ао В покупке - 10 В портфеле - 0 В продаже - 0 Статус - e_buy
12:11:39 OnDepoLimit() out 1: ВТБ ао Статус - confirm_buy
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 8 В портфеле - 2 В продаже - 0 Статус - confirm_buy
12:11:40 SendOrder(): Заявка S от ВТБ ао отправлена! Цена = 0.021675
12:11:40 OnDepoLimit() out 2: ВТБ ао Статус - part_e_buy
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 7 В портфеле - 3 В продаже - 0 Статус - part_e_buy
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 6 В портфеле - 4 В продаже - 0 Статус - part_e_buy
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 5 В портфеле - 5 В продаже - 0 Статус - part_e_buy
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 1 В портфеле - 9 В продаже - 0 Статус - part_e_buy
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 0 В портфеле - 10 В продаже - 0 Статус - part_e_buy
12:11:40 OnDepoLimit() out 4.1: ВТБ ао Статус - part_buy
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 0 В портфеле - 10 В продаже - 2 Статус - part_buy
12:11:40 KillOrder() от ВТБ ао: Записей в таблице заявок 97
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x1E ID - 24655
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x18 ID - 24655
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x1C ID - 24655
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x18 ID - 24655
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x1C ID - 24655
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x18 ID - 24655
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x1C ID - 24655
12:11:40 KillOrder(): от ВТБ ао Значения: Код клиента - 10609, Код инструмента - VTBR, Флаги - 0x18 ID - 24655
12:11:40 OnDepoLimit() out 5: ВТБ ао Статус - kill_order
Вначале видим, что стратегия решила о необходимости после предыдущей закрытой сделки(купля-продажа) открыть сделку повторно(т.е. прикупить еще бумаг), отправляем заявку и подтверждаем что она выставлена. После чего происходит покупка 2 лотов из 10, что мы видим по выводу и отправляем заявку на продажу уже купленных 2 лотов SendOrder() и спокойно уходим из коллбэка по условию out 2. И вот здесь начинается чехарда с частичными покупками, причем судя по всему первые 4 коллбэка даже не завершились, ибо вход в функцию после всех фильтров есть, но выхода нет. Для данного случая я не стал предусматривать отдельного выхода, ибо геморойно, просто функция 100% должна была завершиться сообщениями
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 7 В портфеле - 3 В продаже - 0 Статус - part_e_buy
[u]12:11:40 OnDepoLimit() out: ВТБ ао В покупке - 7 В портфеле - 3 В продаже - 0 Статус - wait[/u]
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 6 В портфеле - 4 В продаже - 0 Статус - part_e_buy
[u]12:11:40 OnDepoLimit() out: ВТБ ао В покупке - 6 В портфеле - 4 В продаже - 0 Статус - wait[/u]
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 5 В портфеле - 5 В продаже - 0 Статус - part_e_buy
[u]12:11:40 OnDepoLimit() out: ВТБ ао В покупке - 5 В портфеле - 5 В продаже - 0 Статус - wait[/u]
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 1 В портфеле - 9 В продаже - 0 Статус - part_e_buy
[u]12:11:40 OnDepoLimit() out: ВТБ ао В покупке - 1 В портфеле - 9 В продаже - 0 Статус - wait[/u]
Тем не менее незавершенная функция не помешала отработать при полной покупке и нормально выйти по out 4.1(Не знаю как отразится в будущем такая неполная отработка коллбэка, возможно переполнение или опустошение стэка, не знаю). После чего приходит коллбэк OnDepoLimit() in с тем, что заявка, отправлена ранее, выставлена, что мы и видим
12:11:40 OnDepoLimit() in: ВТБ ао В покупке - 0 В портфеле - 10 В продаже - 2 Статус - part_buy
Эти цифры я беру из таблицы, возвращаемой коллбэком.
Тут по моей логике необходимо прибить заявку и выставить заново с тем количеством, что у меня в портфеле. Для чего вызываю прямо из действующего текущего OnDepoLimit() функцию KillOrder()(Да, знаю, хреновое решение, но других вариантов я не придумал, ибо надо максимально быстро это сделать). Теперь функция быстренько перебирает всю таблицу заявок, отбирает только действующие заявки на продажу по флагам и если находит то убивает. НО! В таблице заявок выставленной заявки еще нет! Мы видим что нашлось 97 записей, а по факту нужная заявка в таблице 98! Причем все предыдущие заявки отображаются верно. С ID я поспешил и вывел текущее значение вместо того чтобы взять его из таблицы заявок.
Причем, если частичные покупки совершаются не так интенсивно и OnDepoLimit() успевает завершаться, все работает идеально...
Принципиально у меня есть решение, тупо вынести убийство заявки в майн, можно подумать вынести в OnTrade(), а в OnDepoLimit() только выставлять флаг что необходимо прибить заявку... Но в первом случае это очень и очень долго, во втором случае не гарантирует что я не нарвусь на тот же самый глюк, да и прилететь новые могут... Как всегда, вопрос что делать?