
--переменные
keyRateCB = 7.5
classCode = "TQOB"
function CreateTable()
t_id = AllocTable()
AddColumn(t_id, 0, "Бумага", true, QTABLE_STRING_TYPE, 15)
AddColumn(t_id, 1, "Цена", true, QTABLE_DOUBLE_TYPE, 15)
AddColumn(t_id, 2, "Доходность, %", true, QTABLE_DOUBLE_TYPE, 15)
AddColumn(t_id, 3, "Дюрация, лет", true, QTABLE_DOUBLE_TYPE, 15)
AddColumn(t_id, 4, "Купон, %", true, QTABLE_DOUBLE_TYPE, 15)
AddColumn(t_id, 5, "Премия к ЦБ, бп", true, QTABLE_INT_TYPE, 15)
AddColumn(t_id, 6, "Погашение", true, QTABLE_STRING_TYPE, 15)
t = CreateWindow(t_id)
SetWindowCaption(t_id, "ОФЗ")
end
function string.split(str, sep)
local fields = {}
str:gsub(string.format("([^%s]+)", sep), function(f_c) fields[#fields + 1] = f_c end)
return fields
end
function getParamNumber(code, param)
return tonumber(getParamEx(classCode, code, param).param_value)
end
function formatData(prm)
return string.format("%02d.%02d.%04d", prm%100, (prm%10000)/100, prm/10000)
end
CreateTable()
arr = {}
sec_list = getClassSecurities(classCode)
sec_listTable = string.split(sec_list, ',')
j = 0
for i = 1, #sec_listTable do
secCode = sec_listTable[i]
securityInfo = getSecurityInfo(classCode, secCode)
short_name = securityInfo.short_name
if short_name:find("ОФЗ 26") ~= nil then
j = j + 1
r = {}
r["short_name"] = short_name
r["price"] = getParamNumber(securityInfo.code, "PREVPRICE")
r["yield"] = getParamNumber(securityInfo.code, "YIELD")
r["duration"] = getParamNumber(securityInfo.code, "DURATION")/365
couponvalue = getParamNumber(securityInfo.code, "COUPONVALUE")
couponperiod = getParamNumber(securityInfo.code, "COUPONPERIOD")
r["coupon"] = ((365/couponperiod) * couponvalue)/10
r["bonus"] = (r["yield"] - keyRateCB)*100
r["mat_date"] = getParamNumber(securityInfo.code, "MAT_DATE")
table.insert(arr, j, r)
end
end
table.sort(arr, function(a,b) return a["duration"] < b["duration"] end)
for j = 1, #arr do
row = InsertRow(t_id, -1)
SetCell(t_id, row, 0, arr[j]["short_name"])
price = arr[j]["price"]
SetCell(t_id, row, 1, string.format("%.2f", price), price)
yield = arr[j]["yield"]
SetCell(t_id, row, 2, string.format("%.2f", yield), yield)
duration = arr[j]["duration"]
SetCell(t_id, row, 3, string.format("%.2f", duration), duration)
coupon = arr[j]["coupon"]
SetCell(t_id, row, 4, string.format("%.2f", coupon), coupon)
bonus = arr[j]["bonus"]
SetCell(t_id, row, 5, string.format("%.0f", bonus), bonus)
mat_date = arr[j]["mat_date"]
SetCell(t_id, row, 6, formatData(mat_date), mat_date)
end
Обновил индикатор регрессии. Для меня это основной индикатор определения тренда.
Теперь он показывает историю. Становится видно, как над применять данный индикатор. Без истории видно, что тренд вниз. Но вот начало разворота (возможного) как раз видно по истории. Меняя degree, меняем тип: линейная, параболическая, кубическая.
Приветствую всех после длительного перерыва, связанного с рождением сына и временным переходом в реальной сектор.
В QUIK 7.14 и выше, при использовании индикаторов и скриптов QPILE / QLUA, метки могут отображаться на чёрном фоне. Решение проблемы не требует особых знаний программирования.

1. Откройте файл скрипта текстовым редактором, например Блокнотом (у меня Notepad++).
2. Нажмите Ctrl+F и введите «TRANSPARENT_BACKGROUND», подтвердите поиск. Найдётся параметр, который отвечает за прозрачность меток. Он должен иметь значение «1».
ЕСЛИ НЕ УДАЛОСЬ НАЙТИ:
Нажмите Ctrl+F и введите «ADD_LABEL», подтвердите поиск. Найдётся функция, которая отвечает за вывод меток. Рядом должны быть параметры. Нужно добавить где-нибудь среди них строку: «_map = SET_VALUE(_map,«TRANSPARENT_BACKGROUND»,1)». В вашем коде массив _map, скорее всего, будет называться иначе.

3. После изменений сохраните файл скрипта и загрузите его в QUIK снова.
1. В папке с Квиком создаем директорию LuaIndicators.
2. В этой папке создаем файл br_rub.lua, туда записываем:
Settings =
{
Name = "BR_RUB",
tag = "USDRUB",
tag1 = "BR",
line=
{
{Name = "brent_rub", Color = RGB(0, 0, 255), Type = 1,Width = 1}
}
}
function Init()
return 1
end
function OnCalculate(index)
local Out = (getCandlesByIndex(Settings.tag1, 0, index-1, 1)[0].close or 0) * (getCandlesByIndex(Settings.tag, 0, index-1, 1)[0].close or 0)
if Out > 0 then
return Out
else
return nil
end
end1. В Квике создаем график с курсом доллара (USDRUB_TOM).
2. К графику добавляем график с брентом (BR-3.18).
3. Идем в настройки графика, в разделе Дополнительно указываем Идентификатор: BR -для графика с брентом, USDRUB- для графика с курсом.
4. Добавляем индикатор (выбираем из выпадающего списка BR_RUB).

5. Уменьшаем ненужные поля. Если график не отобразился — даблкликаем на графике — жмем Применить:

Узнал, что продается робот на Lua, «Автологин терминала QUIK».
Продается то, что есть в открытом виде на quik2dde.ru
Выкладываю тут:
-- quik_login.lua
-- Автологин терминала QUIK
-- © http://qui2dde.ru/
-- Версия: 2.0
-- для Quik от версии 7.11.1.5
local w32 = require("w32")
-- логин и пароль для терминала
QUIK_LOGIN = "Uxxxxxxx"
QUIK_PASSW = "yyyyy"
function FindLoginWindow()
hLoginWnd = w32.FindWindow("", "Идентификация пользователя")
if hLoginWnd == 0 then
hLoginWnd = w32.FindWindow("", "User identification")
end
return hLoginWnd
end
timeout = 1000 -- таймаут между попытками поиска окна логина
is_run = true
function OnStop()
timeout = 1
is_run = false
end
function main()
while is_run do
sleep(timeout)
if isConnected() == 0 then
local hLoginWnd = FindLoginWindow()
if hLoginWnd ~= 0 then
local n1 = w32.FindWindowEx(hLoginWnd, 0, "", "")
local n2 = w32.FindWindowEx(hLoginWnd, n1, "", "")
local n3 = w32.FindWindowEx(hLoginWnd, n2, "", "")
local n4 = w32.FindWindowEx(hLoginWnd, n3, "", "")
w32.SetWindowText(n2, QUIK_LOGIN)
w32.SetWindowText(n3, QUIK_PASSW)
w32.SetFocus(n4)
w32.PostMessage(n4, w32.BM_CLICK, 0, 0)
end
end
end
endБлагодарности, как понимаю, следует адресовать swerg 
IsRun = true
class_code="TQBR"
function main()
-- Получает доступный id для создания
t_id = AllocTable()
-- добавить столбцы
AddColumn(t_id, 1, "Бумага", true, QTABLE_STRING_TYPE, 20)
AddColumn(t_id, 2, "Кол-во", true, QTABLE_INT_TYPE, 7)
AddColumn(t_id, 3, "Цена покупки", true, QTABLE_DOUBLE_TYPE, 14)
AddColumn(t_id, 4, "Цена текущая", true, QTABLE_DOUBLE_TYPE, 14)
AddColumn(t_id, 5, "Прибыль, р", true, QTABLE_DOUBLE_TYPE, 14)
AddColumn(t_id, 6, "Прибыль, %", true, QTABLE_DOUBLE_TYPE, 14)
t = CreateWindow(t_id)
for iRow=1, getNumberOf("depo_limits")-1, 1 do
rowInPortfolioTable = getItem("depo_limits", iRow) -- получить текущую строку из таблицы "Лимиты по бумагам"
qtyBoughtLots = tonumber(rowInPortfolioTable.currentbal)
limitKind = rowInPortfolioTable.limit_kind
if qtyBoughtLots>0 and limitKind<1 then
InsertRow(t_id, iRow)-- добавить новую строку вниз таблицы
end
end
local rows, columns = GetTableSize (t_id)
InsertRow(t_id, rows+1) -- добавить новую строку вниз таблицы для "Итого"
SetWindowCaption(t_id, "Портфель: прибыли и убытки © ramirzaev@mail.ru")
-- исполнять цикл, пока пользователь не остановит скрипт или не закроет окно таблицы
while IsRun do
if IsWindowClosed(t_id)==true then
IsRun=false
end
local currentPrice=0
local qtyBoughtLots=0
local profitAbs = 0
local profitPerc = 0
local currentSecCode= ""
local fullNameOfInstrument = ""
local limitKind = 0
local rowInPortfolioTable = {} -- строка из таблицы "Лимиты по бумагам"
local tableInstrument = {} -- данные "Таблицы текущих торгов"
local iRowInOutTable = 1
local totalInvest = 0
local totalPortfolio = 0
local totalProfit = 0
local totalPercent = 0
for iRow=0, getNumberOf("depo_limits")-1, 1 do
rowInPortfolioTable = getItem("depo_limits", iRow) -- получить текущую строку из таблицы "Лимиты по бумагам"
qtyBoughtLots = tonumber(rowInPortfolioTable.currentbal)
limitKind = rowInPortfolioTable.limit_kind
if qtyBoughtLots>0 and limitKind<1 then -- если кол-во лотов >0 и тип лимита T0
currentSecCode = rowInPortfolioTable.sec_code
fullNameOfInstrument = tostring(getParamEx(class_code, currentSecCode, "SHORTNAME").param_image or "0") --"LONGNAME"
avgPrice = tonumber(rowInPortfolioTable.awg_position_price)
currentPrice = GetAskPrice(currentSecCode)
profitAbs = (currentPrice-avgPrice)*qtyBoughtLots
profitPerc = 100*currentPrice/avgPrice - 100
totalInvest = totalInvest + avgPrice*qtyBoughtLots
totalPortfolio = totalPortfolio + currentPrice*qtyBoughtLots
SetCell(t_id, iRowInOutTable, 1, fullNameOfInstrument) -- "Бумага"
SetCell(t_id, iRowInOutTable, 2, tostring(qtyBoughtLots)) -- "Кол-во"RemoveZero(tostring(qtyBoughtLots)))
SetCell(t_id, iRowInOutTable, 3, tostring( math_round(avgPrice, 3) )) -- tostring(avgPrice)) -- "Цена покупки"
SetCell(t_id, iRowInOutTable, 4, RemoveZero(tostring(currentPrice))) -- "Цена текущая"
SetCell(t_id, iRowInOutTable, 5, tostring( math_round( profitAbs, 0)) ) -- "Прибыль, р"
SetCell(t_id, iRowInOutTable, 6, tostring(math_round(profitPerc, 1)) .."%") -- "Прибыль, %"
if profitPerc >5 then -- окрашиваем
ColourRowInGreen(iRowInOutTable)
elseif profitPerc<-5 then
ColourRowInRed(iRowInOutTable)
else
ColourRowInYellow(iRowInOutTable)
end
iRowInOutTable = iRowInOutTable+1
end
end
totalProfit = totalPortfolio - totalInvest
totalPercent = 100*totalProfit/totalInvest
SetCell(t_id, iRowInOutTable, 1, "Итого")
SetCell(t_id, iRowInOutTable, 3, tostring( math_round(totalInvest, 0) ))
SetCell(t_id, iRowInOutTable, 4, tostring( math_round(totalPortfolio, 0)))
SetCell(t_id, iRowInOutTable, 5, tostring( math_round( totalProfit, 0)) )
SetCell(t_id, iRowInOutTable, 6, tostring(math_round(totalPercent, 1)) .."%")
if profitPerc >5 then -- окрашиваем
ColourRowInGreen(iRowInOutTable)
elseif profitPerc<-5 then
ColourRowInRed(iRowInOutTable)
else
ColourRowInYellow(iRowInOutTable)
end
iRowInOutTable = iRowInOutTable+1
sleep(5000) -- пауза 5 сек.
end
--message("script table portfolio finished")
end
function ColourRowInRed(num_row)
SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(255,150,150), RGB(0,0,0), RGB(255,150,150), RGB(0,0,0))
end
function ColourRowInYellow(num_row)
SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(255,255,200), RGB(0,0,0), RGB(255,255,200), RGB(0,0,0))
end
function ColourRowInGreen(num_row)
SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(150,255,150), RGB(0,0,0), RGB(150,255,150), RGB(0,0,0))
end
function GetAskPrice(inp_Sec_Code )
local ask = tostring(getParamEx(class_code, inp_Sec_Code, "OFFER").param_value or 0)
return ask
end
-- Округляет число до указанной точности
function math_round (num, idp)
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5) / mult
end
-- удаление точки и нулей после нее
function RemoveZero(str)
while (string.sub(str,-1) == "0" and str ~= "0") do
str = string.sub(str,1,-2)
end
if (string.sub(str,-1) == ".") then
str = string.sub(str,1,-2)
end
return str
end
function OnStop()
DestroyTable(t_id)
IsRun = false
end