Блог им. andrey_koltsov
Для реализации одной задумки в один прекрасный момент мне необходимо было узнать какие акции, торгуемые на ММВБ, являются самыми волатильными за определенный период…
Скачивать историю по всем акциям и прогонять ее через Excel слишком долго и нудно…
Захотелось написать робота, чтобы он сам за меня все посчитал… Но так как я знаком только с языком программирования Qpile, то мне пришлось столкнуться с проблемой – для получения данных по свечкам используется функция «GET_CANDLE», а она работает только при открытом графике… Открывать в Квике три сотни графиков мне тоже не хотелось…
На помощь пришла «Текущая таблица параметров» в QUIK… Но у нее один недостаток – информация в ней содержится только за текущий день. Что-же делать? Можно и подождать…
Пришлось быстренько написать робота и запустить его для накапливания информации. Каждый торговый день после 18:50 робот сохраняет информацию в файлы и одновременно отображает ее. Формула для расчета простая: (Max-Min)/среднедневная цена. То есть, волатильность в процентном выражении от среднедневной цены.
Далее копируем таблицу в буфер и сортируем в Excel как нам надо...
-----
Кому надо копируйте. Мне не жалко.
В коде надо обязательно указать путь к папке, в которой будет сохраняться рабочая информация и указать за какой период накапливать и рассчитывать волатильность.
Код:
PORTFOLIO_EX Koltsov-ATR-1.0;
DESCRIPTION Koltsov-ATR-1.0;
CLIENTS_LIST ALL_CLIENTS;
FIRMS_LIST FIRMID;
USE_CASE_SENSITIVE_CONSTANTS;
PROGRAM
'________________________________________________________________________________________
DELETE_ALL_ITEMS()
'---------- НАСТРОЙКИ ПОЛЬЗОВАТЕЛЯ ----------
Classcode = "TQBR" 'Код Класса
period = 14 'За какой период рассчитываем ATR
papka = "C:/Quik_Open/Info/raschet/ATR/" 'Папка для сохранения информации (НЕОБХОДИМО СОЗДАТЬ САМОСТОЯТЕЛЬНО!!!)
'________________________________________________________________________________________
line = 0 'Идентификатор для подсветки строк
'------------------
'Задаем время онлайн
Vrema = GET_INFO_PARAM ("SERVERTIME") 'определяем время
Hour0="" & (0 + substr(Vrema,0,2))
Min0 =floor (substr(Vrema,3,2))
Sec0 =floor (substr(Vrema,6,2))
if len(Sec0) == 1
Sec0= "0" & Sec0
end if
if len(Min0) == 1
Min0= "0" & Min0
end if
if len(Hour0) == 1
Hour0= "0" & Hour0
end if
Time0=Hour0 & Min0 & Sec0 'Время on-line
Time0=Time0+0
Time=Hour0 & Min0 & 0 & 0 'Время с округлением до минуты
'------------------
'Задаем дату
dats = GET_INFO_PARAM ("TRADEDATE")
Year="" & (0 + substr(dats,6,4))
Month="" & (0 + substr(dats,3,2))
if len(Month) == 1
Month= "0" & Month
end if
Day="" & (0 + substr(dats,0,2))
if len(Day) == 1
Day= "0" & Day
end if
Date = Year & Month & Day 'переводим в нужный формат
Date = Date+0
'===============================================================================================================================
'===============================================================================================================================
pozicii_a =0
pozicii_a =GET_CLASS_SECURITIES(Classcode) 'Получение списка кодов бумаг (в одной строке через запятую)
razdelitel=find(pozicii_a,0,",")+0
pozicii_b =0
pozicii_b =len(pozicii_a)/(razdelitel+1) 'Сколько всего бумаг в списке (примерно)
pozicii_c =0
razdelitel=0
'===============================================================================================================================
'===============================================================================================================================
'Начало основного цикла
for cikl from 1 to pozicii_b
'==============================================================================
'Получаем Код бумаги из Текущей таблицы параметров
razdelitel_new = find(pozicii_a,(razdelitel+1),",")+0
if razdelitel_new>razdelitel
razdelitel = razdelitel_new
Seccode = substr(pozicii_a,pozicii_c,(razdelitel-pozicii_c))
pozicii_c = razdelitel+1
'----------
today_f = papka & "today_" & Seccode & ".log"
ATR_f = papka & "ATR_" & Seccode & ".log"
'----------
'Получение Краткого названия бумаги из Таблицы текущих значений параметров
Seccode_name = ""
Seccode_name = GET_PARAM_EX (Classcode, Seccode, "SHORTNAME")
Seccode_name = GET_VALUE(Seccode_name,"PARAM_IMAGE")
'----------
'Максимальная цена сделки из Таблицы текущих значений параметров
HIGH_now = 0
HIGH_now = GET_PARAM_EX (Classcode, Seccode, "HIGH")
HIGH_now = GET_VALUE(HIGH_now,"PARAM_VALUE")+0
'----------
'Минимальная цена сделки из Таблицы текущих значений параметров
LOW_now = 0
LOW_now = GET_PARAM_EX (Classcode, Seccode, "LOW")
LOW_now = GET_VALUE(LOW_now,"PARAM_VALUE")+0
'----------
'Дата торгов из Таблицы текущих значений параметров
TRADE_DATE = 0
TRADE_DATE = GET_PARAM_EX (Classcode, Seccode, "TRADE_DATE_CODE")
TRADE_DATE = GET_VALUE(TRADE_DATE,"PARAM_VALUE")+0
'----------
'Расчет волатильности за текущий день
ATR = 0
today = 0
if HIGH_now>0 and LOW_now>0
ATR = (HIGH_now-LOW_now)/((HIGH_now+LOW_now)/2)*100 'Волатильность в % от среднедневной цены
today = READ_LINE(today_f,1,"error")+0
if Date<>today and Date=TRADE_DATE and Time0>185000 and Date>0 and ATR>0
CLEAR_FILE(today_f)
WRITELN (today_f,Date)
WRITELN (ATR_f,ATR)
end if 'Date<>today
end if 'HIGH_now>0 and LOW_now>0
'----------
'Расчет общей волатильности
ATR_all = 0
str = 0
str = GET_FILE_LEN(ATR_f)+0 'Сколько строк в файле
for n from 1 to str
ATR0 = READ_LINE(ATR_f,n,"error")+0
ATR_all = ATR_all + ATR0
end for
if ATR_all>0 and str>0
ATR_all = ATR_all/str
end if
'----------
'Расчет волатильности за период
ATR_per = 0
str = 0
p = 0
str = GET_FILE_LEN(ATR_f)+0 'Сколько строк в файле
period_on = str-period+1
if period_on<1
period_on=1
end if
for n from period_on to str
ATR0 = READ_LINE(ATR_f,n,"error")+0
ATR_per = ATR_per + ATR0
p = p+1
end for
if ATR_per>0 and p>0
ATR_per = ATR_per/p
end if
'==============================================================================
output=CREATE_MAP()
output=SET_VALUE(output,"1",Seccode_name)
output=SET_VALUE(output,"2",HIGH_now)
output=SET_VALUE(output,"3",LOW_now)
output=SET_VALUE(output,"4",ATR)
output=SET_VALUE(output,"5",ATR_per)
output=SET_VALUE(output,"6",ATR_all)
ADD_ITEM(cikl,Output)
'----------
'Подсветка четных линий
if line=1
SET_ROW_COLOR_EX (cikl, "RGB(235,235,235)", "DEFAULT_COLOR", "DEFAULT_COLOR", "DEFAULT_COLOR") 'легкая серая заливка слабая
line=0
else
line=line+1
end if
'==============================================================================
'Конец основного цикла
end if 'razdelitel_new>razdelitel
end for
'==============================================================================
END_PROGRAM
PARAMETER 1;
PARAMETER_TITLE Бумага;
PARAMETER_DESCRIPTION Бумага;
PARAMETER_TYPE STRING(32);
END
PARAMETER 2;
PARAMETER_TITLE MAX;
PARAMETER_DESCRIPTION MAX;
PARAMETER_TYPE STRING(32);
END
PARAMETER 3;
PARAMETER_TITLE MIN;
PARAMETER_DESCRIPTION MIN;
PARAMETER_TYPE STRING(32);
END
PARAMETER 4;
PARAMETER_TITLE ATR-now (%);
PARAMETER_DESCRIPTION ATR (%);
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER 5;
PARAMETER_TITLE ATR-per (%);
PARAMETER_DESCRIPTION ATR (%);
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER 6;
PARAMETER_TITLE ATR-all (%);
PARAMETER_DESCRIPTION ATR (%);
PARAMETER_TYPE NUMERIC(10,2);
END
END_PORTFOLIO_EX
Для акций, предлагаю, допилить и сделать расчет для нового индекса ММВБ (который включает 50 бумаг)
Кстати, скрипт отлично зашел бы для фьючей.
Жаль «плюсануть» не могу, новичЁк на форуме.
Чтобы аналогично показывало на фьючерсах, надо в настройках пользователя код класса TQBR заменить на SPBFUT
Но будет проблема с вечерней сессией.
Да. (HIGH+LOW)/2
Попробуйте поверить на слово, т.к. и QPile и QLua мне пришлось изучать с нуля. Начинал, как и Вы, с QPile. Сейчас полностью перешел на C#.
Например, для получения ВСЕЙ истории свечек, которую может хранить Квик, по одному инструменту, в Lua достаточно использовать всего одну команду «CreateDataSource». И никаких таблиц в квике открывать при этом не надо.
Чтобы аналогично показывало на фьючерсах, надо в настройках пользователя код класса TQBR заменить на SPBFUT
Но будет проблема с вечерней сессией.