Терминал позволяет разрабатывать самодельные индикаторы, работающие в отдельном потоке. Но индикаторам можно давать и дополнительную нагрузку, реализовывать даже легких роботов-индикаторов, торгующих автономно. Из плюсов – получаем штатное диалоговое окно средствами Квика, что-то рисуем не отходя от кассы… Не требуется подключения внешних библиотек для работы и отображения диалоговых окон, что повышает надежность и простоту установки.
Для примера сделал вполне рабочую программку авто стоп-тейк. Торговлю для примера на скользящих делать не стал, никому не нужна, а автостоп пригодится. Проверял на собственном реальном счете – работает. Пользуйтесь на здоровье!
Есть один недостаток: по одному графику инструмента (бумаги) не может работать индикатор, получающий данные извне этого графика (как этот) и луа скрипт с main. Происходит конфликт и Квик подвисает. Поэтому сейчас становится сложно надежно графически отобразить арбитражный спред например и его торговать. Но эту проблемку разработчики терминала обещают устранить в свежей версии.
Работает только на срочном рынке!!! Можно совместно допилить до универсальности ко всем рынкам… Буду рад любым дополнениям, выложенным в открытый доступ.
Тут вынужден предупредить: на рынок уходят реальные заявки, поэтому любые необдуманные эксперименты с кодом могут привести к плачевным последствиям!!!
Инструкция после кода.
Settings={} Settings.Name = "тейк и стоп FUT_L" Settings.client_code="0" Settings.loss=0 Settings.loss_prosk=0 Settings.profit=0 Settings.profit_otstup=0 Settings.profit_prosk=0 Sorder=true idx_prosl=-1 Zapusk=true function get_balance(sec, client_code) local limit={} local n=getNumberOf("futures_client_holding") for i=0,n-1 do limit = getItem("futures_client_holding", i) if limit~=nil and limit.seccode== sec and limit.trdaccid==client_code then return tonumber(limit.totalnet) end end return 0 end function get_latestprice(sec, client_code) local ord={} local n=getNumberOf("trades") for i=n-1,0,-1 do ord = getItem("trades", i) if ord~=nil and ord.sec_code==sec and (ord.client_code==client_code or ord.account==client_code) then return tonumber(ord.price) end end return 0 end function Init() return 1 end function TP_SL(class,security,direction,volume,stopprice,price,dealprice,offset,defspread,exp_date,comment) if (class==nil or security==nil or direction==nil or volume==nil or dealprice==nil or offset==nil or defspread==nil) then return nil, "AUTOMATIK_STOP_FUT: нет одного из параметров стоп-заявки." end local trans_id = string.format('%d', math.random(2000000000)) local err = sendTransaction({ TRANS_ID=trans_id, ACTION='NEW_STOP_ORDER', STOP_ORDER_KIND='TAKE_PROFIT_AND_STOP_LIMIT_ORDER', CLASSCODE=class, SECCODE=security, ACCOUNT=Settings.client_code, CLIENT_CODE=Settings.client_code, OPERATION=direction, QUANTITY=tostring(volume), PRICE=tostring(price), EXPIRY_DATE='GTC', MARKET_STOP_LIMIT='NO', MARKET_TAKE_PROFIT='NO', IS_ACTIVE_IN_TIME='NO', OFFSET=tostring(offset), OFFSET_UNITS='PRICE_UNITS', STOPPRICE=tostring(dealprice), <br> STOPPRICE2=tostring(stopprice), SPREAD=tostring(defspread), SPREAD_UNITS='PRICE_UNITS', COMMENT='TP_SL' }) if err~="" then return nil, "AUTOMATIK_STOP_FUT результат: "..err else return trans_id, "" end end function OnCalculate(idx) if Zapusk then class=getDataSourceInfo().class_code sec=getDataSourceInfo().sec_code old_balance=get_balance(sec, Settings.client_code) Zapusk=false end if idx_prosl==idx then balance=get_balance(sec, Settings.client_code) if balance>0 and old_balance<balance then Sorder=false if old_balance<0 then spr_balance=balance else spr_balance=balance-old_balance end end if balance<0 and old_balance>balance then Sorder=false if old_balance>0 then spr_balance=0-balance else spr_balance=old_balance-balance end end if balance~=0 and not Sorder then Open_Price=get_latestprice(sec, Settings.client_code) if balance>0 and Open_Price~=0 then dealprice=Open_Price+Settings.profit --тейк stopprice=Open_Price-Settings.loss --стоп цена price=stopprice-Settings.loss_prosk --стоп с запасом offset=Settings.profit_otstup --отход от тейка defspread=Settings.profit_prosk --проск тейка Tr_Id,STR=TP_SL(class,sec,"S",spr_balance,stopprice,price,dealprice,offset,defspread,nil,nil) Sorder=true if Tr_Id==nil then message(" "..STR,1) end end if balance<0 and Open_Price~=0 then dealprice=Open_Price-Settings.profit --тейк stopprice=Open_Price+Settings.loss --стоп цена price=stopprice+Settings.loss_prosk --стоп с запасом offset=Settings.profit_otstup --отход от тейка defspread=Settings.profit_prosk --проск тейка Tr_Id,STR=TP_SL(class,sec,"B",spr_balance,stopprice,price,dealprice,offset,defspread,nil,nil) Sorder=true if Tr_Id==nil then message(" "..STR,1) end end end old_balance=get_balance(sec, Settings.client_code) end idx_prosl=idx return nil end
Принцип работы: при активации автостоп_фут получает параметры инструмента на графике которого он открыт (код и класс), проверяет баланс по инструменту (если уже есть открытая позиция, не выставляет на нее тейк-стоп заявку). При увеличении позиции выставляет на сервер брокера стандартную тейк-стоп заявку по введенным в настройках параметрам на то количество, на сколько увеличена позиция. Лонг или шорт определяет сам. Цену открытия позиции определяет как цену последней сделки, если сделки прошли по разной цене.
При закрытии позиции частично или полностью вручную (не по выставленным тейк-стоп заявкам) эти заявки остаются, нужно скорректировать их тоже тогда вручную!!!
На графике ничего не рисует, но можно при настройке на вкладке «Дополнительно» выбрать «Показывать стоп-заявки» и др.
Как пользоваться:
— В папке с Квиком создать, если нет, папку обязательно с именем LuaIndicators
— открыть блокнот (например), скопировать в него код и сохранить в LuaIndicators с любым именем (Auto_TeikStop.lua например) но обязательно с расширением .lua
Открыть, если не открыта, в терминале таблицу « Позиции по клиентским счетам (фьючерсы)», в этой таблице должны быть колонки: «Торговый счет», «Код инструмента», «Тек. чистая», без этого работать не будет.
Открыть, если не открыта, таблицу стоп-заявок для визуального контроля.
Дальше добавляем на график инструмента, по которому будем использовать индикатор_автостоп_фут, как обычный индикатор в любое окно: в списке доступных индикаторов имя «тейк и стоп FUT_L». В открывшемся окне индикатора вместо нулей вводим:
client_code – код клиента из таблицы «Позиции по клиентским счетам (фьючерсы)» из колонки «Торговый счет».
Вводим кратно шагу цены:
loss – сколько от цены открытия позиции до срабатывания стопа;
loss_prosk – разница между ценой срабатывания стопа и заявкой, которая пойдет на биржу;
profit – сколько от цены открытия позиции до начала активации расчета тейка;
profit_otstup – на сколько можно ухудшиться от профитного экстремума для фиксации прибыли (если ноль – то закроет сразу по достижении тейка);
profit_prosk – разница между ценой срабатывания тейка и заявкой, которая пойдет на биржу.
Нажимаем «сохранить» и автостоп активен.
Можно добавить эти параметры сразу в код, при неактивном индикаторе, и они будут установлены по умолчанию.
Например.
Надо защитить любую открываемую позицию по RIM6 на счете SPBFUT******* (client_code):
по тейк-профиту: если прибыль 1500 (profit) пунктов от цены открытия — начать расчет тейка, когда цена отойдет на 200 (profit_otstup) пунктов от профитного экстремума с начала расчета тейка, отправится заявка по цене с запасом на проскальзывание 500 пунктов (profit_prosk);
и по стоп-лимиту: если убыток 1000 (loss) пунктов от цены открытия, отправится заявка по цене с запасом на проскальзывание 300 пунктов (loss_prosk)
Для этого добавляем на график RIM6 индикатор_автостоп_фут, как обычный индикатор в любое окно: в списке доступных индикаторов имя «тейк и стоп FUT_L». В открывшемся окне индикатора вместо нулей вводим:
client_code SPBFUT*******
loss 1000
loss_prosk 300
profit 1500
profit_otstup 200
profit_prosk 500
нажать «сохранить» и автостоп_фут активен. Теперь любая позиция открытая после активации по RIM6 на счете SPBFUT******* будет защищена стандартной тейк-стоп заявкой. Лонг открыт или шорт и цену открытия, и размер позиции индикатор определяет сам.
Если тейк-стоп заявка была отклонена, появится сообщение с причиной отклонения. Надо будет выставить стоп вручную, проверить параметры и лимиты.
Важно: При изменении параметров и активации будут действовать новые параметры. Ранее выставленные тейк-стоп заявки сохранятся.
Профитной торговли!
Переделай так:
STOPPRICE=tostring(dealprice),
STOPPRICE2=tostring(stopprice),
Откуда-то <br> прилипла.
Попробуешь, напиши!
«GTC» – до отмены,
«TODAY» — до окончания текущей торговой сессии,
Дата в формате «ГГММДД».
только в верхних кавычках, как в коде.
Индикатор хороший, но опробовать не удалось.
Его нет в списке доступных индикаторов. Папка с индикаторами создана давно. Все остальные индикаторы отображаются
Settings={}
Settings.Name = «SL_TP»
Settings.client_code=""
Settings.loss=0.020
Settings.loss_prosk=0
Settings.profit=0.040
Settings.profit_otstup=0
Settings.profit_prosk=0
Sorder=true
idx_prosl=-1
Zapusk=true
function get_balance(sec, client_code)
local limit={}
local n=getNumberOf(«futures_client_holding»)
for i=0,n-1 do
limit = getItem(«futures_client_holding», i)
if limit~=nil and limit.seccode== sec and limit.trdaccid==client_code then
return tonumber(limit.totalnet)
end
end
return 0
end
function get_latestprice(sec, client_code)
local ord={}
local n=getNumberOf(«trades»)
for i=n-1,0,-1 do
ord = getItem(«trades», i)
if ord~=nil and ord.sec_code==sec and (ord.client_code==client_code or ord.account==client_code) then
return tonumber(ord.price)
end
end
return 0
end
function Init()
return 1
end
function TP_SL(class,security,direction,volume,stopprice,price,dealprice,offset,defspread,exp_date,comment)
if (class==nil or security==nil or direction==nil or volume==nil or dealprice==nil or offset==nil or defspread==nil) then
return nil, «AUTOMATIK_STOP_FUT: нет одного из параметров стоп-заявки.»
end
local trans_id = string.format('%d', math.random(2000000000))
local err = sendTransaction({
TRANS_ID=trans_id,
ACTION='NEW_STOP_ORDER',
STOP_ORDER_KIND='TAKE_PROFIT_AND_STOP_LIMIT_ORDER',
CLASSCODE=class,
SECCODE=security,
ACCOUNT=Settings.client_code,
CLIENT_CODE=Settings.client_code,
OPERATION=direction,
QUANTITY=tostring(volume),
PRICE=tostring(price),
EXPIRY_DATE='GTC',
MARKET_STOP_LIMIT='NO',
MARKET_TAKE_PROFIT='NO',
IS_ACTIVE_IN_TIME='NO',
OFFSET=tostring(offset),
OFFSET_UNITS='PRICE_UNITS',
STOPPRICE=tostring(dealprice), STOPPRICE2=tostring(stopprice),
SPREAD=tostring(defspread),
SPREAD_UNITS='PRICE_UNITS',
COMMENT='TP_SL'
})
if err~="" then
return nil, «AUTOMATIK_STOP_FUT результат: »..err
else
return trans_id, ""
end
end
function OnCalculate(idx)
if Zapusk then
class=getDataSourceInfo().class_code
sec=getDataSourceInfo().sec_code
old_balance=get_balance(sec, Settings.client_code)
Zapusk=false
end
if idx_prosl==idx then
balance=get_balance(sec, Settings.client_code)
if balance>0 and old_balance<balance then
Sorder=false
if old_balance<0 then
spr_balance=balance
else
spr_balance=balance-old_balance
end
end
if balance<0 and old_balance>balance then
Sorder=false
if old_balance>0 then
spr_balance=0-balance
else
spr_balance=old_balance-balance
end
end
if balance~=0 and not Sorder then
Open_Price=get_latestprice(sec, Settings.client_code)
if balance>0 and Open_Price~=0 then
dealprice=Open_Price+Settings.profit --тейк
stopprice=Open_Price-Settings.loss --стоп цена
price=stopprice-Settings.loss_prosk --стоп с запасом
offset=Settings.profit_otstup --отход от тейка
defspread=Settings.profit_prosk --проск тейка
Tr_Id,STR=TP_SL(class,sec,«S»,spr_balance,stopprice,price,dealprice,offset,defspread,nil,nil)
Sorder=true
if Tr_Id==nil then
message(" "..STR,1)
end
end
if balance<0 and Open_Price~=0 then
dealprice=Open_Price-Settings.profit --тейк
stopprice=Open_Price+Settings.loss --стоп цена
price=stopprice+Settings.loss_prosk --стоп с запасом
offset=Settings.profit_otstup --отход от тейка
defspread=Settings.profit_prosk --проск тейка
Tr_Id,STR=TP_SL(class,sec,«B»,spr_balance,stopprice,price,dealprice,offset,defspread,nil,nil)
Sorder=true
if Tr_Id==nil then
message(" "..STR,1)
end
end
end
old_balance=get_balance(sec, Settings.client_code)
end
idx_prosl=idx
return nil
end
рабочий вариант, и лучше в поля для пунктов выставлять десятичный вариант для примера, у меня не получилось его ввести с 0 по умолчанию