Блог им. 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
Но будет проблема с вечерней сессией.