Awọn ẹya ara ẹrọ ti Q ati ede KDB+ ni lilo apẹẹrẹ ti iṣẹ akoko gidi kan

O le ka nipa kini ipilẹ KDB +, ede siseto Q jẹ, kini awọn agbara ati ailagbara wọn wa ninu iṣaaju mi article ati ni soki ninu ifihan. Ninu nkan naa, a yoo ṣe iṣẹ kan lori Q ti yoo ṣe ilana ṣiṣan data ti nwọle ati ṣe iṣiro ọpọlọpọ awọn iṣẹ ikojọpọ ni iṣẹju kọọkan ni ipo “akoko gidi” (ie, yoo ni akoko lati ṣe iṣiro ohun gbogbo ṣaaju apakan data atẹle). Ẹya akọkọ ti Q ni pe o jẹ ede fekito ti o fun ọ laaye lati ṣiṣẹ kii ṣe pẹlu awọn nkan ẹyọkan, ṣugbọn pẹlu awọn ohun elo wọn, awọn akojọpọ ti awọn ohun elo ati awọn nkan idiju miiran. Awọn ede bii Q ati awọn ibatan rẹ K, J, APL jẹ olokiki fun kukuru wọn. Nigbagbogbo, eto ti o gba ọpọlọpọ awọn iboju ti koodu ni ede ti o mọ bi Java le ti kọ sori wọn ni awọn laini diẹ. Eyi ni ohun ti Mo fẹ lati ṣafihan ninu nkan yii.

Awọn ẹya ara ẹrọ ti Q ati ede KDB+ ni lilo apẹẹrẹ ti iṣẹ akoko gidi kan

Ifihan

KDB+ jẹ ibi ipamọ data ti ọwọn ti o dojukọ lori iye data ti o tobi pupọ, ti paṣẹ ni ọna kan (nipataki nipasẹ akoko). O ti lo ni akọkọ ni awọn ile-iṣẹ inawo - awọn banki, awọn owo idoko-owo, awọn ile-iṣẹ iṣeduro. Ede Q jẹ ede inu ti KDB+ ti o fun ọ laaye lati ṣiṣẹ daradara pẹlu data yii. Imọ ẹkọ Q jẹ kukuru ati ṣiṣe, lakoko ti o ti rubọ mimọ. Eyi jẹ idalare nipasẹ otitọ pe ede fekito yoo nira lati ni oye ni eyikeyi ọran, ati kukuru ati ọlọrọ ti gbigbasilẹ gba ọ laaye lati wo apakan ti o tobi pupọ ti eto naa loju iboju kan, eyiti o jẹ ki o rọrun lati ni oye.

Ninu nkan yii a ṣe eto eto kikun ni Q ati pe o le fẹ gbiyanju rẹ. Lati ṣe eyi, iwọ yoo nilo Q. O le ṣe igbasilẹ ẹya 32-bit ọfẹ lori oju opo wẹẹbu ile-iṣẹ kx - www.kx.com. Nibe, ti o ba nifẹ, iwọ yoo wa alaye itọkasi lori Q, iwe naa Q Fun Eniyan ati orisirisi ohun èlò lori koko yi.

Igbekalẹ iṣoro naa

Orisun kan wa ti o firanṣẹ tabili pẹlu data ni gbogbo 25 milliseconds. Niwọn igba ti a ti lo KDB + ni akọkọ ni iṣuna, a yoo ro pe eyi jẹ tabili awọn iṣowo (awọn iṣowo), eyiti o ni awọn ọwọn wọnyi: akoko (akoko ni awọn iṣẹju-aaya), sym (iṣapẹẹrẹ ile-iṣẹ lori paṣipaarọ ọja - Emu, AAPL,…), idiyele (iye owo ti a ti ra awọn mọlẹbi), iwọn (iwọn idunadura naa). Aarin millisecond 25 jẹ lainidii, ko kere ju ko si gun ju. Wiwa rẹ tumọ si pe data wa si iṣẹ ti o ti ni ifipamọ tẹlẹ. Yoo rọrun lati ṣe ifisilẹ ni ẹgbẹ iṣẹ, pẹlu ififunni agbara ti o da lori ẹru lọwọlọwọ, ṣugbọn fun ayedero, a yoo dojukọ aarin aarin ti o wa titi.

Iṣẹ naa gbọdọ ka ni iṣẹju kọọkan fun aami ti nwọle kọọkan lati ọwọn sym ṣeto awọn iṣẹ iṣakojọpọ - idiyele ti o pọju, idiyele apapọ, iwọn apao, ati bẹbẹ lọ. alaye to wulo. Fun ayedero, a yoo ro pe gbogbo awọn iṣẹ le ṣe iṣiro ni afikun, i.e. lati gba iye tuntun, o to lati mọ awọn nọmba meji - atijọ ati awọn iye ti nwọle. Fun apẹẹrẹ, awọn iṣẹ max, apapọ, apao ni ohun-ini yii, ṣugbọn iṣẹ agbedemeji ko.

A yoo tun ro pe ṣiṣan data ti nwọle jẹ akoko ti a paṣẹ. Eyi yoo fun wa ni aye lati ṣiṣẹ nikan pẹlu iṣẹju to kẹhin. Ni iṣe, o to lati ni anfani lati ṣiṣẹ pẹlu awọn iṣẹju lọwọlọwọ ati ti tẹlẹ ni ọran diẹ ninu awọn imudojuiwọn ti pẹ. Fun ayedero, a ko ni ro ọran yii.

Awọn iṣẹ akojọpọ

Awọn iṣẹ akojọpọ ti a beere ti wa ni akojọ si isalẹ. Mo mu ọpọlọpọ ninu wọn bi o ti ṣee ṣe lati mu ẹru lori iṣẹ naa pọ si:

  • ga - max owo - o pọju owo fun iseju.
  • kekere – min owo – kere owo fun iseju.
  • FirstPrice – akọkọ owo – akọkọ owo fun iseju.
  • lastPrice – kẹhin owo – kẹhin owo fun iseju.
  • Iwọn akọkọ - iwọn akọkọ - iwọn iṣowo akọkọ fun iṣẹju kan.
  • lastSize – kẹhin iwọn — kẹhin isowo iwọn ni iseju kan.
  • numTrades - ka i - nọmba awọn iṣowo fun iṣẹju kan.
  • iwọn didun – apao iwọn – apao awọn iwọn isowo fun iseju.
  • pvolume – apao owo – apao awọn owo fun iseju, beere fun avgPrice.
  • - iye owo iyipada apao * iwọn - iwọn lapapọ ti awọn iṣowo fun iṣẹju kan.
  • avgPrice – pvolume%numTrades – apapọ owo fun iseju.
  • avgSize – iwọn didun% numTrades – apapọ iwọn isowo fun iseju.
  • vwap – iyipada% iwọn didun – iye owo apapọ fun iṣẹju kan ni iwuwo nipasẹ iwọn idunadura.
  • cumVolume – apao iwọn didun – akojo iwọn ti awọn lẹkọ lori gbogbo akoko.

Jẹ ki a lẹsẹkẹsẹ jiroro ni aaye kan ti kii ṣe kedere - bii o ṣe le ṣe ipilẹṣẹ awọn ọwọn wọnyi fun igba akọkọ ati fun iṣẹju kọọkan ti o tẹle. Diẹ ninu awọn ọwọn ti iruPrice akọkọ gbọdọ wa ni ipilẹṣẹ lati di asan ni igba kọọkan; iye wọn jẹ aisọye. Awọn oriṣi iwọn didun miiran gbọdọ wa ni nigbagbogbo ṣeto si 0. Awọn ọwọn tun wa ti o nilo ọna apapọ - fun apẹẹrẹ, cumVolume gbọdọ jẹ daakọ lati iṣẹju iṣaaju, ati fun akọkọ ṣeto si 0. Jẹ ki a ṣeto gbogbo awọn aye wọnyi nipa lilo data iwe-itumọ. iru (afọwọṣe si igbasilẹ):

// list ! list – создать словарь, 0n – float null, 0N – long null, `sym – тип символ, `sym1`sym2 – список символов
initWith:`sym`time`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover`avgPrice`avgSize`vwap`cumVolume!(`;00:00;0n;0n;0n;0n;0N;0N;0;0;0.0;0.0;0n;0n;0n;0);
aggCols:reverse key[initWith] except `sym`time; // список всех вычисляемых колонок, reverse объяснен ниже

Mo ṣafikun aami ati akoko si iwe-itumọ fun irọrun, ni bayi initWith jẹ laini ti a ti ṣetan lati tabili akojọpọ ipari, nibiti o wa lati ṣeto aami ati akoko to pe. O le lo lati ṣafikun awọn ori ila tuntun si tabili kan.

A yoo nilo aggCols nigba ṣiṣẹda iṣẹ apapọ kan. Atokọ naa gbọdọ jẹ iyipada nitori aṣẹ ti a ṣe ayẹwo awọn ikosile ni Q (lati ọtun si osi). Ibi-afẹde ni lati rii daju pe iṣiro naa lọ lati giga si cumVolume, nitori diẹ ninu awọn ọwọn da lori awọn ti tẹlẹ.

Awọn ọwọn ti o nilo lati daakọ si iṣẹju tuntun lati ọkan ti tẹlẹ, a ṣafikun iwe aami fun irọrun:

rollColumns:`sym`cumVolume;

Bayi jẹ ki a pin awọn ọwọn si awọn ẹgbẹ ni ibamu si bi wọn ṣe yẹ ki o ṣe imudojuiwọn. Awọn oriṣi mẹta le ṣe iyatọ:

  1. Accumulators (iwọn didun, iyipada, ..) - a gbọdọ fi iye ti nwọle si ti tẹlẹ.
  2. Pẹlu aaye pataki kan (giga, kekere, ..) - iye akọkọ ni iṣẹju ni a gba lati inu data ti nwọle, awọn iyokù ti wa ni iṣiro nipa lilo iṣẹ naa.
  3. Sinmi. Ṣe iṣiro nigbagbogbo nipa lilo iṣẹ kan.

Jẹ ki a ṣalaye awọn oniyipada fun awọn kilasi wọnyi:

accumulatorCols:`numTrades`volume`pvolume`turnover;
specialCols:`high`low`firstPrice`firstSize;

Ilana iṣiro

A yoo ṣe imudojuiwọn tabili apapọ ni awọn ipele meji. Fun ṣiṣe, a kọkọ dinku tabili ti nwọle ki ila kan wa fun ohun kikọ kọọkan ati iṣẹju. Otitọ pe gbogbo awọn iṣẹ wa jẹ afikun ati awọn iṣeduro associative pe abajade ti igbesẹ afikun yii kii yoo yipada. O le dinku tabili ni lilo yan:

select high:max price, low:min price … by sym,time.minute from table

Ọna yii ni aila-nfani - ṣeto ti awọn ọwọn iṣiro jẹ asọye tẹlẹ. Ni akoko, ni Q, yan tun jẹ imuse bi iṣẹ kan nibiti o le paarọ awọn ariyanjiyan ti a ṣẹda ni agbara:

?[table;whereClause;byClause;selectClause]

Emi kii yoo ṣe apejuwe ni apejuwe awọn ọna kika ti awọn ariyanjiyan; ninu ọran wa, nikan nipasẹ ati yan awọn ọrọ yoo jẹ aiṣedeede ati pe wọn yẹ ki o jẹ awọn iwe-itumọ ti awọn ọwọn fọọmu! Nitorinaa, iṣẹ idinku le jẹ asọye bi atẹle:

selExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover!parse each ("max price";"min price";"first price";"last price";"first size";"last size";"count i";"sum size";"sum price";"sum price*size"); // each это функция map в Q для одного списка
preprocess:?[;();`sym`time!`sym`time.minute;selExpression];

Fun wípé, Mo lo iṣẹ parse, eyi ti o yi okun kan pẹlu ikosile Q sinu iye ti o le kọja si iṣẹ eval ati eyi ti o nilo ninu iṣẹ ti o yan. Tun ṣe akiyesi pe ilana iṣaaju ti wa ni asọye bi iṣiro kan (ie, iṣẹ kan pẹlu awọn ariyanjiyan asọye apakan) ti iṣẹ yiyan, ariyanjiyan kan (tabili) ti nsọnu. Ti a ba lo ilana iṣaaju si tabili kan, a yoo gba tabili fisinuirindigbindigbin.

Ipele keji jẹ mimu dojuiwọn tabili akojọpọ. Jẹ ki a kọkọ kọ algorithm ni pseudocode:

for each sym in inputTable
  idx: row index in agg table for sym+currentTime;
  aggTable[idx;`high]: aggTable[idx;`high] | inputTable[sym;`high];
  aggTable[idx;`volume]: aggTable[idx;`volume] + inputTable[sym;`volume];
  …

Ni Q, o wọpọ lati lo maapu / dinku awọn iṣẹ dipo awọn losiwajulosehin. Ṣugbọn niwọn igba ti Q jẹ ede fekito ati pe a le ni irọrun lo gbogbo awọn iṣẹ si gbogbo awọn aami ni ẹẹkan, lẹhinna si isunmọ akọkọ a le ṣe laisi lupu rara, ṣiṣe awọn iṣẹ lori gbogbo awọn aami ni ẹẹkan:

idx:calcIdx inputTable;
row:aggTable idx;
aggTable[idx;`high]: row[`high] | inputTable`high;
aggTable[idx;`volume]: row[`volume] + inputTable`volume;
…

Ṣugbọn a le lọ siwaju, Q ni oniṣẹ alailẹgbẹ ati alagbara pupọ - oniṣẹ iṣẹ iyansilẹ gbogbogbo. O gba ọ laaye lati yi eto awọn iye pada ni eto data eka kan nipa lilo atokọ ti awọn atọka, awọn iṣẹ ati awọn ariyanjiyan. Ninu ọran wa o dabi eyi:

idx:calcIdx inputTable;
rows:aggTable idx;
// .[target;(idx0;idx1;..);function;argument] ~ target[idx 0;idx 1;…]: function[target[idx 0;idx 1;…];argument], в нашем случае функция – это присваивание
.[aggTable;(idx;aggCols);:;flip (row[`high] | inputTable`high;row[`volume] + inputTable`volume;…)];

Laanu, lati fi si tabili kan o nilo atokọ ti awọn ori ila, kii ṣe awọn ọwọn, ati pe o ni lati yi matrix naa pada (akojọ awọn ọwọn si atokọ ti awọn ori ila) ni lilo iṣẹ isipade. Eyi jẹ gbowolori fun tabili nla kan, nitorinaa dipo a lo iṣẹ iyansilẹ gbogbogbo si iwe kọọkan lọtọ, ni lilo iṣẹ maapu (eyiti o dabi apostrophe):

.[aggTable;;:;]'[(idx;)each aggCols; (row[`high] | inputTable`high;row[`volume] + inputTable`volume;…)];

A tun lo iṣiro iṣẹ. Tun ṣe akiyesi pe ni Q, ṣiṣẹda atokọ tun jẹ iṣẹ kan ati pe a le pe ni lilo iṣẹ kọọkan (maapu) lati gba atokọ ti awọn atokọ.

Lati rii daju pe ṣeto awọn ọwọn iṣiro ko wa titi, a yoo ṣẹda ikosile ti o wa loke ni agbara. Jẹ ki a kọkọ ṣalaye awọn iṣẹ lati ṣe iṣiro iwe kọọkan, ni lilo ila ati awọn oniyipada inp lati tọka si akojọpọ ati data titẹ sii:

aggExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`avgPrice`avgSize`vwap`cumVolume!
 ("row[`high]|inp`high";"row[`low]&inp`low";"row`firstPrice";"inp`lastPrice";"row`firstSize";"inp`lastSize";"pvolume%numTrades";"volume%numTrades";"turnover%volume";"row[`cumVolume]+inp`volume");

Diẹ ninu awọn ọwọn jẹ pataki; iye akọkọ wọn ko yẹ ki o ṣe iṣiro nipasẹ iṣẹ naa. A le pinnu pe o jẹ akọkọ nipasẹ ila [`numTrades] iwe - ti o ba ni 0, lẹhinna iye jẹ akọkọ. Q ni iṣẹ yiyan -?[Atokọ Boolean; list1; list2] - eyiti o yan iye kan lati atokọ 1 tabi 2 da lori ipo ni ariyanjiyan akọkọ:

// high -> ?[isFirst;inp`high;row[`high]|inp`high]
// @ - тоже обобщенное присваивание для случая когда индекс неглубокий
@[`aggExpression;specialCols;{[x;y]"?[isFirst;inp`",y,";",x,"]"};string specialCols];

Nibi Mo pe iṣẹ iyansilẹ gbogbogbo pẹlu iṣẹ mi (ikosile ni awọn àmúró iṣupọ). O gba iye ti isiyi (ariyanjiyan akọkọ) ati ariyanjiyan afikun, eyiti Mo kọja ni paramita 4th.

Jẹ ki a ṣafikun awọn agbohunsoke batiri lọtọ, nitori iṣẹ naa jẹ kanna fun wọn:

// volume -> row[`volume]+inp`volume
aggExpression[accumulatorCols]:{"row[`",x,"]+inp`",x } each string accumulatorCols;

Eyi jẹ iṣẹ iyansilẹ deede nipasẹ awọn iṣedede Q, ṣugbọn Mo n yan atokọ ti awọn iye ni ẹẹkan. Ni ipari, jẹ ki a ṣẹda iṣẹ akọkọ:

// ":",/:aggExprs ~ map[{":",x};aggExpr] => ":row[`high]|inp`high" присвоим вычисленное значение переменной, потому что некоторые колонки зависят от уже вычисленных значений
// string[cols],'exprs ~ map[,;string[cols];exprs] => "high:row[`high]|inp`high" завершим создание присваивания. ,’ расшифровывается как map[concat]
// ";" sv exprs – String from Vector (sv), соединяет список строк вставляя “;” посредине
updateAgg:value "{[aggTable;idx;inp] row:aggTable idx; isFirst_0=row`numTrades; .[aggTable;;:;]'[(idx;)each aggCols;(",(";"sv string[aggCols],'":",/:aggExpression aggCols),")]}";

Pẹlu ikosile yii, Mo ṣẹda iṣẹ ṣiṣe kan lati inu okun ti o ni ọrọ ti Mo fun loke. Abajade yoo dabi eyi:

{[aggTable;idx;inp] rows:aggTable idx; isFirst_0=row`numTrades; .[aggTable;;:;]'[(idx;)each aggCols ;(cumVolume:row[`cumVolume]+inp`cumVolume;… ; high:?[isFirst;inp`high;row[`high]|inp`high])]}

Ilana igbelewọn ọwọn ti yipada nitori pe ni Q aṣẹ igbelewọn wa lati ọtun si osi.

Bayi a ni awọn iṣẹ akọkọ meji pataki fun awọn iṣiro, a kan nilo lati ṣafikun awọn amayederun diẹ ati iṣẹ naa ti ṣetan.

Awọn igbesẹ ipari

A ni ilana iṣaaju ati awọn iṣẹ imudojuiwọnAgg ti o ṣe gbogbo iṣẹ naa. Ṣugbọn o tun jẹ dandan lati rii daju iyipada ti o tọ nipasẹ awọn iṣẹju ati ṣe iṣiro awọn atọka fun apapọ. Ni akọkọ, jẹ ki a ṣalaye iṣẹ init:

init:{
  tradeAgg:: 0#enlist[initWith]; // создаем пустую типизированную таблицу, enlist превращает словарь в таблицу, а 0# означает взять 0 элементов из нее
  currTime::00:00; // начнем с 0, :: означает, что присваивание в глобальную переменную
  currSyms::`u#`symbol$(); // `u# - превращает список в дерево, для ускорения поиска элементов
  offset::0; // индекс в tradeAgg, где начинается текущая минута 
  rollCache:: `sym xkey update `u#sym from rollColumns#tradeAgg; // кэш для последних значений roll колонок, таблица с ключом sym
 }

A yoo tun setumo iṣẹ eerun, eyi ti yoo yi awọn ti isiyi iseju:

roll:{[tm]
  if[currTime>tm; :init[]]; // если перевалили за полночь, то просто вызовем init
  rollCache,::offset _ rollColumns#tradeAgg; // обновим кэш – взять roll колонки из aggTable, обрезать, вставить в rollCache
  offset::count tradeAgg;
  currSyms::`u#`$();
 }

A yoo nilo iṣẹ kan lati ṣafikun awọn ohun kikọ tuntun:

addSyms:{[syms]
  currSyms,::syms; // добавим в список известных
  // добавим в таблицу sym, time и rollColumns воспользовавшись обобщенным присваиванием.
  // Функция ^ подставляет значения по умолчанию для roll колонок, если символа нет в кэше. value flip table возвращает список колонок в таблице.
  `tradeAgg upsert @[count[syms]#enlist initWith;`sym`time,cols rc;:;(syms;currTime), (initWith cols rc)^value flip rc:rollCache ([] sym: syms)];
 }

Ati nikẹhin, iṣẹ imudojuiwọn (orukọ ibile fun iṣẹ yii fun awọn iṣẹ Q), eyiti alabara pe lati ṣafikun data:

upd:{[tblName;data] // tblName нам не нужно, но обычно сервис обрабатывает несколько таблиц 
  tm:exec distinct time from data:() xkey preprocess data; // preprocess & calc time
  updMinute[data] each tm; // добавим данные для каждой минуты
};
updMinute:{[data;tm]
  if[tm<>currTime; roll tm; currTime::tm]; // поменяем минуту, если необходимо
  data:select from data where time=tm; // фильтрация
  if[count msyms:syms where not (syms:data`sym)in currSyms; addSyms msyms]; // новые символы
  updateAgg[`tradeAgg;offset+currSyms?syms;data]; // обновим агрегированную таблицу. Функция ? ищет индекс элементов списка справа в списке слева.
 };

Gbogbo ẹ niyẹn. Eyi ni koodu pipe ti iṣẹ wa, bi a ti ṣe ileri, o kan awọn laini diẹ:

initWith:`sym`time`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover`avgPrice`avgSize`vwap`cumVolume!(`;00:00;0n;0n;0n;0n;0N;0N;0;0;0.0;0.0;0n;0n;0n;0);
aggCols:reverse key[initWith] except `sym`time;
rollColumns:`sym`cumVolume;

accumulatorCols:`numTrades`volume`pvolume`turnover;
specialCols:`high`low`firstPrice`firstSize;

selExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover!parse each ("max price";"min price";"first price";"last price";"first size";"last size";"count i";"sum size";"sum price";"sum price*size");
preprocess:?[;();`sym`time!`sym`time.minute;selExpression];

aggExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`avgPrice`avgSize`vwap`cumVolume!("row[`high]|inp`high";"row[`low]&inp`low";"row`firstPrice";"inp`lastPrice";"row`firstSize";"inp`lastSize";"pvolume%numTrades";"volume%numTrades";"turnover%volume";"row[`cumVolume]+inp`volume");
@[`aggExpression;specialCols;{"?[isFirst;inp`",y,";",x,"]"};string specialCols];
aggExpression[accumulatorCols]:{"row[`",x,"]+inp`",x } each string accumulatorCols;
updateAgg:value "{[aggTable;idx;inp] row:aggTable idx; isFirst_0=row`numTrades; .[aggTable;;:;]'[(idx;)each aggCols;(",(";"sv string[aggCols],'":",/:aggExpression aggCols),")]}"; / '

init:{
  tradeAgg::0#enlist[initWith];
  currTime::00:00;
  currSyms::`u#`symbol$();
  offset::0;
  rollCache:: `sym xkey update `u#sym from rollColumns#tradeAgg;
 };
roll:{[tm]
  if[currTime>tm; :init[]];
  rollCache,::offset _ rollColumns#tradeAgg;
  offset::count tradeAgg;
  currSyms::`u#`$();
 };
addSyms:{[syms]
  currSyms,::syms;
  `tradeAgg upsert @[count[syms]#enlist initWith;`sym`time,cols rc;:;(syms;currTime),(initWith cols rc)^value flip rc:rollCache ([] sym: syms)];
 };

upd:{[tblName;data] updMinute[data] each exec distinct time from data:() xkey preprocess data};
updMinute:{[data;tm]
  if[tm<>currTime; roll tm; currTime::tm];
  data:select from data where time=tm;
  if[count msyms:syms where not (syms:data`sym)in currSyms; addSyms msyms];
  updateAgg[`tradeAgg;offset+currSyms?syms;data];
 };

Igbeyewo

Jẹ ki a ṣayẹwo iṣẹ iṣẹ naa. Lati ṣe eyi, jẹ ki a ṣiṣẹ ni ilana ti o yatọ (fi koodu naa sinu faili service.q) ki o pe iṣẹ init:

q service.q –p 5566

q)init[]

Ninu console miiran, bẹrẹ ilana Q keji ki o sopọ si akọkọ:

h:hopen `:host:5566
h:hopen 5566 // если оба на одном хосте

Ni akọkọ, jẹ ki a ṣẹda atokọ ti awọn aami - awọn ege 10000 ki o ṣafikun iṣẹ kan lati ṣẹda tabili laileto. Ninu console keji:

syms:`IBM`AAPL`GOOG,-9997?`8
rnd:{[n;t] ([] sym:n?syms; time:t+asc n#til 25; price:n?10f; size:n?10)}

Mo ṣafikun awọn aami gidi mẹta si atokọ lati jẹ ki o rọrun lati wa wọn ninu tabili. Awọn rnd iṣẹ ṣẹda a ID tabili pẹlu n ila, ibi ti awọn akoko yatọ lati t to t + 25 milliseconds.

Bayi o le gbiyanju fifiranṣẹ data si iṣẹ naa (fi awọn wakati mẹwa akọkọ kun):

{h (`upd;`trade;rnd[10000;x])} each `time$00:00 + til 60*10

O le ṣayẹwo ninu iṣẹ naa pe tabili ti ni imudojuiwọn:

c 25 200
select from tradeAgg where sym=`AAPL
-20#select from tradeAgg where sym=`AAPL

Esi:

sym|time|high|low|firstPrice|lastPrice|firstSize|lastSize|numTrades|volume|pvolume|turnover|avgPrice|avgSize|vwap|cumVolume
--|--|--|--|--|--------------------------------
AAPL|09:27|9.258904|9.258904|9.258904|9.258904|8|8|1|8|9.258904|74.07123|9.258904|8|9.258904|2888
AAPL|09:28|9.068162|9.068162|9.068162|9.068162|7|7|1|7|9.068162|63.47713|9.068162|7|9.068162|2895
AAPL|09:31|4.680449|0.2011121|1.620827|0.2011121|1|5|4|14|9.569556|36.84342|2.392389|3.5|2.631673|2909
AAPL|09:33|2.812535|2.812535|2.812535|2.812535|6|6|1|6|2.812535|16.87521|2.812535|6|2.812535|2915
AAPL|09:34|5.099025|5.099025|5.099025|5.099025|4|4|1|4|5.099025|20.3961|5.099025|4|5.099025|2919

Jẹ ki a ṣe idanwo fifuye lati wa iye data ti iṣẹ naa le ṣe ni iṣẹju kan. Jẹ ki n leti pe a ṣeto aarin imudojuiwọn si 25 milliseconds. Nitorinaa, iṣẹ naa gbọdọ (ni apapọ) baamu o kere ju 20 milliseconds fun imudojuiwọn lati fun awọn olumulo ni akoko lati beere data. Tẹ atẹle naa ni ilana keji:

tm:10:00:00.000
stressTest:{[n] 1 string[tm]," "; times,::h ({st:.z.T; upd[`trade;x]; .z.T-st};rnd[n;tm]); tm+:25}
start:{[n] times::(); do[4800;stressTest[n]]; -1 " "; `min`avg`med`max!(min times;avg times;med times;max times)}

4800 jẹ iṣẹju meji. O le gbiyanju lati ṣiṣẹ ni akọkọ fun awọn ori ila 1000 ni gbogbo milimita 25:

start 1000

Ninu ọran mi, abajade wa ni ayika awọn milliseconds meji fun imudojuiwọn. Nitorinaa Emi yoo mu nọmba awọn ori ila pọ si lẹsẹkẹsẹ si 10.000:

start 10000

Esi:

min| 00:00:00.004
avg| 9.191458
med| 9f
max| 00:00:00.030

Lẹẹkansi, ohunkohun pataki, sugbon yi jẹ 24 million ila fun iseju, 400 ẹgbẹrun fun keji. Fun diẹ ẹ sii ju milliseconds 25, imudojuiwọn naa fa fifalẹ ni awọn akoko 5 nikan, o han gbangba nigbati iṣẹju ba yipada. Jẹ ki a pọ si 100.000:

start 100000

Esi:

min| 00:00:00.013
avg| 25.11083
med| 24f
max| 00:00:00.108
q)sum times
00:02:00.532

Bii o ti le rii, iṣẹ naa le farada lasan, ṣugbọn sibẹsibẹ o ṣakoso lati duro loju omi. Iru iwọn data (awọn laini miliọnu 240 fun iṣẹju kan) tobi pupọ; ni iru awọn ọran, o wọpọ lati ṣe ifilọlẹ ọpọlọpọ awọn ere ibeji (tabi paapaa awọn dosinni ti awọn ere ibeji) ti iṣẹ naa, ọkọọkan eyiti o ṣe ilana apakan nikan ti awọn ohun kikọ. Sibẹsibẹ, abajade jẹ iwunilori fun ede ti o tumọ ti o dojukọ akọkọ lori ibi ipamọ data.

Ibeere naa le dide bi idi ti akoko fi n dagba ti kii ṣe laini pẹlu iwọn ti imudojuiwọn kọọkan. Idi ni wipe awọn isunki iṣẹ jẹ kosi kan C iṣẹ, eyi ti o jẹ Elo siwaju sii daradara ju updateAgg. Bibẹrẹ lati iwọn imudojuiwọn kan (ni ayika 10.000), imudojuiwọnAgg de aja rẹ ati lẹhinna akoko ipaniyan rẹ ko da lori iwọn imudojuiwọn. O jẹ nitori igbesẹ alakoko Q pe iṣẹ naa ni anfani lati ṣajọ iru awọn iwọn data. Eyi ṣe afihan bi o ṣe ṣe pataki lati yan algorithm ti o tọ nigba ṣiṣẹ pẹlu data nla. Ojuami miiran ni ibi ipamọ to tọ ti data ni iranti. Ti data naa ko ba tọju ni ọwọn tabi ko paṣẹ nipasẹ akoko, lẹhinna a yoo faramọ iru nkan bii miss kaṣe TLB - isansa ti adirẹsi oju-iwe iranti ni kaṣe adirẹsi ero isise. Wiwa adirẹsi kan gba to awọn akoko 30 to gun ti o ko ba ṣaṣeyọri, ati pe ti data ba tuka, o le fa fifalẹ iṣẹ naa ni igba pupọ.

ipari

Ninu nkan yii, Mo fihan pe KDB + ati data data Q dara kii ṣe fun titoju data nla nikan ati ni irọrun wọle si nipasẹ yiyan, ṣugbọn tun fun ṣiṣẹda awọn iṣẹ ṣiṣe data ti o lagbara lati digesting awọn ọgọọgọrun awọn ori ila / gigabytes ti data paapaa ni ninu ilana Q kan ṣoṣo. Ede Q funrarẹ ngbanilaaye fun ṣoki pupọ ati imuse daradara ti awọn algoridimu ti o ni ibatan si sisẹ data nitori ẹda fekito rẹ, onitumọ ede SQL ti a ṣe sinu ati eto aṣeyọri pupọ ti awọn iṣẹ ikawe.

Emi yoo ṣe akiyesi pe ohun ti o wa loke jẹ apakan ti ohun ti Q le ṣe, o ni awọn ẹya alailẹgbẹ miiran daradara. Fun apẹẹrẹ, ilana Ilana IPC ti o rọrun pupọ ti o pa aala laarin awọn ilana Q kọọkan ati gba ọ laaye lati ṣajọpọ awọn ọgọọgọrun ti awọn ilana wọnyi sinu nẹtiwọọki kan, eyiti o le wa lori awọn dosinni ti awọn olupin ni awọn ẹya oriṣiriṣi agbaye.

orisun: www.habr.com

Fi ọrọìwòye kun