Waxaad ka akhrisan kartaa waxa ku saabsan saldhigga KDB+, luqadda barnaamijyada Q, waxa ay ku fiican yihiin iyo meelaha ay ku liidato ee aan hore oo kooban oo hordhac ah. Maqaalka, waxaan hirgelin doonaa adeeg ku saabsan Q kaas oo ka shaqeyn doona qulqulka xogta soo socota oo xisaabin doona hawlaha kala duwan ee isku-darka daqiiqad kasta "waqtiga dhabta ah" qaabka (ie, waxay heli doontaa wakhti lagu xisaabiyo wax kasta ka hor qaybta xigta ee xogta). Tilmaamaha ugu muhiimsan ee Q waa in uu yahay luqadda vector oo kuu ogolaanaysa inaad ku shaqeyso shay keliya, laakiin aad ku shaqeyn karto qalabkooda, qalabkooda iyo walxo kale oo adag. Luqadaha sida Q iyo qaraabadooda K, J, APL waxay caan ku yihiin soo koobiddooda. Inta badan, barnaamij qaada dhawr shaashad oo kood ah oo ku qoran luqad la yaqaan sida Java ayaa lagu qori karaa dhowr sadar. Tani waa waxa aan rabo in aan ku muujiyo maqaalkan.

Horudhac
KDB+ waa xog ururin tiirar ah oo diiradda lagu saaray tiro aad u badan oo xog ah, oo loo dalbay hab gaar ah (ugu badnaan waqti). Waxaa loo adeegsadaa ugu horrayn hay'adaha maaliyadeed - bangiyada, maalgelinta maalgashiga, shirkadaha caymiska. Luuqadda Q waa luqadda gudaha ee KDB+ oo kuu ogolaanaysa inaad si wax ku ool ah ula shaqeyso xogtan. Fikirka Q waa gaaban iyo hufnaan, halka caddaynta la huray. Taas waxaa lagu sababeynayaa in luqadda vector-ku ay adkaan doonto in la fahmo xaalad kasta, soo koobida iyo qaninimada duubista ayaa kuu oggolaaneysa inaad hal shaashad ka aragto qayb aad u weyn oo barnaamijka ah, taasoo ugu dambeyntii sahlaysa in la fahmo.
Maqaalkan waxaan ku hirgelineynaa barnaamij Q buuxa ah waxaana laga yaabaa inaad rabto inaad tijaabiso. Si aad tan u sameyso, waxaad u baahan doontaa Q lafteeda waxaad kala soo bixi kartaa nooca 32-bit ee bilaashka ah mareegaha shirkadda kx - . Halkaas, haddii aad xiisaynayso, waxaad ka heli doontaa macluumaadka tixraaca ee Q, buugga iyo maqaallo kala duwan oo mawduucan ku saabsan.
Abuurista dhibaatada
Waxaa jira ilo soo dira miis xogta leh 25 millise seconds kasta. Maaddaama KDB + loo isticmaalo ugu horrayn maaliyadda, waxaan u qaadan doonaa in tani ay tahay miiska wax kala iibsiga (ganacsiga), kaas oo leh tiirarka soo socda: waqti (waqtiga millise seconds), sym (magacaabidda shirkadda ee sarrifka saamiyada - IBM, AAPL,…), Qiimaha (qiimaha lagu iibsaday saamiyada), cabbirka (xajmiga wax kala iibsiga). Inta u dhaxaysa 25 millise-ilbiriqsi waa mid aan sabab lahayn, aad uma yara mana dheera. Joogitaankeeda waxay ka dhigan tahay in xogtu ay ku timaaddo adeegii hore loo xannibay. Way sahlanaan doontaa in la hirgeliyo bakhaar dhinaca adeega ah, oo ay ku jirto baqdin firfircoon oo ku xidhan culayska hadda jira, laakiin fududaynta, waxaanu diiradda saari doonaa muddo go'an.
Adeeggu waa inuu tiriyaa daqiiqad kasta calaamad kasta oo ka imanaysa tiirarka summadda ee tiirarka summadda ee tiirarka is-ururinta - qiimaha ugu sarreeya, celceliska qiimaha, cabbirka wadarta, iwm. macluumaad waxtar leh. Si fudud, waxaan u qaadan doonaa in dhammaan hawlaha la xisaabin karo si kordheysa, i.e. Si loo helo qiime cusub, waa ku filan in la ogaado laba tiro - kuwii hore iyo qiimaha soo socda. Tusaale ahaan, hawlaha ugu badan, celceliska, wadarta waxay leeyihiin hantidan, laakiin shaqada dhexdhexaadka ah ma laha.
Waxaan sidoo kale u qaadan doonaa in qulqulka xogta ee soo socota ay tahay waqti la dalbaday. Tani waxay na siin doontaa fursad aan ku shaqeyno kaliya daqiiqada ugu dambeysa. Ficil ahaan, waa ku filan tahay inaad la shaqeyso daqiiqadaha hadda jira iyo kuwa hore haddii ay dhacdo in qaar ka mid ah cusbooneysiinta ay soo daahdaan. Si fudud, ma tixgelin doono kiiskan.
Hawlaha ururinta
Hawlaha isku-darka ee loo baahan yahay ayaa hoos ku taxan. Waxaan qaatay inta ugu badan ee suurtogalka ah si aan u kordhiyo culeyska adeegga:
- sare - qiimaha ugu badan - qiimaha ugu badan daqiiqadii.
- hooseeya - qiimo yar - qiimaha ugu yar daqiiqadii.
- FirstPrice - qiimaha ugu horeeya - qiimaha ugu horeeya daqiiqadii.
- LastPrice - qiimihii ugu dambeeyay - qiimihii ugu dambeeyay daqiiqadii.
- cabbirka koowaad - cabbirka koowaad - cabbirka ganacsiga ugu horreeya daqiiqaddii.
- LastSize - cabbirka ugu dambeeya - cabbirka ganacsi ee ugu dambeeya hal daqiiqo.
- numTrades - xisaabi i - tirada ganacsiyada daqiiqadii.
- mugga - cabbirka wadarta - wadarta cabbirrada ganacsiga daqiiqadii.
- pvolume - wadarta qiimaha - wadarta qiimaha daqiiqadii, looga baahan yahay celcelis ahaan.
- - wadarta qiimaha wareejinta * cabbirka - wadarta mugga wax kala iibsiga daqiiqaddii.
- avgPrice - pvolume%numTrades - celceliska qiimaha daqiiqadii.
- celceliska cabbirka - mugga%numTrades - celceliska cabbirka ganacsiga daqiiqadii.
- vwap - celceliska boqolkiiba mugga - celceliska qiimaha daqiiqadii lagu miisaamay cabbirka wax kala iibsiga.
- cumVolume - wadarta mugga - cabbirka wax kala iibsiga ee urursan wakhtiga oo dhan.
Aynu isla markiiba ka hadalno hal qodob oo aan caddayn - sida loo bilaabo tiirarkan marka ugu horeysa iyo daqiiqad kasta oo xigta. Qaar ka mid ah tiirarka nooca qiimihiisu yahay waa in la bilaabaa inay buraan mar kasta; Noocyada kale ee mugga waa in had iyo jeer la dejiyaa 0. Waxa kale oo jira tiirar u baahan hab isku dhafan - tusaale ahaan, cumVolume waa in laga soo guuriyaa daqiiqaddii hore, iyo kan ugu horreeya ee loo dhigo 0. Aynu dejinno dhammaan xuduudahan annaga oo isticmaalaya xogta qaamuuska. nooca (oo la mid ah diiwaan):
// 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 объяснен ниже
Waxaan ku daray sym iyo waqti qaamuuska si ay ugu habboonaato, hadda initWith waa khad diyaarsan oo laga soo qaatay miiska ugu dambeeya ee la isku daray, halkaas oo ay ku hadhsan tahay in la dejiyo calaamadaha saxda ah iyo waqtiga. Waxaad u isticmaali kartaa inaad ku darto safaf cusub miiska.
Waxaan u baahan doonaa aggCols marka la abuurayo shaqada isu geynta. Liistada waa in la rogaa iyadoo ay ugu wacan tahay sida ay u kala horreeyaan tibaaxaha Q ee loo qiimeeyo (midig ilaa bidix). Hadafku waa in la hubiyo in xisaabintu ay ka soo baxdo sare ilaa cumVolume, maadaama tiirarka qaar ay ku xidhan yihiin kuwii hore.
Tiirarka u baahan in lagu koobiyeeyo daqiiqad cusub oo ka timid tii hore, tiirarka astaanta ayaa lagu daraa si ay ugu habboonaato:
rollColumns:`sym`cumVolume;
Hadda aan u qaybinno tiirarka kooxo sida ay tahay in loo cusboonaysiiyo. Saddex nooc ayaa loo kala saari karaa:
- Accumulators (mugga, wareejinta, ..) - waa inaan ku darnaa qiimaha soo socda kii hore.
- Iyada oo leh dhibic gaar ah (sare, hoose, ..) - qiimaha ugu horreeya ee daqiiqada ayaa laga soo qaatay xogta soo socota, inta soo hartay waxaa lagu xisaabiyaa iyadoo la adeegsanayo shaqada.
- Naso Had iyo jeer la xisaabiyaa iyadoo la isticmaalayo hawl.
Aynu qeexno doorsoomayaasha fasaladan:
accumulatorCols:`numTrades`volume`pvolume`turnover;
specialCols:`high`low`firstPrice`firstSize;
Amarka xisaabinta
Waxaan u cusbooneysiin doonaa shaxda isku-darka ah laba marxaladood. Waxtarka, waxaan marka hore yareynaa miiska soo socda si ay u jirto hal saf oo keliya dabeecad kasta iyo daqiiqad kasta. Xaqiiqda ah in dhammaan hawlahayagu ay yihiin kuwo kordhin iyo isku-xirnaan ayaa dammaanad qaadaya in natiijada tallaabadan dheeraadka ah aysan isbeddelin. Waxaad hoos u dhigi kartaa miiska adoo isticmaalaya:
select high:max price, low:min price … by sym,time.minute from table
Habkani wuxuu leeyahay faa'iido darro - set of tiirarka la xisaabiyey waa la sii qeexay. Nasiib wanaag, gudaha Q, doorashadu sidoo kale waxaa loo fuliyaa hawl ahaan halkaas oo aad ku beddeli karto doodaha si firfircoon loo abuuray:
?[table;whereClause;byClause;selectClause]
Ma si faahfaahsan u qeexi doono qaabka doodaha ee kiiskayaga, kaliya by iyo xulashada tibaaxaha waxay noqon doonaan kuwo aan waxtar lahayn oo waa inay noqdaan qaamuusyada qaabka tiirarka! Haddaba, shaqada sii yaraanaya waxaa lagu qeexi karaa sida soo socota:
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];
Si loo caddeeyo, waxaan isticmaalay shaqada laf-dhabarka, kaas oo u rogaya xadhig leh odhaah Q ah qiime loo gudbi karo shaqada eval oo looga baahan yahay shaqada dooro. Sidoo kale ogow in ka-hor-u-socodka lagu qeexay saadaal (tusaale ahaan, shaqo leh doodo qayb ahaan la qeexay) ee hawsha xulashada, hal dood (miiska) ayaa maqan. Haddii aan ku dabaqno nidaamka horudhaca miis, waxaan heli doonaa miis cufan.
Marxaladda labaad waa cusboonaysiinta miiska la isku daray. Aan marka hore ku qorno algorithmamka 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];
…
Q, waa wax caadi ah in la isticmaalo khariidad/yaraynta hawlaha halkii laga isticmaali lahaa wareegyada. Laakin maadaama Q uu yahay luqadda vector-ka oo aan si badbaado leh ugu dabaqi karno dhammaan hawlgallada dhammaan calaamadaha hal mar, ka dib qiyaasta ugu horreysa waxaan samayn karnaa sinaba la'aan, anagoo ku samaynayna dhammaan calaamadaha hal mar:
idx:calcIdx inputTable;
row:aggTable idx;
aggTable[idx;`high]: row[`high] | inputTable`high;
aggTable[idx;`volume]: row[`volume] + inputTable`volume;
…
Laakiin waan sii socon karnaa, Q wuxuu leeyahay hawlwadeen gaar ah oo aad u awood badan - hawlwadeenka guud ee shaqada. Waxay kuu ogolaanaysaa inaad beddesho set of qiyamka qaab-dhismeedka xogta adag iyadoo la isticmaalayo liiska tusmooyinka, hawlaha iyo doodaha. Xaaladeena waxay u egtahay sidan:
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;…)];
Nasiib darro, si aad u qoondayso miis waxaad u baahan tahay liis saf ah, ma aha tiirar, waana inaad beddeshaa jaantuska (liiska tiirarka liiska safafka) adoo isticmaalaya shaqada rogida. Tani waxay qaali u tahay miis weyn, markaa taa beddelkeeda waxaan u adeegsanaa meelaynta guud ee tiir kasta si gaar ah, annagoo adeegsanayna shaqada khariidadda (oo u ekaanaysa ruug-caddaa):
.[aggTable;;:;]'[(idx;)each aggCols; (row[`high] | inputTable`high;row[`volume] + inputTable`volume;…)];
Waxaan mar kale isticmaalnaa saadaalinta shaqada. Sidoo kale ogow in Q, abuurista liis sidoo kale waa shaqo waxaana u wici karnaa iyada oo la adeegsanayo hawl kasta (map) si aan u helno liis liis ah.
Si loo hubiyo in jaangooyooyinka tiirarka la xisaabiyay aan la hagaajin, waxaan u abuuri doonaa muujinta sare si firfircoon. Aan marka hore qeexno shaqooyinka si loo xisaabiyo tiir kasta, annagoo adeegsanayna doorsoomayaasha safka iyo kuwa soo gasha si aan u tixraacno xogta la isku daray iyo wax gelinta:
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");
Tiirarrada qaarkood waa kuwo gaar ah; Waxaan go'aamin karnaa inay tahay tan ugu horreysa safka [`numTrades] column - haddii ay ka kooban tahay 0, markaa qiimuhu waa marka hore. Q waxa uu leeyahay shaqo door ah -
// high -> ?[isFirst;inp`high;row[`high]|inp`high]
// @ - тоже обобщенное присваивание для случая когда индекс неглубокий
@[`aggExpression;specialCols;{[x;y]"?[isFirst;inp`",y,";",x,"]"};string specialCols];
Halkan waxaan ugu yeedhay hawlo guud oo shaqadayda ah (odhaah ku jirta laab-laabashada). Waxay helaysaa qiimaha hadda ( doodda koowaad) iyo dood dheeraad ah, oo aan ku dhaafo qiyaasta 4th.
Aynu si gaar ah ugu darno kuwa ku hadla baytariga, maadaama hawshu ay iyaga la mid tahay:
// volume -> row[`volume]+inp`volume
aggExpression[accumulatorCols]:{"row[`",x,"]+inp`",x } each string accumulatorCols;
Tani waa shaqo caadi ah marka loo eego heerarka Q, laakiin waxaan ku meelaynayaa liiska qiyamka hal mar. Ugu dambeyntii, aan abuurno shaqada ugu weyn:
// ":",/: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),")]}";
Tibaaxdan, waxaan si firfircoon uga abuurayaa xargo ka kooban tibaaxda aan kor ku sheegay. Natiijadu waxay u ekaan doontaa sidan:
{[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])]}
Nidaamka qiimaynta tiirka waa la rogay sababtoo ah Q nidaamka qiimayntu waa midig ilaa bidix.
Hadda waxaan haynaa laba hawlood oo muhiim ah oo lagama maarmaanka u ah xisaabinta, waxaan u baahanahay kaliya inaan ku darno kaabayaasha yar oo adeeggu waa diyaar.
Tallaabooyinka ugu dambeeya
Waxaan haynaa hab-socodka iyo cusboonaysiinta hawlaha Agg ee qabta shaqada oo dhan. Laakin wali waa lagama maarmaan in la hubiyo kala-guurka saxda ah ee daqiiqadaha iyo xisaabinta tusmooyinka isu-ururinta. Marka hore, aynu qeexno shaqada 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
}
Waxaan sidoo kale qeexi doonaa shaqada duubka, taas oo bedeli doonta daqiiqadda hadda:
roll:{[tm]
if[currTime>tm; :init[]]; // если перевалили за полночь, то просто вызовем init
rollCache,::offset _ rollColumns#tradeAgg; // обновим кэш – взять roll колонки из aggTable, обрезать, вставить в rollCache
offset::count tradeAgg;
currSyms::`u#`$();
}
Waxaan u baahan doonaa shaqo si aan ugu darno jilayaal cusub:
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)];
}
Ugu dambeyntiina, shaqada la cusboonaysiiyay (magaca soo jireenka ah ee shaqadan ee adeegyada Q), kaas oo loogu yeero macmiilka si loogu daro xogta:
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]; // обновим агрегированную таблицу. Функция ? ищет индекс элементов списка справа в списке слева.
};
Waa intaas. Waa kan koodka adeeggayaga oo dhammaystiran, sidii ballanku ahaa, dhawr sadar:
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];
};
Imtixaanka
Aynu eegno waxqabadka adeegga. Si tan loo sameeyo, aan u wadno hanaan gaar ah (ku dheji koodka faylka service.q) oo wac shaqada init:
q service.q –p 5566
q)init[]
Koonsole kale, billow habka labaad ee Q oo ku xidh kan kowaad:
h:hopen `:host:5566
h:hopen 5566 // если оба на одном хосте
Marka hore, aan abuurno liis calaamado ah - 10000 oo xabbo oo ku dar shaqo si aan u abuurno miis random ah. Koonsole labaad:
syms:`IBM`AAPL`GOOG,-9997?`8
rnd:{[n;t] ([] sym:n?syms; time:t+asc n#til 25; price:n?10f; size:n?10)}
Waxaan liiska ku daray saddex calaamadood oo dhab ah si ay ugu fududaato in aad miiska ka raadiso. Shaqada rnd waxay abuurtaa miis random ah oo leh saf, halkaas oo wakhtigu ku kala duwan yahay t ilaa t +25 millise seconds.
Hadda waxaad isku dayi kartaa inaad xogta u dirto adeegga (ku dar tobanka saacadood ee ugu horreeya):
{h (`upd;`trade;rnd[10000;x])} each `time$00:00 + til 60*10
Waxaad ka hubin kartaa adeegga in miiska la cusboonaysiiyay:
c 25 200
select from tradeAgg where sym=`AAPL
-20#select from tradeAgg where sym=`AAPL
Natiijada:
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|2919Aynu hadda samayno tijaabada culayska si aan u ogaano inta xogta adeeggu ku shaqayn karo daqiiqad kasta. Aan ku xasuusiyo inaan dhignay inta u dhaxaysa 25 millise seconds. Marka la eego, adeeggu waa in (celcelis ahaan) ku habboon yahay ugu yaraan 20 millise seconds cusboonaysiin kasta si loo siiyo isticmaalayaasha waqti ay ku codsadaan xogta. Geli waxa soo socda habka labaad:
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 waa laba daqiiqo. Waxaad isku dayi kartaa inaad marka hore u ordo 1000 saf 25kii millise seconds:
start 1000
Xaaladeyda, natiijadu waxay ku dhowdahay dhowr millise seconds cusbooneysiintiiba. Markaa waxaan isla markiiba kordhin doonaa tirada safafka ilaa 10.000:
start 10000
Natiijada:
min| 00:00:00.004
avg| 9.191458
med| 9f
max| 00:00:00.030
Mar labaad, wax gaar ah ma jiraan, laakiin tani waa 24 milyan oo xariiq daqiiqaddii, 400 kun ilbiriqsi kasta. In ka badan 25 millise seconds, cusboonaysiinta ayaa hoos u dhacday 5 jeer oo keliya, sida muuqata markii daqiiqaddu isbedeshay. Aynu korarno 100.000:
start 100000
Natiijada:
min| 00:00:00.013
avg| 25.11083
med| 24f
max| 00:00:00.108
q)sum times
00:02:00.532
Sida aad arki karto, adeeggu si dhib leh ayuu ula qabsan karaa, laakiin si kastaba ha ahaatee waxa uu maareeyaa in uu sii socdo. Xogta noocan oo kale ah (240 milyan oo saf daqiiqaddii) aad bay u weyn tahay xaaladahan oo kale, waa wax caadi ah in la bilaabo dhowr clones (ama xitaa daraasiin clones) ee adeegga, mid kasta oo ka mid ah oo kaliya qayb ka mid ah jilayaasha. Sidaas oo ay tahay, natiijadu waa mid cajiib ah luqadda la turjumay ee diiradda saarta kaydinta xogta.
Su'aasha ayaa laga yaabaa inay soo baxdo sababta waqtigu u korayo si aan toos ahayn oo leh xajmiga cusbooneysiinta kasta. Sababta ayaa ah in shaqada dhimista ay dhab ahaantii tahay shaqada C, taas oo aad uga waxtar badan marka loo eego updateAgg. Laga bilaabo cabbir cusboonaysiin gaar ah (qiyaastii 10.000), updateAgg wuxuu gaadhay saqafka saqafka ka dibna wakhtiga fulinta kuma xidhna cabbirka cusboonaysiinta. Waxaa ugu wacan tillaabada horudhaca ah ee Q in adeeggu uu awoodo inuu dheefshiido xogtan oo kale. Tani waxay muujineysaa sida ay muhiimka u tahay in la doorto algorithm saxda ah marka la shaqeynayo xog weyn. Qodob kale ayaa ah kaydinta saxda ah ee xogta xusuusta. Haddii xogta aan loo kaydin si columnar ah ama aan la dalban waqti, markaas waxaan la baran lahaa sida wax sida TLB cache miss - maqnaanshaha cinwaanka bogga xusuusta ee kaydinta cinwaanka processor-ka. Raadinta ciwaanku waxay qaadataa ilaa 30 jeer ka dheer haddii lagu guulaysan waayo, iyo haddii xogta la daadiyo, waxay hoos u dhigi kartaa adeegga dhowr jeer.
gunaanad
Maqaalkan, waxaan ku tusay in KDB + iyo xogta Q ay ku habboon yihiin oo kaliya in lagu kaydiyo xogta waaweyn oo si sahlan loo helo iyada oo loo marayo xulashada, laakiin sidoo kale abuurista adeegyo habaynta xogta kuwaas oo awood u leh inay dheefshiido boqolaal milyan oo saf / gigabytes ah oo xog ah xitaa gudaha hal hab oo Q ah. Luuqada Q lafteedu waxa ay ogolaataa in si kooban oo hufan loo hirgaliyo algorithms-yada la xidhiidha habaynta xogta iyada oo ay ugu wacan tahay dabeecadeeda vector, turjubaanka lahjadda SQL ee ku dhex dhisan iyo hab guul leh oo ah shaqooyinka maktabadda.
Waxaan ogaan doonaa in kor ku xusan ay tahay qayb ka mid ah waxa Q uu samayn karo, waxay leedahay astaamo kale oo gaar ah sidoo kale. Tusaale ahaan, hab-maamuuska IPC ee aadka u fudud ee tirtiraya xadka u dhexeeya hababka Q shakhsi ahaaneed oo kuu ogolaanaya inaad ku darto boqollaal hababkan ah hal shabakad, kaas oo ku yaal daraasiin server ah meelo kala duwan oo adduunka ah.
Source: www.habr.com
