p_classcode="SPBFUT" --Код класса p_seccode="SBRF" --Код инструмента p_account="" --Код счета p_clientcode="" --Клиенткий код p_count=2 --Размер позиции p_spread=0.7 --Проскальзывание 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=3 --Уровень стоп лосса добавить это p_bez_stop_level=3.1 -- Уровень безубытка p_traling_stop_level=1 --Уровень стоп лосса, при котором мы "подтягиваем" стоп лосс p_file = io.open("D:\\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(2000) 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 --Сначала мы ищем нашу стоп заявку:для поиска используем функцию SearchItems, она у нас вызывает CALLBACK-функцию fn: 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") -- индефикатор цены на графике N
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") --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 --in_trade признак того, что мы в позиции if count>0 then send_stop_loss("B",count,last_price)--формируем стоп-лосс и выставляем его, вызвав функцию send_stop_loss, 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; --condition это состояние, p_t строка 79 l_direction="B" else to_log("count<=0") delta_price=t_so_item.condition_price-p_t[0].close l_direction="S" end
добавить тут if delta_price>=p_bez_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 --[[ После выставления стопа вначале должен выставиться p_bez_stop_level, а за ним p_traling_stop_level. Но до выставления безубытка трал должен игнорироваться.
Размышления: Я думал, например изначально traling = false if delta_price>=p_bez_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) traling=true end if delta_price>= (p_traling_stop_level or count~=t_so_item.qty) and traling then to_log("Послылаем новую стоп заявку price="..p_t[0].close.." количество "..count) send_stop_loss(l_direction,count,p_t[0].close) end Вроде пока traling = false трал не будет работать. ]]
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"]="GTC", ["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 --stop_loss_num = "" --номер стоп заявик по открытой сделке in_set_stop_loss=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"]="GTC", ["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
--Параметры: p_classcode="SPBFUT" --Код класса p_seccode="SBRF" --Код инструмента p_account="" --Код счета p_clientcode="" --Клиенткий код p_count=2 --Размер позиции p_spread=0.7 --Проскальзывание 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=3 --Уровень стоп лосса p_traling_stop_level=3.1 --Уровень стоп лосса, при котором мы "подтягиваем" стоп лосс p_file = io.open("D:\\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(2000) 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 --Сначала мы ищем нашу стоп заявку:для поиска используем функцию SearchItems, она у нас вызывает CALLBACK-функцию fn: 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") -- индефикатор цены на графике N 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") --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 --in_trade признак того, что мы в позиции if count>0 then send_stop_loss("B",count,last_price)--формируем стоп-лосс и выставляем его, вызвав функцию send_stop_loss, 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; --condition это состояние, p_t строка 79 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 --Количество сделки
--заявку послали и сразу же мы оказались в позиции и будем в ней до тех пор, пока не закроется сделка --или пока не будет доказано обратное (мы узнаем, что сделка не прошла) 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 --stop_loss_num = "" --номер стоп заявик по открытой сделке in_set_stop_loss=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
--Пошлем стоп заявку 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"]="GTC", ["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
Не так написал, выставить безубыток я смогу (по дельте 1), но для трала нужна дельта2. Как сделать что бы после выставления безубытка дельта1 игнорировалась?
Если в двух словах то пробую сделать безубыток. У меня есть образец кода с трейлинг-стопом, вот я и пробую что бы после первого стопа ставился безубыток, а далее работал трал. Сложность в том, что не понимаю как сделать чтобы после достижения безубытка выставлялся стоп по дельте (по разнице в цене между первым стопом и текущей ценой), а далее эта дельта была другой.
Добрый день. Такой вопрос: Как разделить условия, вначале выполняется одно, другие игнорируются, а затем другое, а первое игнорируется. То есть первое учитывается только один раз От сделки не зависит.
vit10052 написал: Подскажите, как получать сообщение 10 с конца, таблицы обезличенных сделок (например: qty) через getItem(). Пробовал, но увы не вышло. Если не трудно покажите полностью код с данной функцией.
Подскажите, как получать сообщение 10 с конца, таблицы обезличенных сделок (например: qty) через getItem(). Пробовал, но увы не вышло. Если не трудно покажите полностью код с данной функцией.