Ungafunda mayelana nesisekelo se-KDB+, ulimi lohlelo lwe-Q, ukuthi amandla abo kanye nobuthakathaka buyini kweyami eyedlule.
Isingeniso
I-KDB+ isizindalwazi sekholomu esigxile enanini elikhulu kakhulu ledatha, ehlelwe ngendlela ethile (ikakhulukazi ngesikhathi). Isetshenziswa ngokuyinhloko ezikhungweni zezezimali - amabhange, izimali zokutshala izimali, izinkampani zomshuwalense. Ulimi lwe-Q ulimi lwangaphakathi lwe-KDB+ olukuvumela ukuthi usebenze ngempumelelo nale datha. I-Q ideology imfishane nokusebenza kahle, kuyilapho ukucaca kuyanikelwa. Lokhu kufakazelwa yiqiniso lokuthi ulimi lwe-vector luzoba nzima ukuluqonda kunoma yikuphi, futhi ubufushane nokunotha kokuqoshwa kukuvumela ukuthi ubone ingxenye enkulu kakhulu yohlelo esikrinini esisodwa, okwenza kube lula ukuyiqonda.
Kulesi sihloko sisebenzisa uhlelo olugcwele ku-Q futhi ungase ufune ukuluzama. Ukwenza lokhu, uzodinga u-Q wangempela. Ungalanda inguqulo yamahhala engu-32-bit kuwebhusayithi yenkampani ye-kx -
Ukwakheka kwenkinga
Kunomthombo othumela ithebula elinedatha njalo ngama-millisecond angama-25. Njengoba i-KDB+ isetshenziswa ngokuyinhloko kwezezimali, sizothatha ngokuthi leli itafula lokuthengiselana (ukuhweba), elinamakholomu alandelayo: isikhathi (isikhathi ngama-millisecond), i-sym (igama lenkampani esitokoleni - IBM, AAPL,β¦), inani (inani lapho amasheya athengwa khona), usayizi (usayizi wokwenziwe). Isikhawu esingama-millisecond angu-25 asinasizathu, asincane kakhulu futhi asiside kakhulu. Ukuba khona kwayo kusho ukuthi idatha iza kusevisi isivele ivikelwe. Kungaba lula ukusebenzisa ukugcina kumthamo ohlangothini lwesevisi, okuhlanganisa ukugcina kumthamo okuguquguqukayo kuye ngomthwalo wamanje, kodwa ukuze kube lula, sizogxila kusikhawu esinqunyiwe.
Isevisi kufanele ibale iminithi ngalinye ngophawu ngalunye olungenayo olusuka kukholomu yohlelo isethi yemisebenzi yokuhlanganisa - inani eliphezulu, inani elimaphakathi, usayizi wesamba, njll. ulwazi oluwusizo. Ukwenza kube lula, sizocabanga ukuthi yonke imisebenzi ingabalwa ngokuqhubekayo, i.e. ukuze uthole inani elisha, kwanele ukwazi izinombolo ezimbili - amanani amadala nangenayo. Isibonelo, imisebenzi ubuningi, isilinganiso, isamba sinalesi sici, kodwa umsebenzi we-median awunawo.
Sizophinde sicabange ukuthi ukusakazwa kwedatha engenayo kuhlelwe isikhathi. Lokhu kuzosinika ithuba lokusebenza ngomzuzu wokugcina kuphela. Empeleni, kwanele ukuthi ukwazi ukusebenza ngemizuzu yamanje neyangaphambilini uma kwenzeka ezinye izibuyekezo zephuzile. Ukuze kube lula, ngeke sicabangele leli cala.
Imisebenzi yokuhlanganisa
Imisebenzi edingekayo yokuhlanganisa ibalwe ngezansi. Ngithathe abaningi babo ngangokunokwenzeka ukuze ngandise umthwalo wenkonzo:
- intengo ephezulu β intengo ephezulu ngomzuzu.
- intengo ephansi β encane β inani elincane ngomzuzu.
- firstPrice - intengo yokuqala - intengo yokuqala ngomzuzu.
- lastPrice - intengo yokugcina - intengo yokugcina ngomzuzu.
- OkokuqalaSize - usayizi wokuqala - usayizi wokuqala wokuhweba ngomzuzu.
- lastSize - usayizi wokugcina - usayizi wokugcina wokuhweba ngomzuzu.
- numTrades - count i - inombolo yokuhweba ngomzuzu.
- umthamo - usayizi wesamba - isamba samasayizi okuhweba ngomzuzu.
- i-pvolume β isamba senani β isamba sezintengo ngomzuzu, esidingekayo ku-avgPrice.
- - isamba sentengo yenzuzo * usayizi - umthamo ophelele wokuthengiselana ngomzuzu.
- avgPrice β pvolume%numTrades β isilinganiso senani ngomzuzu.
- avgSize - ivolumu%numTrades - isilinganiso sosayizi wokuhweba ngomzuzu.
- vwap β turnover%volume β intengo emaphakathi ngomzuzu enesisindo ngosayizi wokwenziwe.
- cumVolume - isamba sevolumu - usayizi oqoqiwe wokuthengiselana phakathi naso sonke isikhathi.
Masixoxe ngokushesha ngephuzu elilodwa elingabonakali - ukuthi ungawaqalisa kanjani lawa makholomu okokuqala nangomzuzu ngamunye olandelayo. Amanye amakholomu ohlobo lwe-firstPrice kufanele aqaliswe ukuze angasebenzi isikhathi ngasinye; inani lawo alichazwanga. Ezinye izinhlobo zevolumu kufanele zihlale zisethelwe ku-0. Kukhona futhi amakholomu adinga indlela ehlanganisiwe - isibonelo, i-cumVolume kufanele ikopishwe ukusuka kumzuzu wangaphambilini, futhi kweyokuqala isethwe ku-0. Masimise yonke le mingcele sisebenzisa idatha yesichazamazwi. uhlobo (okufana nerekhodi):
// 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 ΠΎΠ±ΡΡΡΠ½Π΅Π½ Π½ΠΈΠΆΠ΅
Ngingeze i-sym nesikhathi kusichazamazwi ukuze kube lula, manje i-initWith ingumugqa osuvele usuwenziwe osuka kuthebula elihlanganisiwe lokugcina, lapho kusala khona ukusetha i-sym nesikhathi esifanele. Ungayisebenzisa ukuze wengeze imigqa emisha etafuleni.
Sizodinga ama-aggCols lapho sidala umsebenzi wokuhlanganisa. Uhlu kufanele luguqulwe ngenxa yendlela izinkulumo eziku-Q ezihlolwa ngayo (kusuka kwesokudla kuye kwesokunxele). Umgomo uwukuqinisekisa ukuthi isibalo sisuka phezulu siye ku-cumVolume, njengoba amanye amakholomu ancike kwedlule.
Amakholomu adinga ukukopishelwa kuminithi elisha ukusuka kwedlule, ikholomu yosim yengezwa ukuze kube lula:
rollColumns:`sym`cumVolume;
Manje ake sihlukanise amakholomu ngamaqembu ngendlela okufanele abuyekezwe ngayo. Izinhlobo ezintathu zingahlukaniswa:
- Ama-accumulators (ivolumu, inzuzo, ..) - kufanele sengeze inani elingenayo kwedlule.
- Ngephuzu elikhethekile (eliphezulu, eliphansi, ..) - inani lokuqala ngomzuzu lithathwa kudatha engenayo, okusele kubalwa kusetshenziswa umsebenzi.
- Phumula. Njalo kubalwa kusetshenziswa umsebenzi.
Ake sichaze okuguquguqukayo kulawa makilasi:
accumulatorCols:`numTrades`volume`pvolume`turnover;
specialCols:`high`low`firstPrice`firstSize;
I-oda lokubala
Sizobuyekeza ithebula elihlanganisiwe ngezigaba ezimbili. Ngokusebenza kahle, siqala sinciphisa ithebula elingenayo ukuze kube nomugqa owodwa kuphela wohlamvu nomzuzu ngamunye. Iqiniso lokuthi yonke imisebenzi yethu iyakhula futhi iyahlanganisa iqinisekisa ukuthi umphumela walesi sinyathelo esengeziwe ngeke ushintshe. Unganciphisa ithebula usebenzisa ukukhetha:
select high:max price, low:min price β¦ by sym,time.minute from table
Le ndlela inesimo esibi - isethi yamakholomu abaliwe ichazwe ngaphambilini. Ngenhlanhla, ku-Q, ukukhetha kuphinda kusetshenziswe njengomsebenzi lapho ungashintsha khona ama-agumenti adalwe ngamandla:
?[table;whereClause;byClause;selectClause]
Ngeke ngichaze ngokuningiliziwe ifomethi yama-agumenti; esimweni sethu, kuphela noma ngokukhetha izinkulumo eziyoba ezingasho lutho futhi kufanele zibe izichazamazwi zamakholomu efomu!izinkulumo. Ngakho, umsebenzi wokuncipha ungachazwa kanje:
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];
Ukuze kube sobala, ngisebenzise umsebenzi wokuhlaziya, oguqula iyunithi yezinhlamvu ngesisho esingu-Q sibe inani elingadluliswa kumsebenzi we-eval futhi odingekayo ekukhetheni umsebenzi. Futhi qaphela ukuthi ukucubungula kwangaphambili kuchazwa njengokuqagela (okungukuthi, umsebenzi onama-agumenti achazwe ngokwengxenye) womsebenzi okhethiwe, i-agumenti eyodwa (ithebula) ayikho. Uma sisebenzisa i-preprocess etafuleni, sizothola itafula elicindezelwe.
Isigaba sesibili sibuyekeza ithebula elihlanganisiwe. Masiqale sibhale i-algorithm ku-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];
β¦
Ku-Q, kuvamile ukusebenzisa imephu/ukunciphisa imisebenzi esikhundleni samaluphu. Kodwa njengoba i-Q iwulimi lwe-vector futhi singasebenzisa kalula yonke imisebenzi kuzo zonke izimpawu ngesikhathi esisodwa, lapho-ke esilinganisweni sokuqala singenza ngaphandle kweluphu nhlobo, senza imisebenzi kuzo zonke izimpawu ngesikhathi esisodwa:
idx:calcIdx inputTable;
row:aggTable idx;
aggTable[idx;`high]: row[`high] | inputTable`high;
aggTable[idx;`volume]: row[`volume] + inputTable`volume;
β¦
Kodwa singaqhubekela phambili, u-Q uno-opharetha ohlukile futhi onamandla ngokwedlulele - u-opharetha wesabelo ojwayelekile. Ikuvumela ukuthi uguqule isethi yamanani esakhiweni sedatha esiyinkimbinkimbi usebenzisa uhlu lwezinkomba, imisebenzi kanye nezimpikiswano. Esimweni sethu kubonakala kanje:
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;β¦)];
Ngeshwa, ukuze unikeze ithebula udinga uhlu lwemigqa, hhayi amakholomu, futhi kufanele uguqule i-matrix (uhlu lwamakholomu ohlwini lwemigqa) usebenzisa umsebenzi wokupheqa. Lokhu kuyabiza etafuleni elikhulu, ngakho esikhundleni salokho sisebenzisa isabelo esijwayelekile kukholomu ngayinye ngokwehlukana, sisebenzisa umsebenzi wemephu (obukeka njenge-apostrophe):
.[aggTable;;:;]'[(idx;)each aggCols; (row[`high] | inputTable`high;row[`volume] + inputTable`volume;β¦)];
Siphinda sisebenzisa ukuqagela komsebenzi. Futhi qaphela ukuthi ku-Q, ukudala uhlu kuwumsebenzi futhi singawubiza sisebenzisa (imephu) umsebenzi ngamunye ukuthola uhlu lohlu.
Ukuqinisekisa ukuthi isethi yamakholomu abaliwe ayigxili, sizodala inkulumo engenhla ngamandla. Ake siqale sichaze imisebenzi yokubala ikholomu ngayinye, sisebenzisa okuguquguqukayo komugqa nokungenayo ukuze sibhekisele kudatha ehlanganisiwe neyokufaka:
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");
Amanye amakholomu akhethekile; inani lawo lokuqala akufanele libalwe ngomsebenzi. Singanquma ukuthi ingeyokuqala ngomugqa[`numTrades] ikholomu - uma iqukethe u-0, inani lingowokuqala. U-Q unomsebenzi wokukhetha - ?[Uhlu oluphusile;uhlu1;uhlu2] - olukhetha inani ohlwini 1 noma 2 kuye ngesimo esiku-agumenti yokuqala:
// high -> ?[isFirst;inp`high;row[`high]|inp`high]
// @ - ΡΠΎΠΆΠ΅ ΠΎΠ±ΠΎΠ±ΡΠ΅Π½Π½ΠΎΠ΅ ΠΏΡΠΈΡΠ²Π°ΠΈΠ²Π°Π½ΠΈΠ΅ Π΄Π»Ρ ΡΠ»ΡΡΠ°Ρ ΠΊΠΎΠ³Π΄Π° ΠΈΠ½Π΄Π΅ΠΊΡ Π½Π΅Π³Π»ΡΠ±ΠΎΠΊΠΈΠΉ
@[`aggExpression;specialCols;{[x;y]"?[isFirst;inp`",y,";",x,"]"};string specialCols];
Lapha ngibize umsebenzi ojwayelekile ngomsebenzi wami (inkulumo kumabrace asontekile). Ithola inani lamanje (i-agumenti yokuqala) kanye ne-agumenti eyengeziwe, engiyidlulisa kupharamitha yesi-4.
Ake sengeze izipikha zebhethri ngokuhlukana, njengoba umsebenzi uyafana kuzo:
// volume -> row[`volume]+inp`volume
aggExpression[accumulatorCols]:{"row[`",x,"]+inp`",x } each string accumulatorCols;
Lesi isabelo esivamile ngamazinga we-Q, kodwa nginikeza uhlu lwamanani ngesikhathi esisodwa. Ekugcineni, masidale umsebenzi oyinhloko:
// ":",/: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),")]}";
Ngalesi sisho, ngidala umsebenzi osuka kuyunithi yezinhlamvu equkethe isisho engisinikeze ngenhla. Umphumela uzobukeka kanje:
{[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])]}
Uhlelo lokuhlola ikholomu luhlanekezelwe ngenxa yokuthi ku-Q uhlelo lokuhlola lusuka kwesokudla uye kwesokunxele.
Manje sinemisebenzi emibili eyinhloko edingekayo ekubaleni, sidinga nje ukwengeza ingqalasizinda encane futhi isevisi isilungile.
Izinyathelo zokugcina
Sinemisebenzi ye-preprocess kanye ne-updateAgg eyenza wonke umsebenzi. Kodwa kusadingeka ukuthi uqinisekise uguquko olulungile ngemizuzu futhi ubale izinkomba zokuhlanganisa. Okokuqala, ake sichaze umsebenzi we-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
}
Sizophinde sichaze umsebenzi we-roll, ozoshintsha iminithi lamanje:
roll:{[tm]
if[currTime>tm; :init[]]; // Π΅ΡΠ»ΠΈ ΠΏΠ΅ΡΠ΅Π²Π°Π»ΠΈΠ»ΠΈ Π·Π° ΠΏΠΎΠ»Π½ΠΎΡΡ, ΡΠΎ ΠΏΡΠΎΡΡΠΎ Π²ΡΠ·ΠΎΠ²Π΅ΠΌ init
rollCache,::offset _ rollColumns#tradeAgg; // ΠΎΠ±Π½ΠΎΠ²ΠΈΠΌ ΠΊΡΡ β Π²Π·ΡΡΡ roll ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ ΠΈΠ· aggTable, ΠΎΠ±ΡΠ΅Π·Π°ΡΡ, Π²ΡΡΠ°Π²ΠΈΡΡ Π² rollCache
offset::count tradeAgg;
currSyms::`u#`$();
}
Sizodinga umsebenzi ukwengeza izinhlamvu ezintsha:
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)];
}
Futhi ekugcineni, umsebenzi wokuvuselela (igama lendabuko lalo msebenzi wezinsizakalo ze-Q), obizwa iklayenti ukwengeza idatha:
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]; // ΠΎΠ±Π½ΠΎΠ²ΠΈΠΌ Π°Π³ΡΠ΅Π³ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΡΠ°Π±Π»ΠΈΡΡ. Π€ΡΠ½ΠΊΡΠΈΡ ? ΠΈΡΠ΅Ρ ΠΈΠ½Π΄Π΅ΠΊΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² ΡΠΏΠΈΡΠΊΠ° ΡΠΏΡΠ°Π²Π° Π² ΡΠΏΠΈΡΠΊΠ΅ ΡΠ»Π΅Π²Π°.
};
Yilokho kuphela. Nansi ikhodi ephelele yenkonzo yethu, njengoba kuthenjisiwe, imigqa embalwa nje:
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];
};
Ukuhlola
Ake sihlole ukusebenza kwesevisi. Ukwenza lokhu, asiyiqalise ngenqubo ehlukile (faka ikhodi kufayela le-service.q) bese sishayela umsebenzi we-init:
q service.q βp 5566
q)init[]
Kwenye ikhonsoli, qala inqubo yesibili ye-Q bese uxhuma kweyokuqala:
h:hopen `:host:5566
h:hopen 5566 // Π΅ΡΠ»ΠΈ ΠΎΠ±Π° Π½Π° ΠΎΠ΄Π½ΠΎΠΌ Ρ
ΠΎΡΡΠ΅
Okokuqala, masidale uhlu lwezimpawu - izingcezu eziyi-10000 futhi sengeze umsebenzi ukuze sakhe ithebula elingahleliwe. Kwikhonsoli yesibili:
syms:`IBM`AAPL`GOOG,-9997?`8
rnd:{[n;t] ([] sym:n?syms; time:t+asc n#til 25; price:n?10f; size:n?10)}
Ngengeze izimpawu zangempela ezintathu ohlwini ukuze kube lula ukuzibheka etafuleni. Umsebenzi we-rnd udala ithebula elingahleliwe elinemigqa engu-n, lapho isikhathi sihluka ukusuka ku-t ukuya ku-t+25 millisecond.
Manje ungazama ukuthumela idatha kusevisi (engeza amahora ayishumi okuqala):
{h (`upd;`trade;rnd[10000;x])} each `time$00:00 + til 60*10
Ungahlola isevisi ukuthi ithebula libuyekeziwe:
c 25 200
select from tradeAgg where sym=`AAPL
-20#select from tradeAgg where sym=`AAPL
Umphumela:
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
Manje ake senze ukuhlola komthwalo ukuze sithole ukuthi ingakanani idatha isevisi engayicubungula ngomzuzu. Ake ngikukhumbuze ukuthi simisa isikhathi sokubuyekeza sibe ama-millisecond angu-25. Ngokufanelekile, isevisi kufanele (ngokwesilinganiso) ingene okungenani kuma-millisecond angu-20 isibuyekezo ngasinye ukuze inikeze abasebenzisi isikhathi sokucela idatha. Faka okulandelayo ohlelweni lwesibili:
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 imizuzu emibili. Ungazama ukugijima kuqala ngemigqa engu-1000 njalo ngama-millisecond angama-25:
start 1000
Endabeni yami, umphumela uzungeze ama-millisecond ambalwa ngesibuyekezo ngasinye. Ngakho-ke ngizokwengeza ngokushesha inombolo yemigqa ibe ngu-10.000:
start 10000
Umphumela:
min| 00:00:00.004
avg| 9.191458
med| 9f
max| 00:00:00.030
Futhi, akukho okukhethekile, kodwa lokhu kuyimigqa eyizigidi ezingu-24 ngomzuzu, izinkulungwane ezingama-400 ngomzuzwana. Ngama-millisecond angaphezu kwangu-25, isibuyekezo sehlise ijubane izikhathi ezi-5 kuphela, ngokusobala lapho iminithi ishintsha. Masikhuphukele ku-100.000:
start 100000
Umphumela:
min| 00:00:00.013
avg| 25.11083
med| 24f
max| 00:00:00.108
q)sum times
00:02:00.532
Njengoba ubona, insizakalo ayikwazi ukubhekana nalokhu, kodwa noma kunjalo iyakwazi ukuhlala ihamba. Ivolumu enjalo yedatha (imigqa eyizigidi ezingama-240 ngomzuzu) inkulu kakhulu; ezimweni ezinjalo, kuvamile ukwethula ama-clones amaningana (noma inqwaba yama-clones) wesevisi, ngayinye ecubungula ingxenye yezinhlamvu kuphela. Noma kunjalo, umphumela uyahlaba umxhwele ngolimi olutolikiwe olugxile kakhulu ekugcinweni kwedatha.
Kungase kuphakame umbuzo wokuthi kungani isikhathi sikhula ngokungahambisani nosayizi wesibuyekezo ngasinye. Isizathu siwukuthi umsebenzi we-shrink empeleni uwumsebenzi we-C, osebenza kahle kakhulu kune-updateAgg. Kusukela kusayizi othile wokubuyekeza (cishe u-10.000), i-updateAgg ifinyelela ophahleni lwayo bese isikhathi sayo sokwenza singanciki kusayizi wokubuyekeza. Kungenxa yesinyathelo sokuqala u-Q ukuthi isevisi ikwazi ukugaya amavolumu anjalo edatha. Lokhu kugqamisa ukuthi kubaluleke kangakanani ukukhetha i-algorithm efanele uma usebenza nedatha enkulu. Elinye iphuzu ukugcinwa okufanele kwedatha kumemori. Uma idatha ibingagcinwanga ngokwekholomu noma ibinga-odwanga ngesikhathi, besiyobe sesijwayelana nento efana nokuphuthelwa kwenqolobane ye-TLB - ukungabikho kwekheli lekhasi lememori kunqolobane yekheli lokucubungula. Ukusesha ikheli kuthatha cishe izikhathi ezingu-30 ubude uma kungasebenzi, futhi uma idatha ihlakazeka, inganciphisa isevisi izikhathi ezimbalwa.
isiphetho
Kulesi sihloko, ngibonise ukuthi i-database ye-KDB+ ne-Q ayifanele kuphela ukugcina idatha enkulu futhi uyifinyelele kalula ngokukhetha, kodwa futhi nokudala izinsizakalo zokucubungula idatha ezikwazi ukugaya amakhulu ezigidi zemigqa/gigabytes yedatha ngisho naku- inqubo eyodwa Q eyodwa. Ulimi lwe-Q ngokwalo luvumela ukusetshenziswa okufushane kakhulu nangempumelelo kwama-algorithms ahlobene nokucutshungulwa kwedatha ngenxa yemvelo yayo ye-vector, umhumushi wolimi we-SQL owakhelwe ngaphakathi kanye nesethi ephumelele kakhulu yemisebenzi yelabhulali.
Ngizoqaphela ukuthi lokhu okungenhla kuyingxenye yalokho u-Q angakwenza, inezinye izici eziyingqayizivele futhi. Isibonelo, iphrothokholi ye-IPC elula kakhulu esula umngcele phakathi kwezinqubo ezingazodwana ze-Q futhi ikuvumela ukuthi uhlanganise amakhulu alezi zinqubo ube yinethiwekhi eyodwa, etholakala kumaseva amaningi ezingxenyeni ezihlukene zomhlaba.
Source: www.habr.com