Написать программу, осуществляющую поиск ценных бумаг с наибольшим коридором поддержки (КП). Поиск выполняется в пределах одного торговой сессии. Результат отображается в программируемой таблице OWN.
Величина коридора поддержки, образуемый линиями сопротивления и поддержки (ЛС и ЛП), определяется как разность между максимальной и минимальной ценами на выбранном временном интервале (рис. 1).
Рис. 1. Коридор поддержки
На входе программы задаются дата tradeDate торговой сессии и список scList кодов бумаг
На выходе формируется таблица OWN с данными о бумагах, имеющих набольший КП (рис. 2)
Рис. 2. Бумаги с наибольшим коридором поддержки
Результирующая таблица будет иметь более одной строки, если несколько бумаг обладают максимальным КП.
В результирующей таблице отображаются следующие сведения (в скобках указывается имя столбца):
Число ненулевых свеч будет меньше, если неточно задан временной интервал. В частности, Not null candles < All candles, если выбрана незакрытая торговая сессия (дата текущей торговой сессия возвращается функцией GET_TRADE_DATE).
Программа составляется на языке QPILE, запуск программы выполняется в системе QUIK.
Используется следующая схема:
Программа содержит функции addTCllctn, rslts и addSomeValues, соответственно отвечающие пунктам 4, 5 и 6 вышеприведенной схемы решения задачи. Задание входных данных и вывод результата выполняется в теле основной программы.
Заметим, что функция GET_VALUE возвращает строку, для преобразования строки в число программе используется следующее выражение (на примере параметра OPEN):
pn = 0 + get_value(mpCndl, "OPEN")
Почие пояснения к нижеследующей программе оформлены в виде комментария.
PORTFOLIO_EX ЦБ с максимальным КП;
DESCRIPTION Поиск ЦБ с максимальным КП;
CLIENTS_LIST ALL_CLIENTS;
FIRMS_LIST ALL_FIRMS;
PROGRAM
'
' Формирует коллекцию cllctnMp массивов с данными о ценных бумах из списка scList
func addTCllctn(scList, n, tn)
cllctnMp = create_collection()
for sc in scList
cc = get_value(get_security_info("", sc), "CLASS_CODE")
' Начало торговой сессии
hr = 10
' Интервал (расстояние между свечами)
mnts = -tn
hgh = -1
lw = 100000
vlm = 0
prAvg = 0
' Число ненулевых свеч
nLL = 0
for k from 1 to n
mnts = mnts + tn
if mnts >= 60
mnts = mnts - 60
hr = hr + 1
end if
tm = hr * 10000 + mnts * 100
' dt - дата свечи, формат YYYYMMDD (20050527 = 27 мая 2005 г)
' tm - время опрашиваемой свечи, формат hmmss (163500 = 16 ч. 35 мин)
mpCndl = get_candle(cc, sc, "", tn, "PRICE", dt, tm)
pn = 0 + get_value(mpCndl, "OPEN")
if pn > 0
h = 0 + get_value(mpCndl, "HIGH")
l = 0 + get_value(mpCndl, "LOW")
cl = 0 + get_value(mpCndl, "CLOSE")
nLL = nLL + 1
prAvg = prAvg + pn + cl
' Находим максимальную и минимальную цену рассматриваемой бумаги
if h > hgh
hgh = h
end if
if l > 0 and l < lw
lw = l
end if
vlm = vlm + get_value(mpCndl, "VOLUME")
end if
end for
' Ширину КП вычисляем с точность до 2-х десятичных знаков
cr = 0 + apply_scale(hgh - lw, 2)
if nLL > 0
' Средняя цена бумаги
prAVg = 0.5 * prAVg / nLL
end if
' Формируем массив mp с данными о текущей бумаге и заносим его в коллекцию cllctnMp
mp = create_map()
mp = set_value(mp, "cc", cc)
mp = set_value(mp, "sc", sc)
mp = set_value(mp, "nm", get_value(get_param_ex(cc, sc, "SHORTNAME"), "PARAM_IMAGE"))
mp = set_value(mp, "high", hgh)
mp = set_value(mp, "low", lw)
mp = set_value(mp, "volume", vlm)
mp = set_value(mp, "cr", cr)
mp = set_value(mp, "avg", prAvg)
mp = set_value(mp, "nLL", nLL)
mp = set_value(mp, "n", n)
' crMx - ширина наибольшего КП
if cr > crMx
crMx = cr
end if
cllctnMp = insert_collection_item(cllctnMp, 0, mp)
end for
result = cllctnMp
end func
'
' Формирует коллекцию cllctnMpRslt из массивов коллекции cllctnMp с наибольшим КП
func rslts(cllctnMp, crMX)
cllctnMpCnt = get_collection_count(cllctnMp) - 1
cllctnMpRslt = create_collection()
for k from 0 to cllctnMpCnt
mp = get_collection_item(cllctnMp, k)
cr = 0 + get_value(mp, "cr")
' crMx - ширина наибольшего КП
if cr = crMx
cllctnMpRslt = insert_collection_item(cllctnMpRslt, 0, mp)
end if
end for
result = cllctnMpRslt
end func
'
' Добавляет дополнительные сведения в массивы коллекции cllctnMpRslt
func addSomeValues(n, tn, df, cllctnMpRsltCnt)
for k from 0 to cllctnMpRsltCnt
mp = get_collection_item(cllctnMpRslt, k)
cc = get_value(mp, "cc")
sc = get_value(mp, "sc")
hgh = 0 + get_value(mp, "high")
lw = 0 + get_value(mp, "low")
hr = 10
mnts = -tn
nH = 0
nL = 0
pn0 = 0
cndlsH = ""
cndlsL = ""
for m from 1 to n
mnts = mnts + tn
if mnts >= 60
mnts = mnts - 60
hr = hr + 1
end if
tm = hr * 10000 + mnts * 100
mpCndl = get_candle(cc, sc, "", tn, "PRICE", dt, tm)
pn = 0 + get_value(mpCndl, "OPEN")
if pn > 0
if pn0 = 0
pn0 = pn
end if
h = (1.0 + df) * get_value(mpCndl, "HIGH")
l = (1.0 - df) * get_value(mpCndl, "LOW")
cl = (1.0 - df) * get_value(mpCndl, "CLOSE")
if mnts < 10
mnts2 = "0" & mnts
else
mnts2 = mnts
end if
if h - hgh >= 0
' Число свеч, близких к максимальной цене
nH = nH + 1
' Список свеч, близких максимальной цене
cndlsH = cndlsH & "; " & hr & "." & mnts2
end if
if l - lw <= 0
' Число свеч, близких к минимальной цене
nL = nL + 1
' Список свеч, близких к минимальной цене
cndlsL = cndlsL & "; " & hr & "." & mnts2
end if
end if
end for
' Пополняем массив коллекции cllctnMpRslt
mp = set_value(mp, "pn", pn0)
mp = set_value(mp, "cl", cl)
mp = set_value(mp, "nHigh", nH)
mp = set_value(mp, "nHigh", nH)
mp = set_value(mp, "nLow", nL)
mp = set_value(mp, "cndlsH", substr(cndlsH, 2, len(cndlsH) - 2))
mp = set_value(mp, "cndlsL", substr(cndlsL, 2, len(cndlsL) - 2))
' Модифицируем соответствующий элемент коллекции cllctnMpRslt
cllctnMpRslt = set_collection_item(cllctnMpRslt, k, mp)
end for
end func
'
' Основная программа
' Список кодов ценных бумаг
scList = "GAZP, TATNP, SBERP"
' Дата торговой сессии
tradeDate = get_trade_date()
yr = get_value(tradeDate, "YEAR")
mnth = get_value(tradeDate, "MONTH")
d = get_value(tradeDate, "DAY")
dt = yr * 10000 + mnth * 100 + d
' Интервал (расстояние между свечами в минутах)
tn = "5"
' Число опрашиваемых свечей (540 - число минут в торговой сессии)
n = 540 / tn - 1
crMx = -1
' Коэффициент, используемый для формирования списков High candels и Low candels
df = 0.001
' Формируем коллекцию cllctnMp массивов с данными о ценных бумах из списка scList
cllctnMp = addTCllctn(scList, n, tn)
' Формируем коллекцию cllctnMpRslt из массивов коллекции cllctnMp с наибольшим КП
cllctnMpRslt = rslts(cllctnMp, crMx)
cllctnMpRsltCnt = get_collection_count(cllctnMpRslt) - 1
' Добавляем дополнительные сведения в массивы коллекции cllctnMpRslt
addSomeValues(n, tn, df, cllctnMpRsltCnt)
' Очищаем таблицу OWN
delete_all_items()
' Заполняем таблицу OWN
for k from 0 to cllctnMpRsltCnt
mp = get_collection_item(cllctnMpRslt, k)
add_item(1, mp)
end for
END_PROGRAM
PARAMETER nm;
PARAMETER_TITLE Бумага;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE STRING(50);
END
PARAMETER pn;
PARAMETER_TITLE Open;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER cl;
PARAMETER_TITLE Close;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER high;
PARAMETER_TITLE High price;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER low;
PARAMETER_TITLE Low price;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER volume;
PARAMETER_TITLE Volume;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(15,0);
END
PARAMETER cr;
PARAMETER_TITLE Criteria;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER avg;
PARAMETER_TITLE Avg price;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,2);
END
PARAMETER nLL;
PARAMETER_TITLE Not null candles;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,0);
END
PARAMETER n;
PARAMETER_TITLE All candles;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,0);
END
PARAMETER nHigh;
PARAMETER_TITLE nHigh;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,0);
END
PARAMETER nLow;
PARAMETER_TITLE nLow;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE NUMERIC(10,0);
END
PARAMETER cndlsH;
PARAMETER_TITLE High candels;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE STRING(100);
END
PARAMETER cndlsL;
PARAMETER_TITLE Low candels;
PARAMETER_DESCRIPTION d;
PARAMETER_TYPE STRING(100);
END
END_PORTFOLIO_EX
Параметр PARAMETER_DESCRIPTION всех столбцов таблицы результатов формально установлен равным d.
В приведенном коде использованы как стандартные, так пользовательские функции QPILE. Также в коде учтена особенность функции GET_VALUE, всегда возвращающей значение типа STRING. При работе с циклом FOR применены обе предусмотренные QPILE конструкции: FOR - IN и FOR - FROM.
Руководство пользователя QUIK v.6.3.