Nikolay написал: Не на всех рынках есть понятие "По рынку". Если после активации ордера лимитный ордер не смог пройти контроль лимитов цен, достаточности средств, то он не будет зарегистрирован. Правда, статус стоп-ордера должен быть "исполнен" т.е. не активный и не снят. А вот биты 10 и 11 как раз могут говорить о причине проблемы.
Правильно ли я понимаю, что такую ситуацию можно отследить, если добавить проверку по флагу и по остатку, и если остаток по фьючерсам есть, а активной заявки нет, то надо выставлять по лимиту по биду/аску?
Добрый день! Написала функцию для стоп-лосса по маркету, но почему-то при выставлении заявки при срабатывании стоп-лосса статус заявки сразу же снята, а не активна, и позиция по стопу не закрывается. Пожалуйста, подскажите, где может быть ошибка:
BlaZed написал: Яна, у меня когда-то подобная задача стояла
В код зашивать список инструментов так себе идея, если необходимо несколько инструментов отслеживать, то грустно станет списки поддерживать в актуальном состоянии. Динамически будет проще и красивее.
Код
function FindSecCode (class_code,pref,dtmd) -- Определяем инструмент для торговли
local sec_list = getClassSecurities (class_code) -- Получаем список инструментов
for test_sec_code in string.gmatch (sec_list,"( "..pref.." [^,] + )") do -- Перебираем список
local param = getParamEx (class_code,test_sec_code,"DAYS_TO_MAT_DATE")
if (param.result = = "1" ) and (param.param_image~ = "" ) and (param.param_type~ = "0" ) then -- Параметр получен корректно?
if (tonumber(param.param_value) > = dtmd) then return test_sec_code end -- Проверяем дни до экспирации
end
end
end
sec_code = FindSecCode( "SPBFUT" ,"BR", 3 )
if (sec_code) then message ( "actual futures is " .. sec_code) end
Возможно, стоило бы сортировку прикрутить, но сколько не наблюдал, от брокера сразу отсортированный по времени экспирации список прилетает.
Вот это круто! ПОпробую. Выглядит как элегантно:) Блеск!
Решение найдено. Ошибка была уже традиционно во внимательности. Контрактом можно вставить, сколько душе угодно
Код
function contract()
--функция проверки актуальности контракта
--if TP==0 then
local futdate = {}
local timedif = {}
local idx = 0
activename = "BR"
futnames = { "BRZ1","BRF2", "BRG2", "BRH2", "BRJ2","BRK2", "BRM2", "BRN2", "BRQ2", "BRU2", "BRV2","BRX2"}
for i=1,12 do
if idx==1 then break end
--message("futnames"..futnames[1]..type(futnames[i]))
if futnames[i] then
futdate[i] = getParamEx(CLASSCODE, futnames[i], "DAYS_TO_MAT_DATE").param_value
futstatus[i]= getParamEx(CLASSCODE, futnames[i], "STATUS").param_value
--message("futdate[i]"..futdate[1])
--message("futstatus[i]"..futstatus[1])
--timedif[i] = futdate[i]-tonumber(DATE)
--message('timedif='..timedif[i])
if futdate[i]~=nil then
if tonumber(futdate[i])>2 then
INSTRUMENT=futnames[i]
message('actual futures is'..INSTRUMENT)
idx=1
end
end
end
end
end
Владимир написал: Яна, Ну, если не находит, почему бы не сделать предположение, что экспирация уже прошла? Тем более, что в приведённом примере это так и есть. И, насколько я знаю, любые параметры из ТТТ получают по getParamEx. И если хоть один из них (скажем, код инструмента) там есть, значит, должны быть и все остальные. В т.ч. DAYS_TO_MAT_DATE.
Владимир, да, это безусловно так, но попытка объяснить роботу, что ненайденный параметр равно возьми следующее значение не увенчалась успехом. Возможно, у вас будет какая-нибудь идея, как это сделать, чтобы робот это понял.
Коллеги, привет! Написала функцию, которая проверяет количество дней до экспирации, чтобы контракт менялся сам, написала топорно в лоб: создала таблицу, где указала имена контрактов. Функция через getParamEx проверяет, сколько дней осталось до экспиры. Если дней меньше 3, то контракт сам меняется. Но сегодня утром столкнулась с тем, что предыдущий контракт по нефти (который вчера экспирировался) пропал из списка доступных в таблице "Текущие торги" и скрипт не может проверить по нему параметр остатка. Попытка проверить данный параметр на существование к нужному результату не привела. Скрипт с попыткой будет ниже. Как я вижу, нужно забрать из таблицы текущих торгов все возможные контракты по баховому активу и посмотреть их даты экспирации, но вот как забрать эти данные, я не знаю...
Код
function contract()
local futdate = {}
local timedif = {}
local idx = 0
activename = "RTS"
futnames = {"RIZ1", "RIH2", "RIM2", "RIU2", "RIZ2","RIH3", "RIM3", "RIU3", "RIZ3"}
--message("futnames[1]"..futnames[1].."futnames[2]"..futnames[2])
for i=1,12 do
if idx==1 then break end
--message("futnames"..futnames[i]..type(futnames[i]))
if futnames[i] then
futdate[i] = getParamEx(CLASSCODE, futnames[i], "DAYS_TO_MAT_DATE").param_image
--message("futdate[i]"..futdate[i])
--message(type(DATE).."date="..DATE)
--timedif[i] = futdate[i]-tonumber(DATE)
--message('timedif='..timedif[i])
if tonumber(futdate[i])>2 then
INSTRUMENT=futnames[i]
--message('actual futures is'..INSTRUMENT)
idx=1
end
end
end
end
Коллеги, спасибо за помощь и наводки! В итоге скрипт заработал. Мало ли кому будет надо, выкладываю. Просьба не обращать внимание на комменты, я после ковида очень боюсь опять потерять память, поэтому все себе комментирую. Как работает? Забирает отклик при отправке транзакции, если она выполнена, записывает в файл (этого тут нет), далее в файле находит строку и забирает оттуда значение для стопа, которое записано в файлике. Таким образом ничего не теряется. Ошибка нечтения была именно в неверном формате чтения, не записи.
Код
function ReadCsv(FP) -- чтение файла и присвоение значений ТР и стопу
f = io.open(FP,"r+")
local N_CSV_BEGIN = 2
local LINE_A = {}
local Datetime = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Instr = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Total = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Activity = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Price = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Ordernumber = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Ordertype = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Account= {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Robot_name = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Status = {} -- МАССИВ СТРОК ИЗ ОСНОВНОГО ФАЙЛА
local Stops = {}
if f==nil then
message("НЕТ ФАЙЛА ",3)
EXIT = 1
SL = 10000 -- 10000
else
-- message("ФАЙЛ ЕСТЬ",3)
EXIT = 0
SL = 1000
j = 1
for line in f:lines() do
LINE_A[j] = tostring(line)
--message("I'm here")
--message("Строка "..j.." ="..LINE_A[j],1)
j = j + 1
end
f:close()
NCSV = j - N_CSV_BEGIN
--message("NCSV= "..NCSV,1)
if NCSV<1 then Stopqty=0 end
for i = NCSV, 1,-1 do
if idx==1 then break end
-- Парсим все строки на массивы
--message("LINE_A[N_CSV_BEGIN+i-1] ="..LINE_A[N_CSV_BEGIN+i-1],1)
Datetime[i],Instr[i], Total[i], Activity[i], Price[i], Ordernumber[i],Ordertype[i],Account[i], Robot_name[i], Status[i], Stops[i] = string.match(LINE_A[N_CSV_BEGIN+i-1],"(.*);(.*);(.*);(.*);(.*);(%d*);(.*);(.*);(.*);(.*);(.*)")
--message("I'm here")
Datetime[i] = tostring(Datetime[i])
Instr[i] = tostring(Instr[i])
Total[i] = tonumber(Total[i])
Activity[i] = tostring(Activity[i])
Price[i] = tonumber(Price[i])+0.00
Ordernumber[i] = Ordernumber[i]+0.00
Ordertype[i] = tostring(Ordertype[i])
Account[i] = tostring(Account[i])
Robot_name[i] = tostring(Robot_name[i])
Stops[i] = (tonumber(Stops[i])+0.00)
Status[i] = tostring(Status[i])
Stopqty = Stops[i]
message("Stopqty "..Stopqty,1)
idx=1
end --end for
end --if else
end -- function
Да, но важно отметить, что в таком случае важно обеспечить постоянную работоспособность алгоритма, вне зависимости от отключения связи и электропитания.
Подход хороший и понятный, но не читается почему-то значение, записанное в файл. То есть я пошла следующим путем: открывается сделка, записываю все параметры в файл, читаю потом из файла то самое значение, которое будет стопом, но цифры после точки не считываются почему-то. Функций округления при этом нет. Инструмент - нефть. И было бы понятно, если бы он не читал эти данные в формулах где-то, но он из файла их не читает. При этом сепаратором стоит ;.
Коллеги, привет! Скрипт работает уже давно, используется заявка тейк-профит и стоп-лимит, но в пятницу размер стопа не спас ситуацию, нефть слишком упала, и заявку протащило. Поэтому возник вопрос: как сделать заявку тейк-профит и стоп-маркет, чтобы таких ситуаций избегать? Испробована версия с выставлением нулевых параметров, но система логично такую историю отвергает, в итоге и стоп- не стоит, и позиция взята, слишком рисково.
Как получилось на реальном примере: выставлена заявка на закрытие фьюча по нефти, тейк 83, стоп 81,7, цена стопа 81,55. Что вышло на практике? нефть упала в 80 в начале торговой сессии, стоп выставил заявку на продажу по 81,55, и пришлось закрыть сделку руками. Как сделать так, чтобы при прохождении 81,7 у меня выставлялась заявка на продажу по маркету? Думала сама над двумя связанными заявками, но может, у кого есть попроще решение?
Коды все рабочие, представлены ниже. Заранее большое спасибо за ответ!
Как выглядит заявка (тут все тоже рабочее):
Код
function stop2_calc()
if (PRICEMAX-ZZ12)>500 then
stop=PRICEMAX-500
else stop = ZZ12
end
end
function BUY(FLOTS)
ORDER(FLOTS,"B",dD(PRICEMAX+0,0))
stop2_calc()
message("stop "..stop)
TAKESTOPORDER(FLOTS,"S",dD(ZZ31+0,0), dD(stop,0),dD(stop-0,15,0),100,100)
end
Коллеги, привет! У Открытия создан единый счет, пытаюсь запросить остаток средств по срочному рынку, выдает оошибку. Запрашиваю свободные средства через вот эту функцию, выдает ноль. Как узнать таги, которыми можно вывести этот самый остаток? Таблицу с группами, которую указывали на формул ранее вот здесь, не нашла. https://forum.quik.ru/forum10/topic2138/ рабочий код для рынка фортс, хочу такой же работоспособный для единого счета
Код
function Lot_calculate()
--функция для расчета лотности
moneyt = getFuturesLimit(FIRM, ACCOUNT, 0, "SUR")
--message('Cash='..moneyt.cbp_prev_limit)
gofut = getParamEx(CLASSCODE, INSTRUMENT, "SELLDEPO").param_value+0
--message("GO Br = "..gofut)
LOT1 = roundNum(0.25*moneyt.cbp_prev_limit/gofut,0)
--message("LOT="..LOT1)
end
Владимир написал: Яна, Главный совет вовсе не про OnTrade - работайте в ОЗУ! Передавать данные через файл - это источник вечных глюков.
Слушайте, а ведь вы оказались правы полностью! У меня у робота есть признак - его название, который передается в систему при выставлении ордеров, и я в итоге из функции почти на 100 строк для проверки данных сделала на 40 строк, и все берется из системы. Не догнала сразу всю полноту вашего коммента. Спасибо!
Владимир написал: Яна, Господи, какой ужас! Для новичка в программировании кода раз в пять больше, чем нужно. ::
Пока не глядя на код: 1. Данные об отправленной транзакции Вам не нужны, уверен на 99.999%. 2. Скрипт ничего не должен видеть "в файлике" - работайте в ОЗУ!
Теперь смотрим код: 1. OnTransReply - это информация о транзакции, но никак не о сделке. Лично я пользуюсь только OnTrade, что и другим советую. Кстати, учтите, что прерывания приходят пачками, обычно по три штуки на одно событие. Ага, Вы это вроде как учитываете, но ТАКОЙ учёт от ошибок не гарантирует: если проскочит прерывание с другой айдишкой (а оно проскочит - проверено!), а потом снова прилетит по этой же транзакции, то Вы уже перезапишете свой id_done, и посчитаете неверно.
Владимир, за оценку я признательна, но из практического совета дан только замена на OnTrade, что вообще никак не соотносится с моим вопросом.
Sergey написал: Есть сдвиги и изменения в этом вопросе на текущий момент 07.12.2020?
API к WebQUIK нет и не планируется. Есть имеющиеся средства такие как FIX приборы (платно), Trans2Quik, lua скрипты (бесплатно). Если этих средств Вам недостаточно, Вы всегда можете озвучить свои пожелания по доработкам в соответствующей ветке форума. Очевидно что Вы хотите бесплатное, прямое API к серверу. Выпуск такого API не планируется, потому что уже есть FIX приборы.
Коллеги, изменилось ли что-то с момента последнего ответа? Очень нужен нормальный API к квику. Кстати, у ИБ даже курс по программированию на их API выложен, поэтому нам бы тоже такое не помешало. Безусловно за такой курс готов заплатить.
Коллеги, добрый день! Я новичок в программировании луа, и у меня возникла проблема. Есть скрипт, который записывает в файл csv данные об отправленной транзакции в систему, далее скрипт проверяет состояние стопа и фиксирует, если стоп выполнен. И вот после этого происходят чудеса: если появляется ещё одна сделка, то скрипт её открывает, но вот в файлик уже ничего не записывается, и в итоге ломается учёт, так как скрипт не видит записи о номере стопа в файлике. Подскажите, пожалуйста, как это можно починить?
Код
-- Функция вызывается терминалом, когда с сервера приходит новая информация о транзакциях
function OnTransReply(trans_reply)
-- Если пришла информация по нашей транзакции
if trans_reply.trans_id == id_done then
-- Если данный статус уже был обработан, выходит из функции, иначе запоминает статус, чтобы не обрабатывать его повторно
if trans_reply.status == LastStatus then return else LastStatus = trans_reply.status end
-- Выводит в сообщении статусы выполнения транзакции
if trans_reply.status == 1 then -- транзакция активна
--message('OnTransReply(): По транзакции №'..trans_reply.trans_id..' УСПЕШНО ВЫСТАВЛЕНА заявка №'..trans_reply.order_num..' по цене '..trans_reply.price..' объемом '..trans_reply.quantity,3)
end
if trans_reply.status ==3 then -- транзакция выполнена, запись в журнал
--message(trans_reply.result_msg,1)
--message('OnTransReply(): По транзакции №'..trans_reply.trans_id..' УСПЕШНО ВЫПОЛНЕНА заявка №'..trans_reply.order_num..' по цене '..trans_reply.price..' объемом '..trans_reply.quantity,3)
OrderNum = trans_reply.order_num
OrderTime=trans_reply.datetime
OrderPrice=trans_reply.price
OrderQuantity=trans_reply.quantity
OrderCond=TP
OrderInstr =trans_reply.sec_code
Ordcomment=trans_reply.brokerref
local tradeline= os.date("%c", os.time(trans_reply.datetime))..";"..
OrderInstr..";"..
OrderQuantity ..";"..
OrderCond..";"..
OrderPrice..";"..
OrderNum ..";"..
"Open_order"..";"..
ACCOUNT..";"..
Ordcomment..";"..
"Created".."\n"
CSV:seek("end",0)
CSV:write(tradeline); --записали значения в файлик
CSV:flush(); --сохранили файлик
end
end
-- Если пришла информация по нашей стоп-транзакции
if trans_reply.trans_id == id_take then
-- Если данный статус уже был обработан, выходит из функции, иначе запоминает статус, чтобы не обрабатывать его повторно
if trans_reply.status == TakeStatus then return else TakeStatus = trans_reply.status end
-- Выводит в сообщении статусы выполнения транзакции
if trans_reply.status == 3 then -- транзакция активна
Stopnumb =trans_reply.order_num
SlTpOrderTime=trans_reply.datetime
SlTpOrderPrice=trans_reply.price
SlTpOrderQuantity=trans_reply.quantity
SlTpOrderCond=TP
SlTpOrderInstr=trans_reply.sec_code
SlComment=trans_reply.brokerref
--message('OnTransReply(): По транзакции №'..trans_reply.trans_id..' ВЫПОЛНЕНА заявка №'..trans_reply.order_num..' по цене '..trans_reply.price..' объемом '..trans_reply.quantity,3)
local Stopline= os.date("%c", os.time(trans_reply.datetime))..";"..
SlTpOrderInstr..";"..
SlTpOrderQuantity ..";"..
SlTpOrderCond ..";"..
SlTpOrderPrice ..";"..
Stopnumb ..";"..
"Take_Stop_order"..";"..
ACCOUNT..";"..
SlComment..";"..
"Created".."\n"
CSV:seek("end",0)
CSV:write(Stopline); --записали значения в файлик
CSV:flush(); --сохранили файлик
end
end
end