Lineamenta Q et KDB+ linguae utentes exemplo muneris realis-temporis

Legere potes quid in basi KDB+, in lingua programmandi Q sint, quae vires et debilitates in praecedentibus meis sunt. articulus et breviter in prooemio. In articulo, operam in Q efficiemus, quae notitiae advenientis amnis processura est et varias aggregationis functiones minutatim in modum "temporis reali" (i.e., tempus erit omnia computare ante proximam partem notitiarum). Praecipuum notae Q est quod lingua vector est quae non in singulis rebus operari sinit, sed cum vestitu, vestitu, vestitu et aliis rebus complexis. Linguae ut Q et propinqui K, J, APL brevitati sunt celebres. Saepe programma, quod varias tegumenta codicis in lingua familiari quasi Javae suscipit, paucis lineis in iis scribi potest. Hoc est quod in hoc articulo demonstrare volo.

Lineamenta Q et KDB+ linguae utentes exemplo muneris realis-temporis

introduction

KDB+ datorum columnarum in maximas notitiarum copia feruntur, certo modo (praesertim tempore). Imprimis adhibetur in institutis nummariis, ripae, pecuniae collocandae, manipulos assecurationis. Lingua Q lingua est interna KDB+ quae te cum hac notitia efficaciter operari sinit. In Q doetrina brevitas et efficacia est, et claritas immolatur. Hoc iustificatur ex eo quod lingua vector difficilis erit ad intelligendum in omni casu, et brevitas et ubertas recordationis permittit te videre multo maiorem partem programmatis in uno velo, quod tandem facilius intellegitur.

In hoc articulo programma in Q currum plenam efficiendum et experiri forsitan velis. Ad hoc faciendum, ipsa Q. egere potes liberam 32-bit versionem in kx societatis paginae - www.kx.com. Ibi, si interest, informationes in Q, libri invenies Q pro mortalibus et varia de hoc argumento capitula.

DE PECCATO quaestio

Fons est qui mensam mittit cum singulis 25 milliseconds notitia. Cum KDB+ principaliter in rebus oeconomicis adhibetur, ponemus hanc esse tabulam negotiorum (artium), quae habet sequentes columnas: tempus (tempus milliseconds), sym (comitatio designatio in commercio stirpis - IBM, AAPL,. Intervallum XXV millisecondum arbitrarium est, nec nimium parvum nec longum. Praesentia eius significat notitias ad servitium iam buffered. Facile esset ad efficiendum buffering in parte muneris, inter dynamica buffering pendentia in onere currenti, sed pro simplicitate fixum intervallum ponemus.

Ministerium singulis momentis pro singulis advenientibus symbolo computare debet e sym columnae statuto functionum aggregationis - max pretis, avg pretii, summae magnitudinis, etc. utilis notitia. Pro simplicitate, ponemus omnes functiones incrementaliter computari posse, i.e. ut novum valorem obtineat, satis est duos numeros cognoscere, veteres et advenientes valores. Exempli gratia, munera max, mediocris, summa proprietatem hanc habent, sed munus mediana non habet.

Volumus etiam, ut rivus notitiae advenientis tempus iussum sit. Haec nobis facultas operandi solum ultimo minuto dabit. Re, satis est cum momentis currentibus et prioribus elaborare posse si quaedam recentia updates sunt. Pro simplici hoc casu non consideramus.

Aggregatio munera

Munera aggregationis debita infra recensentur. Earum quam plurimas accepi, ut onus in ministerium augerem;

  • magno - max pretio - maximum pretium per minute.
  • low - min price - minimum price per minute.
  • firstPrice - first price - first price per minute.
  • lastPrice - last price - last price per minute.
  • firstSize - first size - first trade size per minute.
  • lastSize - last size - last trade size in minutam.
  • numTrades - count i - number of artium per minute.
  • Volume - summa magnitudo - summa commercii magnitudinum per minutum.
  • pvolume - summa pretia - summa pretia per minutias, pro avgPrice requisiti.
  • - sum turnover price* size - total volumen transactionum per minute.
  • avgPrice - pvolume%numTrades - mediocris pretium per minute.
  • avgSize - volume%numTrades - mediocris artis magnitudo per minute.
  • vwap - turnover% volume - mediocris pretium per minute praegravatis negotii magnitudine.
  • cumVolume - summa volubilis - magnitudine rerum per totum tempus congesta.

De puncto non conspicuo statim discutiamus β€” quomodo has columnas primum initializes et minutas singulas subsequentes. Nonnullae primae quantitatis columnae singulis temporibus initiales fieri debent, earumque valor indefinitus est. Aliae figurae voluminis semper ad 0. Exstant etiam columnae quae accessum coniunctum requirunt - exempli gratia, cum Volumen ex priori minuto exscribendum sit, et primum ad 0. Ponamus omnes istos parametros utentes dictionarii notitia type (analogus to a record):

// 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 объяснСн Π½ΠΈΠΆΠ΅

Addidi sym et tempus glossarium commoditatis, nunc initWith linea parata facta est e tabula finali aggregata, ubi superest ut rectam sym et tempus apponas. Ad mensam novos ordines addere potes.

Nos aggCols egebimus, cum munus aggregationis creando. Elenchus invertendus est ob ordinem quo aestimantur expressiones in Q (a dextra ad sinistram). Finis est curare calculus ab alto usque ad cumVolume, quoniam aliquae columnae a superioribus pendent.

Columnae quae ex priori novo minuto exscribendae sunt, ad commodam sym columnam additur:

rollColumns:`sym`cumVolume;

Nunc columnas dividamus in partes secundum quomodo renovandae sunt. Tria genera distingui possunt;

  1. Accumulatores (volumen, turnover,...) – accessum valorem priori adiciendum est.
  2. Peculiari puncto (alto, humili, ..) - prima valoris in minuto ex notitia advenientis accipitur, reliqua functione utentes computantur.
  3. Requiem. Semper ratione usus functionis.

Diffinimus variabiles hasce classes:

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

Calculus ordo

Mensam aggregatam in duobus gradibus renovabimus. Ad efficientiam venientem tabulam primo abhorremus ita ut unus tantum ordo sit cuiusque characteris et momenti. Quod omnia munera nostra sunt cautiones incrementales et associativas quod effectus accessus additi gradus non mutatur. Mensam recusare poteras utens eligere:

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

Haec methodus incommodum habet - copia columnarum calculi praedefinita est. Fortunate, in Q, selectis etiam munus impletur ubi rationes dynamice creatae substituere potes;

?[table;whereClause;byClause;selectClause]

Formam argumentorum non singillatim describam, in casu tantum ac voces selectae nontriviales erunt et dictionaria columnarum formarum sint locutiones. Quapropter munus recusationis sic definiri potest:

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];

Ad evidentiam, usus sum functione parse, quae filum cum expressione Q vertit in valorem qui ad munus coaevum transiri potest et quod in munere selecto requiritur. Notandum etiam quod preprocessus definitur proiectio (i.e., functio cum argumentis partim definitis) functionis selectae, unum argumentum deesse. Si praeprocessionem applicamus ad mensam, compressam mensam accipiemus.

Secundus gradus mensam aggregatam adaequat. Primum algorithmum in pseudocode scribamus:

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];
  …

In Q, commune est functionum tabularum reducere pro ansulis uti. Sed quia Q est lingua vector et omnes operationes ad omnia simul symbola facile possumus, deinde ad primam approximationem sine ansa facere possumus, operationes in omnibus symbolis simul peragentes;

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

Sed ulterius progredi possumus, Q habet operator singularem et valde potentem - operator assignatio generalis. Permittit te mutare certa bona in structura notitia multiplici utens indice indices, munerum et argumentorum. In nostro casu sic spectat:

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;…)];

Infeliciter, tabulae assignare debes index ordinum, non columnarum, et matricem (album columnarum ad indicem ordinum) transponere debes, functione flip. Haec carus est pro magna mensa, sic loco singulae columnae divisim assignationem generalem applicamus, functione geographica adhibita (quae sicut apostropha spectat);

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

Munus proiectura iterum utimur. Etiam notandum est quod in Q, elenchum creans munus quoque esse et appellare possumus eum utentem singulas functiones ut indicem tabularum accipias.

Ut statuta columnarum calcularum non figatur, hanc expressionem alacriter efficiemus. Prius functiones definias ad singulas columnas computandas, variabilium versuum et inp utentium, referre ad notitias aggregatas et initus;

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");

Quaedam sunt speciales columnae, earum prima dignitas non pensari debet. Determinare possumus eam esse primam per columnam [`numTrades] β€” si contineat 0, primum valorem. Q munus selectum habet - ?[Index Boolean;list1;list2] - qui valorem eligit ex indice 1 vel 2 secundum conditionem primae argumenti:

// high -> ?[isFirst;inp`high;row[`high]|inp`high]
// @ - Ρ‚ΠΎΠΆΠ΅ ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½Π½ΠΎΠ΅ присваиваниС для случая ΠΊΠΎΠ³Π΄Π° индСкс Π½Π΅Π³Π»ΡƒΠ±ΠΎΠΊΠΈΠΉ
@[`aggExpression;specialCols;{[x;y]"?[isFirst;inp`",y,";",x,"]"};string specialCols];

Hic vocavi munus generale cum mea functione (expressio in crispo adstringit). Praesens valorem (primum argumentum) recipit et argumentum adiectum, quod in 4to parametro praetereo.

Seorsim adiciamus oratores altilium, quia idem est illis munus;

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

Haec signa consueta est assignatio per Q, sed indicem valorum statim assigno. Postremo munus praecipuum crearemus;

// ":",/: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),")]}";

Hac expressione, dynamice munus creo ex filo quod supra dictum est continet. Eventus sic erit:

{[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])]}

Columna aestimatio ordinis invertitur eo quia ordo aestimationis in Q est a dextro ad sinistrum.

Nunc habemus duas praecipuas functiones ad calculos necessarias, tantum opus est ut paulo infrastructura addatur et ad servitium promptum.

Gradus finales

Praeprocessionem habemus et renovationes Agg functiones quae totum opus faciunt. Sed adhuc necessarium est ut rectam transitum per minutas et indices pro aggregatione curaret. Primum munus initum definiamus;

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
 }

Etiam munus volvi definiemus, quod currens minutum mutabit;

roll:{[tm]
  if[currTime>tm; :init[]]; // Ссли ΠΏΠ΅Ρ€Π΅Π²Π°Π»ΠΈΠ»ΠΈ Π·Π° ΠΏΠΎΠ»Π½ΠΎΡ‡ΡŒ, Ρ‚ΠΎ просто Π²Ρ‹Π·ΠΎΠ²Π΅ΠΌ init
  rollCache,::offset _ rollColumns#tradeAgg; // ΠΎΠ±Π½ΠΎΠ²ΠΈΠΌ кэш – Π²Π·ΡΡ‚ΡŒ roll ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ ΠΈΠ· aggTable, ΠΎΠ±Ρ€Π΅Π·Π°Ρ‚ΡŒ, Π²ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Π² rollCache
  offset::count tradeAgg;
  currSyms::`u#`$();
 }

Munus nos oportet addere novas characteres:

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)];
 }

Ac denique munus upd (nomen traditum huic functioni pro Q servitiis), quod a cliente dicitur, notitias addere;

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]; // ΠΎΠ±Π½ΠΎΠ²ΠΈΠΌ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½Π½ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ. Ѐункция ? ΠΈΡ‰Π΅Ρ‚ индСкс элСмСнтов списка справа Π² спискС слСва.
 };

Id omne. Hic est integer codicis nostri officium, ut pollicitus est, paucas lineas;

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];
 };

temptationis

Inhibeamus observantiam ministerii. Quod ut facias, illud in processu separato (pone signum in servicio.q fasciculi) curramus et munus initum vocamus:

q service.q –p 5566

q)init[]

In alio consolare, incipit in secundo processu Q et coniunge primo;

h:hopen `:host:5566
h:hopen 5566 // Ссли ΠΎΠ±Π° Π½Π° ΠΎΠ΄Π½ΠΎΠΌ хостС

Primum indicem faciamus symbolorum - 10000 frusta et munus addere ad mensam temere creandam. In secundo console;

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

Tria symbola realia addidi in albo, quo facilius ea in tabula quaererem. Munus rnd mensam temere cum n ordinibus creat, ubi tempus ab t ad t+25 milliseconds variatur.

Nunc experiri potes ut notitias mittens ad officium (primas decem horas adde);

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

Potes inspicere in servitio quod mensa renovata est:

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

effectus:

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

Nunc onere experiamur ut sciamus quanti notitia muneris per minutias processum facere possit. Fac me monere te intervallum renovationis 25 milliseconds constituisse. Proinde officium (mediocris) aptum est saltem viginti millium secundorum per renovationem ad utentes tempus dare petendi notitias. Intra sequentia in secundo processu:

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)}

(IV)DCCC duo minuta est. Tentare potes primum pro 4800 ordinibus singulis 1000 milliseconds currentem:

start 1000

In casu meo, effectus est circiter duorum millium secundorum per update. Itaque statim numerum versuum ad 10.000 augebo;

start 10000

effectus:

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

Iterum nihil speciale, sed hoc est 24 decies centena millia linearum per minutias, 400 mille per secundam. Plus quam 25 millium secundorum millium secundorum renovatio retardatur tantum 5 vicibus, ut videtur, cum minutum mutatur. Crescamus ad 100.000:

start 100000

effectus:

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

Ut videre potes, ministerium vix tolerare potes, sed tamen administrat meatum manere. Tale volumen notitiarum (CCXL milium ordinum per minutum) perquam magnum est, in quo casu commune est ut complures clones (vel etiam justos clones) servitii emittant, quorum unumquemque tantum partem characterum procedit. Tamen, eventus gravis est ad linguam interpretandam quae principaliter in notitia repono.

Quaeri potest, cur tempus non-lineaaliter cum magnitudine uniuscuiusque renovationis crescat. Ratio est, quia recusatum munus est actu functionis C, quae multo efficacior est quam renovatio Agg. Incipiens a quadam magnitudine renovationis (circa 10.000), renovatio Agg lacunam suam attingit ac deinde tempus exsecutionis eius in magnitudine renovationis non pendet. Ob praelibatum gradum Q ut religio possit tales notitias volumina concoquere. Hoc elucidat quanti momenti sit eligere ius algorithmum cum operando cum magnis data. Aliud punctum est recta tabularia notitiarum in memoria. Si notitia electronica non reponeretur vel tempore non ordinata essemus, tunc nota fierimus cum tali re quae deesset TLB cache - absentia memoriae paginae electronicae in processu electronici cella. Investigatio inscriptionis circiter XXX vicibus accipit si parum prospere, et si notitiae dissipatae sunt, servitium pluries retardare potest.

conclusio,

In hoc articulo demonstravi datorum KDB+ et Q apta esse non solum ad magnas notitias accommodandas et facile per selectas accessiones, sed etiam ad operas processus notitias conficiendas, quae centenis decies centena milium versuum/gigabytorum notitiarum concoquendarum capaces sunt. Q processus . Lingua ipsa Q permittit ad exsecutionem algorithmorum valde concisam et efficacem pertinentium ad processus notitiae ex natura sua vectoris, in dialecto SQL interpres constructa et functiones bibliothecae felicissimae.

Notabo hanc partem iustam esse quid Q facere possit, et alias singulares notas habere. Exempli gratia, protocollum IPC simplicissimum, quod limitem inter singulos Q processuum delet et centum horum processuum in unum retis coniungere sinit, quae in justo servientium in diversis mundi partibus collocari potest.

Source: www.habr.com