В процессе разбирательства с АПИ написал несколько полезных для меня утилит. Скорее всего они примитивные, но возможно кому-то понадобятся. Или пригодятся как примеры.
Я не знаю как прицепить к сообщению аттач, поэтому воткну тут самый примитивный из индикаторов Остальное уже большевато для вставки в текст, а как прицепить файл я не нашел. Если кому понадобится что-нить - свистите.
-- ********************************************************************
-- Can displays every candle field as separate graph (see "Settings" for details)
-- ********************************************************************
-- Stupid QUIK: dofile() doesnt work in Indicators :-/
-- ********************************************************************
LOG_FILE = "..\\quick_lua.log";
function log(fmt, ... )
-- Decomment next line to allow global logging
-- _log( fmt, ... )
end
function _log( fmt, ... )
local f = io.open( LOG_FILE, "a+" );
if not f then
f = io.open( LOG_FILE, "w" );
end
if not f then
out( "Error write log file: %s", LOG_FILE );
abort();
end
f:write( strtime(os.date("*t")) .. " " .. string.format( fmt, ... ) .. "\n" );
f:close();
end
function out( fmt, ... ) message( string.format( fmt, ... ), 3) end
function abort(fmt, ... ) out( fmt, ... ); PROGRAMM_ABORT(); end
function iif( cond, y, n ) if cond then return y; else return n; end end
function strtime( tm ) return string.format("%4d-%02d-%02d %02d:%02d:%02d", tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec) end
-- ********************************************************************
-- ********************************************************************
Settings={
Name = "!__Values",
line = {
{ Name = "High", Color = RGB( 112,112,112 ), Width = 1, Type = TYPE_LINE },
{ Name = "Low", Color = RGB( 112,112,112 ), Width = 1, Type = TYPE_LINE },
{ Name = "Open", Color = RGB( 112,255,255 ), Width = 1, Type = TYPE_LINE },
{ Name = "Close", Color = RGB( 112,255,255 ), Width = 1, Type = TYPE_LINE },
{ Name = "Vol", Color = RGB( 128,128,255 ), Width = 6, Type = TYPE_HISTOGRAM },
{ Name = "Median", Color = RGB( 100,215,0 ), Width = 1, Type = TYPE_LINE },
{ Name = "Triple", Color = RGB( 200,67,22 ), Width = 1, Type = TYPE_LINE },
{ Name = "Wide", Color = RGB( 190,30,170 ), Width = 1, Type = TYPE_LINE },
nil
},
Open = "n", -- If set to 'y' will display candle.open graph
Close = "n", -- If set to 'y' will display candle.close graph
High = "y", -- If set to 'y' will display candle.high graph
Low = "y", -- If set to 'y' will display candle.low graph
Vol = "n", -- If set to 'y' will display candle.volume graph
Median = "y", -- If set to 'y' will display calculated "median" graph
Triple = "n", -- If set to 'y' will display calculated "triple" graph
Wide = "n", -- If set to 'y' will display calculated "wide" graph
Margin = 0.01, -- Additional bounds added to High, Low, Open and Close fields on display
-- Used just for better graph view
nil
}
function Init()
return 8
end
function OnCalculate(idx)
local h = H(idx)
local l = L(idx)
if not h or h < 10 then
return nil
end
if h < l then h,l = l,h; end
local o = O(idx)
local c = C(idx)
if o < c then o,c = c,o; end
local v = V(idx)
local m = (h+l)/2
local t = (h+l+C(idx))/3
local w = (h+l+C(idx)*2)/4
if Settings.Open ~= "y" then o = nil; else o = o + Settings.Margin; end
if Settings.Close ~= "y" then c = nil; else c = c - Settings.Margin; end
if Settings.High ~= "y" then h = nil; else h = h + Settings.Margin; end
if Settings.Low ~= "y" then l = nil; else l = l - Settings.Margin; end
if Settings.Vol ~= "y" then v = nil; end
if Settings.Median ~= "y" then m = nil; end
if Settings.Triple ~= "y" then t = nil; end
if Settings.Wide ~= "y" then w = nil; end
return h,l, o,c, v,m,t,w;
end
Вот еще один, которым постоянно пользуюсь Предназначен за рисованием коридора для средне-взвешенного значения инструмента по всем сделкам. Т.е. после установки сделки начинает рисовать коридор профит\лос (там на графике треугольники сделки и горизонтальные линии границы). [URL=http://radikal.ru/fp/eb4e1ac6826140a5a48423cc46bb1377][IMG]http://s018.radikal.ru/i520/1502/39/3bb965470ed2t.jpg[/IMG][/URL]
Из утилит сделал экспорт данных свечей с графиков в CSV т.к. не смог найти средство как это сделать штатно. И еще утилитка рассчета суммарной прибыльности по сделкам: [URL=http://radikal.ru/fp/6f660bd4842941e7842e2ddd37026b6f][IMG]http://s010.radikal.ru/i313/1502/a2/a9d90aa9df2at.jpg[/IMG][/URL]
Если вас устроит вертикальная линия, идущая от самого низа графика до уровня, заданного определенным значением цены, то можно обойтись без меток и нарисовать ее с помощью индикатора, пример которого приведен ниже:
Код
Settings =
{
Name = "v_line",
line =
{
{
Name = "vertical_line",
Color = RGB(0, 255, 255), --
Type = TYPE_HISTOGRAM -- важно задать тип "гистограмма", тогда получатся вертикальные линии
}
}
}
function Init()
return 1
end
function OnCalculate(index)
if (T(index).hour == 10) and (T(index).min == 0) then
return H(index) + (H(index) - L(index)) -- линия идет от самого низа графика и оканчивается немного выше нужной нам свечи
end
end
Этот индикатор будет рисовать вертикальную линию на свече, которая была в 10:00.
Чтобы вертикальная линия не перекрывала тени свечи, можно после наложения на график индикатора поменять "Порядок графиков (индикаторов)" с помощью пункта контекстное меню "Параметры текущего окна".
1) сколько штук их можно сделать на одном графике? 2) можно задать тип линии и толщину? спасибо заранее за ответ
код - ниже 1. сколько угодно (константное число) 2. толщину - не помню, а тип - да, из набора существующих. их, если правильно помню, штук 5, в доке не описаны, но можно просто перебрать числами от 0
-- ********************************************************************
-- Trades graphs
-- Display bounds for every trade you made with profit and loss bounds.
-- Automatically calculate balanced $$ cost
-- Graph has 3 lines:
-- 1. Green line - 'profit' value.
-- If you overcome of this line you balance increases
-- 2. Blue line - 'zero' value.
-- At this value you trade will have zero balance
-- Note: Blue line exists only if you $$ balance nonzero.
-- 3. Red line - 'possible loss' value
-- Indicates value of acceptable loss.
-- If you overcome this line you must make a dessision to close the deal in MINUS or hope price will grows back...
-- ********************************************************************
-- ********************************************************************
-- Stupid QUIK: dofile() doesnt work in Indicators :-/
-- So we must declare all utils in a single file.
-- !!NOTES!!:
-- For use logging you must set "LOG_FILE" to correct log file name
-- For enable global logging decomment "_log" call in "log()" function below
-- ********************************************************************
LOG_FILE = "..\\quick_lua.log";
function log(fmt, ... )
-- Decomment next line to allow global logging
-- _log( fmt, ... )
end
function _log( fmt, ... )
local f = io.open( LOG_FILE, "a+" );
if not f then
f = io.open( LOG_FILE, "w" );
end
if not f then
out( "Error write log file: %s", LOG_FILE );
abort();
end
f:write( strtime(os.date("*t")) .. " " .. string.format( fmt, ... ) .. "\n" );
f:close();
end
function out( fmt, ... ) message( string.format( fmt, ... ), 3) end
function abort(fmt, ... ) out( fmt, ... ); PROGRAMM_ABORT(); end
function iif( cond, y, n ) if cond then return y; else return n; end end
function strtime( tm ) return string.format("%4d-%02d-%02d %02d:%02d:%02d", tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec) end
function cmptime( e, b )
if e.year > b.year then return 1; end
if e.year < b.year then return -1; end
if e.month > b.month then return 1; end
if e.month < b.month then return -1; end
if e.day > b.day then return 1; end
if e.day < b.day then return -1; end
if e.hour > b.hour then return 1; end
if e.hour < b.hour then return -1; end
if e.min > b.min then return 1; end
if e.min < b.min then return -1; end
if e.sec > b.sec then return 1; end
if e.sec < b.sec then return -1; end
return 0;
end
-- ********************************************************************
-- Settings
-- ********************************************************************
Settings = {
Name = "!__Trades",
line = {
{ Name = "Balans", Color = RGB( 4,53,106 ), Type = 4, Width = 1 },
{ Name = "BalPositive", Color = RGB( 47,143,7 ), Type = 4, Width = 1 },
{ Name = "BalProtect", Color = RGB( 244,72,70 ), Type = 4, Width = 1 },
},
Add_Positive = 0.05, -- Value addon to indicate positive balans including all trade comissions
Add_Protect = 0.15, -- Possible loss value
EmptyValue = -1, -- Value will be used to set in graph if you do not have open trades.
-- Value of -1 indicates what value will not be stored.
UseGraphClass = 0, -- If nonzero trades will use sec_code attached to graph
-- If zero the USD_TOM and USD_TOD will be used simultaneous
USD_TOM = "USD000UTSTOM", -- Money codes used if "UseGraphClass=0" (sec_code STRING Код бумаги заявки)
USD_TOD = "USD000000TOD",
CLASS_CODE = "CETS", -- Class code used to access money code (class_code STRING Код класса)
Day_StartValue = 0, -- Starting day value
-- Amount of $$ you have already at your account at start of trading day
-- If zero, Trades will use first trade made as starting point.
Day_StartPrice = 0, -- Balance price of account $$. Useless if "Day_StartValue = 0"
Day_LastOnly = 1, -- Calculate whole trades or the current day only
-- If "Day_LastOnly=1" all trades in days before "Day_xxx" will be ignored
Day_year = 2015, -- Current trades day (year)
Day_mon = 1, -- Current trades day (month)
Day_day = 30, -- Current trades day (day)
}
-- ********************************************************************
-- Local data
-- ********************************************************************
TradeTable = {}
TradeTableLength = 0
LastTableLength = 0
GraphCC = "";
GraphSC = "";
CalcStartTime = nil
-- ********************************************************************
function Filter( cc, sc, fl )
if Settings.UseGraphClass > 0 then
if cc ~= GraphSC then return false; end
if sc ~= GraphCC then return false; end
else
if cc ~= Settings.CLASS_CODE then return false; end
if sc ~= Settings.USD_TOM and sc ~= Settings.USD_TOD then return false; end
end;
-- бит 0 (0x1) Заявка активна, иначе - не активна
-- бит 1 (0x2) Заявка снята. Если флаг не установлен и значение бита <0> равно <0>, то заявка исполнена
-- бит 2 (0x4) Заявка на продажу, иначе - на покупку. Данный флаг для сделок и сделок для исполнения определяет направление сделки (BUY/SELL)
if bit.band(fl,0x1) == 0x1 then return false; end
if bit.band(fl,0x2) == 0x2 then return false; end
return true;
end
function FillTradeTable()
local num = getNumberOf("trades")
if num == 0 then
TradeTable = {};
TradeTableLength = 0;
LastTableLength = 0;
return;
end
if num <= LastTableLength then
return;
end
log( "FillTradeTable %d->%d", LastTableLength, num );
it = {}
while LastTableLength < num do
it = getItem( "trades", LastTableLength );
if Filter( it.class_code, it.sec_code, it.flags ) then
log( "add[%d]: %2d) qty: %3d, price: %3.4f, bs: %s, tm: %s",
TradeTableLength, LastTableLength,
it.qty,
it.price,
iif( bit.band(it.flags,0x04) == 0x04, "SELL", "BUY " ),
strtime(it.datetime),
nil );
TradeTable[ TradeTableLength ] = {
Count = it.qty,
Price = it.price,
Sell = iif( bit.band(it.flags,0x04) == 0x04, true, false ),
Time = it.datetime,
}
TradeTableLength = TradeTableLength + 1;
end
LastTableLength = LastTableLength+1;
end
log( "Added %d items (%d)", TradeTableLength, LastTableLength );
end
function CalcValue( tm )
if cmptime( CalcStartTime, tm ) > 0 then
return 0,0;
end
local n
local hdr = false
local vol = Settings.Day_StartValue
local price = Settings.Day_StartPrice
for n=0,TradeTableLength-1 do
it = TradeTable[n];
if it == nil then return 0,0; end;
if cmptime( it.Time, tm ) > 0 then
break;
end;
-- if not hdr then log( "CalcValue[%s]", strtime(tm) ); hdr = true; end
cn = iif( it.Sell, -it.Count, it.Count );
oldv = vol
vol = vol + cn
if vol ~= 0 then
price = price*oldv/vol + it.Price*cn/vol;
else
price = it.Price;
end;
--log( "time [%s] %d / %3.4f = %3d / %3.4f", strtime(it.Time), iif(it.Sell,-it.Count,it.Count), it.Price, vol, price );
end
return price, vol;
end
function OnCalculate(idx)
if GraphCC == "" then
ds = getDataSourceInfo();
GraphCC = ds.sec_code;
GraphSC = ds.class_code;
log( "Init codes: cc: %s, sc: %s", ds.class_code, ds.sec_code );
if GraphCC == "" or GraphSC == "" then
message( string.format("Invalid CC/SC: [%s]/[%s]", GraphCC, GraphSC) );
GraphCC = "-";
return nil;
end
end
if GraphCC == "" or GraphSC == "" then
return nil;
end
if not CalcStartTime then
if Settings.Day_LastOnly then
CalcStartTime = { year = Settings.Day_year, month = Settings.Day_mon, day = Settings.Day_day, hour = 10, min = 0, sec = 0 };
else
CalcStartTime = T(idx)
end
end
FillTradeTable();
price, vol = CalcValue( T(idx) );
if vol == 0 and price == 0 then
if Settings.EmptyValue < 0 then
return nil;
else
return Settings.EmptyValue,Settings.EmptyValue,Settings.EmptyValue;
end
elseif vol == 0 then
return nil,
price-Settings.Add_Positive,
price+Settings.Add_Protect;
else
return price,
iif( vol > 0, price+Settings.Add_Positive, price-Settings.Add_Positive ),
iif( vol > 0, price-Settings.Add_Protect, price+Settings.Add_Protect );
end
end
function Init()
return 3
end
-- For test run as std script
function main()
FillTradeTable();
tm = { year = 2015, month = 1, day = 30, hour = 16, min = 0, sec = 0 };
price, vol = CalcValue( tm );
log( "price: %3.4f, vol: %d", price, vol );
end
Чтобы не рисовалась переходы с горизонтальных участков надо в самом квике установить тип графика то ли в гистограму то ли еще что-то подобное Не помню уже
вопрос тако с помощью данного решения я допустим реализую индикатор который будет рисовать аналоги баз из 4-5 баров и это все на 35 графиках - будет ли все это тормозить или нормально работать почему спрашиваю - сделал просто поиск баз с выводом в текстовое окно в атф транзак - когда 1-4 графика обсчитывает вроде еще ничего - но как 10-15 жуткие тормоза!
А возможно ли на Lua нарисовать динамический POC, который будет отрисовывать максимальный объём. Например на 1,3240 прошёл объём 300, индикатор рисует линию и рисует её до тех пор пока на определенном уровне не появиться больший объём, например 1,3250 400. Вот пример. И не будет ли после добавления индикатора тормозить график...?
AndrejNaMillion пишет: А возможно ли на Lua нарисовать динамический POC, который будет отрисовывать максимальный объём. Например на 1,3240 прошёл объём 300, индикатор рисует линию и рисует её до тех пор пока на определенном уровне не появиться больший объём, например 1,3250 400. Вот пример. И не будет ли после добавления индикатора тормозить график...?
Дмитрий написал: Если вас устроит вертикальная линия, идущая от самого низа графика до уровня, заданного определенным значением цены, то можно обойтись без меток и нарисовать ее с помощью индикатора, пример которого приведен ниже:
Код
Settings =
{
Name = "v_line" ,
line =
{
{
Name = "vertical_line" ,
Color = RGB ( 0 , 255 , 255 ), --
Type = TYPE_HISTOGRAM -- важно задать тип "гистограмма", тогда получатся вертикальные линии
}
}
}
function Init ()
return 1
end
function OnCalculate (index)
if (T(index).hour = = 10 ) and (T(index).min = = 0 ) then
return H(index) + (H(index) - L(index)) -- линия идет от самого низа графика и оканчивается немного выше нужной нам свечи
end
end
Этот индикатор будет рисовать вертикальную линию на свече, которая была в 10:00.
Чтобы вертикальная линия не перекрывала тени свечи, можно после наложения на график индикатора поменять "Порядок графиков (индикаторов)" с помощью пункта контекстное меню "Параметры текущего окна".
Доброго дня. Подскажите, а есть возможность настраивать время отображения индикатора.? Скажем нужно отметить новости в 15:30, 16:30, 21:00. как это сделать что бы прописать сразу?
RayIntraday написал: Подскажите, а есть возможность настраивать время отображения индикатора.?Скажем нужно отметить новости в 15:30, 16:30, 21:00. как это сделать что бы прописать сразу?
Добавьте внутри кода индикатора анализ времени свечи, чтобы он рисовался только на свечах с заданным временем, а в остальных случаях возвращал значение nil
-- ********************************************************************
-- Trades graphs
-----------------------//--------------------------------------
end
Доброго времени Jourim66, пытался запустить данный индикатор на RIZ1, результат получился нулевой. Возможно ли его использовать на фьючах или акциях? И ещё такой вопрос, как можно изменить этот индикатор, что бы он отрисовывал верхнюю и нижнюю границы 68% (70%) объёмного профиля рынка за час, ежечасно.? Что бы получилось нечто похожее на вот это: