Коллеги, привет! Скрипт работает уже давно, используется заявка тейк-профит и стоп-лимит, но в пятницу размер стопа не спас ситуацию, нефть слишком упала, и заявку протащило. Поэтому возник вопрос: как сделать заявку тейк-профит и стоп-маркет, чтобы таких ситуаций избегать? Испробована версия с выставлением нулевых параметров, но система логично такую историю отвергает, в итоге и стоп- не стоит, и позиция взята, слишком рисково.
Как получилось на реальном примере: выставлена заявка на закрытие фьюча по нефти, тейк 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
Есть варианты: - увеличивать отступ исполнения стоп-ордера, чтобы была больше вероятность исполнения отправленной лимитной заявки (но, возможно, больше будет ГО) - не ставить стоп физически, а отслеживать цену алгоритмом и закрывать "по рынку" исходя из текущей ситуации, если алгоритм решил, что стоп сработал. - более сложный вариант отслеживания активации стопа. После того как получен признак что стоп исполнен, проверять установку связанного с ним лимитного ордера и его исполнение. Если он не исполнен, снимать его алгоритмом и ставить новый исходя из текущей цены. Т.е. реализовать алгоритм "гонки за ценой". Т.к. мы никогда не знаем какая в будущем будет ситуация в момент активации стопа (т.е. угадать отступ), то, по хорошему, какой-то вариант "гонки" все равно необходимо реализовать.
Также не стоит забывать про битовые флаги 10 и 11 стоп ордера:
бит 10 (0x400) - Стоп-заявка сработала, но была отвергнута торговой системой бит 11 (0x800) - Стоп-заявка сработала, но не прошла контроль лимитов
Ордер может исполнится, а лимитный ордер вообще не прошел. Позиция останется, если это не контролировать.
Nikolay написал: - не ставить стоп физически, а отслеживать цену алгоритмом и закрывать "по рынку" исходя из текущей ситуации, если алгоритм решил, что стоп сработал.
Да, но важно отметить, что в таком случае важно обеспечить постоянную работоспособность алгоритма, вне зависимости от отключения связи и электропитания.
Да, но важно отметить, что в таком случае важно обеспечить постоянную работоспособность алгоритма, вне зависимости от отключения связи и электропитания.
Подход хороший и понятный, но не читается почему-то значение, записанное в файл. То есть я пошла следующим путем: открывается сделка, записываю все параметры в файл, читаю потом из файла то самое значение, которое будет стопом, но цифры после точки не считываются почему-то. Функций округления при этом нет. Инструмент - нефть. И было бы понятно, если бы он не читал эти данные в формулах где-то, но он из файла их не читает. При этом сепаратором стоит ;.
Скорее всего просто нарушено форматирование при сохранении или уже при чтении проблема алгоритма.
Лучше пойти путем хранения самого контекста скрипта. Для примера, есть некое состояние, скажем State - это таблица с необходимыми данными. Мы ее сохраняем в файл в виде сериализованой таблицы. Тогда чтение будет через одну единственную команду loadfile.
Да, лично я сроду не ставил никаких стопов и даже никогда не закрывал "по рынку" (только лимитными заявками), "если алгоритм решил, что стоп сработал". От отключения связи и электропитания не страхуюсь (в конце концов, скачки курса, когда наша биржа не работает, куда более вероятны, чем обрыв связи), но при чём здесь вообще файл? Работаем в ОЗУ! Я сбрасываю, конечно, дамп состояния в файл каждые 5 минут (страховка от отвисания Квика, которые в последнее время происходят всё чаще), но это лишь для того, чтобы не потерять ВСЕ свои сделки за сеанс.
Коллеги, спасибо за помощь и наводки! В итоге скрипт заработал. Мало ли кому будет надо, выкладываю. Просьба не обращать внимание на комменты, я после ковида очень боюсь опять потерять память, поэтому все себе комментирую. Как работает? Забирает отклик при отправке транзакции, если она выполнена, записывает в файл (этого тут нет), далее в файле находит строку и забирает оттуда значение для стопа, которое записано в файлике. Таким образом ничего не теряется. Ошибка нечтения была именно в неверном формате чтения, не записи.
Код
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