Блог им. Siroeskin

Для Quik. Авто тейк & стоп. Новый подход, код.

Терминал позволяет разрабатывать самодельные индикаторы, работающие в отдельном потоке. Но индикаторам можно давать и дополнительную нагрузку, реализовывать даже легких роботов-индикаторов, торгующих автономно. Из плюсов – получаем штатное диалоговое окно средствами Квика, что-то рисуем не отходя от кассы…   Не требуется подключения внешних библиотек для работы и отображения диалоговых окон, что повышает надежность и простоту установки.
Для примера сделал вполне рабочую программку авто стоп-тейк. Торговлю для примера на скользящих делать не стал, никому не нужна, а автостоп пригодится. Проверял на собственном реальном счете – работает. Пользуйтесь на здоровье!
   Есть один недостаток: по одному графику инструмента (бумаги) не может работать индикатор, получающий данные извне этого графика (как этот) и луа скрипт с 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******* будет защищена стандартной тейк-стоп заявкой. Лонг открыт или шорт и цену открытия, и размер позиции индикатор определяет сам.

  Если тейк-стоп заявка была отклонена, появится сообщение с причиной отклонения. Надо будет выставить стоп вручную, проверить параметры и лимиты.

Важно: При изменении параметров и активации будут действовать новые параметры. Ранее выставленные тейк-стоп заявки сохранятся. 

Профитной торговли!
★33
25 комментариев
спасибо
avatar
 При увеличении позиции  выставляет на сервер брокера 
Что значит «при увеличении позиции»?
Евгений Гуревич, При каждом увеличении новый тейк-стоп на размер увеличения. Было в шорт 5, продали еще 5 — стоп на 5, потом продали 1 — еще стоп на 1.  В лонг также

СыроеШкин, у меня ошибку выдает при запуске lua-скрипта:
avatar
Иван, 64 строка такая?
 STOPPRICE=tostring(dealprice), <br>    STOPPRICE2=tostring(stopprice),
Переделай так:
 STOPPRICE=tostring(dealprice),
 STOPPRICE2=tostring(stopprice),

Откуда-то <br>  прилипла.
Попробуешь, напиши!
Здесь в коде эту строку не исправить к сожалению, время на исправление вышло.
СыроеШкин, я у себя исправил, убрал <br>, ничего не происходит. Ошибку не выдает, но и запуск не идет. Пробовал на двух квиках от разных счетов.
avatar
СыроеШкин, нет
avatar
 В таблице доступных индикаторов есть «тейк и стоп FUT_L»?
СыроеШкин, да, появилось. Спасибо!
avatar
Иван, Спасибо, Сорри за ошибку!
СыроеШкин, при заключении сделки вылетает окно где написано Превышен допустимый срок действия стоп-заявки (максимальное количество дней 30, по 2016.12.6 включительно)., где исправить? Спасибо
avatar
HD 128621, стоп заявку сейчас ставит «до отмены», брокер видать автоматически не подставляет дату экспирации. в строке, задающей срок 
EXPIRY_DATE='GTC',
 можно указывать следующие значения:

«GTC» – до отмены,
«TODAY» — до окончания текущей торговой сессии,
Дата в формате «ГГММДД».
только в верхних кавычках, как в коде.

avatar
СыроеШкин, Благодарю!
avatar
++
avatar
Спасибо за Вашу помощь!
avatar
Спасибо! А можно где сменить тип стоп заявки на рыночную? Часто приходится двигать стоп, если делать это на графике, при лимитной заявке, получается отложка(
avatar
Добрый день! Как оставить в коде только один тейк-профит, а стоп-лосс убрать.
avatar
Добрый день!
Индикатор хороший, но опробовать не удалось.
Его нет в списке доступных индикаторов. Папка с индикаторами создана давно. Все остальные индикаторы отображаются
avatar

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 по умолчанию

avatar

теги блога СыроеШкин

....все тэги



UPDONW
Новый дизайн