ВозмоТности языка Q ΠΈ KDB+ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ сСрвиса Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ

О Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ Π±Π°Π·Π° KDB+, язык программирования Q, ΠΊΠ°ΠΊΠΈΠ΅ Ρƒ Π½ΠΈΡ… Π΅ΡΡ‚ΡŒ ΡΠΈΠ»ΡŒΠ½Ρ‹Π΅ ΠΈ слабыС стороны, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π² ΠΌΠΎΠ΅ΠΉ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΈ ΠΊΡ€Π°Ρ‚ΠΊΠΎ Π²ΠΎ Π²Π²Π΅Π΄Π΅Π½ΠΈΠΈ. Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΆΠ΅ ΠΌΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ Π½Π° Q сСрвис, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ входящий ΠΏΠΎΡ‚ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Π²Ρ‹ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΠΎΠΌΠΈΠ½ΡƒΡ‚Π½ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ β€œΡ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ врСмСни” (Ρ‚.Π΅. Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΡΠΏΠ΅Π²Π°Ρ‚ΡŒ всС ΠΏΠΎΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π΄ΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΏΠΎΡ€Ρ†ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ…). Главная ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ Q состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ это Π²Π΅ΠΊΡ‚ΠΎΡ€Π½Ρ‹ΠΉ язык, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ ΠΎΠΏΠ΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅ Π΅Π΄ΠΈΠ½ΠΈΡ‡Π½Ρ‹ΠΌΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ, Π° ΠΈΡ… массивами, массивами массивов ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ слоТносоставными ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ. Π’Π°ΠΊΠΈΠ΅ языки ΠΊΠ°ΠΊ Q ΠΈ родствСнныС Π΅ΠΌΡƒ K, J, APL Π·Π½Π°ΠΌΠ΅Π½ΠΈΡ‚Ρ‹ своСй ΠΊΡ€Π°Ρ‚ΠΊΠΎΡΡ‚ΡŒΡŽ. НСрСдко ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, Π·Π°Π½ΠΈΠΌΠ°ΡŽΡ‰ΡƒΡŽ нСсколько экранов ΠΊΠΎΠ΄Π° Π½Π° ΠΏΡ€ΠΈΠ²Ρ‹Ρ‡Π½ΠΎΠΌ языкС Ρ‚ΠΈΠΏΠ° Java, ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π½Π° Π½ΠΈΡ… Π² нСсколько строк. ИмСнно это я ΠΈ Ρ…ΠΎΡ‡Ρƒ ΠΏΡ€ΠΎΠ΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅.

ВозмоТности языка Q ΠΈ KDB+ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ сСрвиса Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ

Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅

KDB+ β€” это колоночная Π±Π°Π·Π° Π΄Π°Π½Π½Ρ‹Ρ…, ориСнтированная Π½Π° ΠΎΡ‡Π΅Π½ΡŒ большиС ΠΎΠ±ΡŠΠ΅ΠΌΡ‹ Π΄Π°Π½Π½Ρ‹Ρ…, упорядочСнныС ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ (Π² ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ). Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠ½Π°, Π² ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, Π² финансовых организациях – Π±Π°Π½ΠΊΠ°Ρ…, инвСстиционных Ρ„ΠΎΠ½Π΄Π°Ρ…, страховых компаниях. Π―Π·Ρ‹ΠΊ Q – это Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΉ язык KDB+, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΠΈΠΉ эффСктивно Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с этими Π΄Π°Π½Π½Ρ‹ΠΌΠΈ. ИдСология Q – это ΠΊΡ€Π°Ρ‚ΠΊΠΎΡΡ‚ΡŒ ΠΈ ΡΡ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ, ΠΏΠΎΠ½ΡΡ‚Π½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈ этом приносится Π² ΠΆΠ΅Ρ€Ρ‚Π²Ρƒ. ΠžΠ±ΠΎΡΠ½ΠΎΠ²Ρ‹Π²Π°Π΅Ρ‚ΡΡ это Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Π²Π΅ΠΊΡ‚ΠΎΡ€Π½Ρ‹ΠΉ язык Π² любом случаС Π±ΡƒΠ΄Π΅Ρ‚ слоТСн для восприятия, Π° ΠΊΡ€Π°Ρ‚ΠΊΠΎΡΡ‚ΡŒ ΠΈ Π½Π°ΡΡ‹Ρ‰Π΅Π½Π½ΠΎΡΡ‚ΡŒ записи позволяСт ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ Π½Π° ΠΎΠ΄Π½ΠΎΠΌ экранС Π³ΠΎΡ€Π°Π·Π΄ΠΎ Π±ΠΎΠ»ΡŒΡˆΡƒΡŽ Ρ‡Π°ΡΡ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Ρ‡Ρ‚ΠΎ Π² ΠΈΡ‚ΠΎΠ³Π΅ ΠΎΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ Π΅Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅.

Π’ ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ ΠΏΠΎΠ»Π½ΠΎΡ†Π΅Π½Π½ΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ Π½Π° Q ΠΈ Π²Π°ΠΌ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, захочСтся ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ Π² Π΄Π΅Π»Π΅. Для этого Π²Π°ΠΌ понадобится собствСнно Q. Π‘ΠΊΠ°Ρ‡Π°Ρ‚ΡŒ Π±Π΅ΡΠΏΠ»Π°Ρ‚Π½ΡƒΡŽ 32-Π±ΠΈΡ‚Π½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ Π½Π° сайтС ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ kx – www.kx.com. Π’Π°ΠΌ ΠΆΠ΅, Ссли Π²Π°ΠΌ интСрСсно, Π²Ρ‹ Π½Π°ΠΉΠ΄Π΅Ρ‚Π΅ ΡΠΏΡ€Π°Π²ΠΎΡ‡Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΏΠΎ Q, ΠΊΠ½ΠΈΠ³Ρƒ Q For Mortals ΠΈ Ρ€Π°Π·Π½ΠΎΠΎΠ±Ρ€Π°Π·Π½Ρ‹Π΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ Π½Π° эту Ρ‚Π΅ΠΌΡƒ.

ΠŸΠΎΡΡ‚Π°Π½ΠΎΠ²ΠΊΠ° Π·Π°Π΄Π°Ρ‡ΠΈ

Π•ΡΡ‚ΡŒ источник, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ присылаСт ΠΊΠ°ΠΆΠ΄Ρ‹Π΅ 25 миллисСкунд Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ с Π΄Π°Π½Π½Ρ‹ΠΌΠΈ. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ KDB+ примСняСтся Π² ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ Π² финансах, Π±ΡƒΠ΄Π΅ΠΌ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ это Ρ‚Π°Π±Π»ΠΈΡ†Π° сдСлок (trades), Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π΅ΡΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ: time (врСмя Π² миллисСкундах), sym (ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠ°Π½ΠΈΠΈ Π½Π° Π±ΠΈΡ€ΠΆΠ΅ – IBM, AAPL,…), price (Ρ†Π΅Π½Π°, ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΊΡƒΠΏΠ»Π΅Π½Ρ‹ Π°ΠΊΡ†ΠΈΠΈ), size (Ρ€Π°Π·ΠΌΠ΅Ρ€ сдСлки). Π˜Π½Ρ‚Π΅Ρ€Π²Π°Π» 25 миллисСкунд Π²Ρ‹Π±Ρ€Π°Π½ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½ΠΎ, ΠΎΠ½ Π½Π΅ слишком малСнький ΠΈ Π½Π΅ слишком большой. Π•Π³ΠΎ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Π΄Π°Π½Π½Ρ‹Π΅ приходят Π² сСрвис ΡƒΠΆΠ΅ Π±ΡƒΡ„Π΅Ρ€ΠΈΠ·ΠΎΠ²Π°Π½Π½Ρ‹Π΅. МоТно Π±Ρ‹Π»ΠΎ Π±Ρ‹ Π»Π΅Π³ΠΊΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π±ΡƒΡ„Π΅Ρ€ΠΈΠ·Π°Ρ†ΠΈΡŽ Π½Π° сторонС сСрвиса, Π² Ρ‚ΠΎΠΌ числС Π΄ΠΈΠ½Π°ΠΌΠΈΡ‡Π΅ΡΠΊΡƒΡŽ, Π·Π°Π²ΠΈΡΡΡ‰ΡƒΡŽ ΠΎΡ‚ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ, Π½ΠΎ для простоты остановимся Π½Π° фиксированном ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Π΅.

БСрвис Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ ΠΏΠΎΠΌΠΈΠ½ΡƒΡ‚Π½ΠΎ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ входящСго символа ΠΈΠ· ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ sym Π½Π°Π±ΠΎΡ€ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΡƒΡŽΡ‰ΠΈΡ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ – max price, avg price, sum size ΠΈ Ρ‚.ΠΏ. ΠΏΠΎΠ»Π΅Π·Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ. Для простоты ΠΌΡ‹ ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Ρ‚ΠΎ всС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡ‚ΡŒ ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½ΠΎ, Ρ‚.Π΅. для получСния Π½ΠΎΠ²ΠΎΠ³ΠΎ значСния достаточно Π·Π½Π°Ρ‚ΡŒ Π΄Π²Π° числа – староС ΠΈ входящСС значСния. НапримСр, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ max, average, sum ΠΎΠ±Π»Π°Π΄Π°ΡŽΡ‚ этим свойством, Π° функция ΠΌΠ΅Π΄ΠΈΠ°Π½Π° Π½Π΅Ρ‚.

Π’Π°ΠΊΠΆΠ΅ ΠΌΡ‹ ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Ρ‡Ρ‚ΠΎ входящий ΠΏΠΎΡ‚ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ… упорядочСн ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. Π­Ρ‚ΠΎ даст Π½Π°ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ с послСднСй ΠΌΠΈΠ½ΡƒΡ‚ΠΎΠΉ. На ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅ достаточно ΡƒΠΌΠ΅Ρ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΈ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ ΠΌΠΈΠ½ΡƒΡ‚Π°ΠΌΠΈ Π½Π° случай, Ссли ΠΊΠ°ΠΊΠΈΠ΅-Ρ‚ΠΎ Π°ΠΏΠ΄Π΅ΠΉΡ‚Ρ‹ Π·Π°ΠΏΠΎΠ·Π΄Π°Π»ΠΈ. Для простоты ΠΌΡ‹ Π½Π΅ Π±ΡƒΠ΄Π΅ΠΌ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ этот случай.

ΠΠ³Ρ€Π΅Π³ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

НиТС пСрСчислСны Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π― взял ΠΈΡ… ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ большС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΡ‚ΡŒ Π½Π°Π³Ρ€ΡƒΠ·ΠΊΡƒ Π½Π° сСрвис:

  • high – max price – максимальная Ρ†Π΅Π½Π° Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • low – min price – минимальная Ρ†Π΅Π½Π° Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • firstPrice – first price – пСрвая Ρ†Π΅Π½Π° Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • lastPrice – last price – послСдняя Ρ†Π΅Π½Π° Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • firstSize – first size – ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ сдСлки Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • lastSize – last size β€” послСдний Ρ€Π°Π·ΠΌΠ΅Ρ€ сдСлки Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • numTrades – count i – число сдСлок Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • volume – sum size – сумма Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠ² сдСлок Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • pvolume – sum price – сумма Ρ†Π΅Π½ Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ для avgPrice.
  • turnover – sum price*size – суммарный объСм сдСлок Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • avgPrice – pvolume%numTrades – срСдняя Ρ†Π΅Π½Π° Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • avgSize – volume%numTrades – срСдний Ρ€Π°Π·ΠΌΠ΅Ρ€ сдСлки Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • vwap – turnover%volume – взвСшСнная ΠΏΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρƒ сдСлки срСдняя Ρ†Π΅Π½Π° Π·Π° ΠΌΠΈΠ½ΡƒΡ‚Ρƒ.
  • cumVolume – sum volume – Π½Π°ΠΊΠΎΠΏΠ»Π΅Π½Π½Ρ‹ΠΉ Ρ€Π°Π·ΠΌΠ΅Ρ€ сдСлок Π·Π° всС врСмя.

Π‘Ρ€Π°Π·Ρƒ обсудим ΠΎΠ΄ΠΈΠ½ Π½Π΅ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ – ΠΊΠ°ΠΊ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ эти ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ Π² ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ€Π°Π· ΠΈ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ ΠΌΠΈΠ½ΡƒΡ‚Ρ‹. НСкоторыС ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ Ρ‚ΠΈΠΏΠ° firstPrice ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· Π½ΡƒΠΆΠ½ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ null, ΠΈΡ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ. Π”Ρ€ΡƒΠ³ΠΈΠ΅ Ρ‚ΠΈΠΏΠ° volume Π½ΡƒΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ всСгда Π² 0. Π•Ρ‰Π΅ Π΅ΡΡ‚ΡŒ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° – Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, cumVolume Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ· ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ ΠΌΠΈΠ½ΡƒΡ‚Ρ‹, Π° для ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ Π² 0. Π—Π°Π΄Π°Π΄ΠΈΠΌ всС эти ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Ρ‚ΠΈΠΏ Π΄Π°Π½Π½Ρ‹Ρ… ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ (Π°Π½Π°Π»ΠΎΠ³ записи):

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

Π― Π΄ΠΎΠ±Π°Π²ΠΈΠ» sym ΠΈ time Π² ΡΠ»ΠΎΠ²Π°Ρ€ΡŒ для удобства, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ initWith – это готовая строчка ΠΈΠ· Ρ„ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠΉ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹, Π³Π΄Π΅ ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹Π΅ sym ΠΈ time. МоТно ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ для добавлСния Π½ΠΎΠ²Ρ‹Ρ… строк Π² Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ.

aggCols Π½Π°ΠΌ понадобится ΠΏΡ€ΠΈ создании Π°Π³Ρ€Π΅Π³ΠΈΡ€ΡƒΡŽΡ‰Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Бписок Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΈΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ·-Π·Π° особСнностСй порядка вычислСний Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π² Q (справа Π½Π°Π»Π΅Π²ΠΎ). ЦСль – ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ вычислСниС Π² Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠΈ ΠΎΡ‚ high ΠΊ cumVolume, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ зависят ΠΎΡ‚ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ….

Колонки, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½ΡƒΠΆΠ½ΠΎ ΡΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² Π½ΠΎΠ²ΡƒΡŽ ΠΌΠΈΠ½ΡƒΡ‚Ρƒ ΠΈΠ· ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ, ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° sym Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π° для удобства:

rollColumns:`sym`cumVolume;

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρ€Π°Π·Π΄Π΅Π»ΠΈΠΌ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ Π½Π° Π³Ρ€ΡƒΠΏΠΏΡ‹ согласно Ρ‚ΠΎΠΌΡƒ, ΠΊΠ°ΠΊ ΠΈΡ… слСдуСт ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ. МоТно Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ‚Ρ€ΠΈ Ρ‚ΠΈΠΏΠ°:

  1. Аккумуляторы (volume, turnover,..) – ΠΌΡ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΡ€ΠΈΠ±Π°Π²ΠΈΡ‚ΡŒ входящСС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΊ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΌΡƒ.
  2. Π‘ особой Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ (high, low, ..) – ΠΏΠ΅Ρ€Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π² ΠΌΠΈΠ½ΡƒΡ‚Π΅ бСрСтся ΠΈΠ· входящих Π΄Π°Π½Π½Ρ‹Ρ…, ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅ ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ.
  3. ΠžΡΡ‚Π°Π»ΡŒΠ½Ρ‹Π΅. ВсСгда ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ΡΡ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ.

ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ для этих классов:

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

ΠŸΠΎΡ€ΡΠ΄ΠΎΠΊ вычислСний

ΠžΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½Π½ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ Π² Π΄Π²Π° этапа. Для эффСктивности ΠΌΡ‹ сначала ΡƒΠΆΠΌΠ΅ΠΌ Π²Ρ…ΠΎΠ΄ΡΡ‰ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Ρ‚Π°ΠΊ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ‚Π°ΠΌ ΠΎΡΡ‚Π°Π»Π°ΡΡŒ ΠΎΠ΄Π½Π° строка для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ символа ΠΈ ΠΌΠΈΠ½ΡƒΡ‚Ρ‹. Π’ΠΎ, Ρ‡Ρ‚ΠΎ всС наши Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ½ΠΊΡ€Π΅ΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½Ρ‹Π΅ ΠΈ ассоциативныС, Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚ Π½Π°ΠΌ, Ρ‡Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΎΡ‚ этого Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ шага Π½Π΅ измСнится. Π£ΠΆΠ°Ρ‚ΡŒ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ ΠΌΠΎΠΆΠ½ΠΎ Π±Ρ‹Π»ΠΎ Π±Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ сСлСкта:

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

Π£ этого способа Π΅ΡΡ‚ΡŒ минус – Π½Π°Π±ΠΎΡ€ вычисляСмых ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΊ Π·Π°Π΄Π°Π½ Π·Π°Ρ€Π°Π½Π΅Π΅. К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, Π² Q сСлСкт Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ ΠΈ ΠΊΠ°ΠΊ функция, ΠΊΡƒΠ΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ динамичСски созданныС Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Ρ‹:

?[table;whereClause;byClause;selectClause]

Π― Π½Π΅ Π±ΡƒΠ΄Ρƒ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ ΠΎΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ², Π² нашСм случаС Π½Π΅Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»ΡŒΠ½Ρ‹ΠΌΠΈ Π±ΡƒΠ΄ΡƒΡ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ by ΠΈ select выраТСния ΠΈ ΠΎΠ½ΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ словарями Π²ΠΈΠ΄Π° columns!expressions. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, ΡƒΠΆΠΈΠΌΠ°ΡŽΡ‰ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ Ρ‚Π°ΠΊ:

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

Для понятности я использовал Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ parse, которая ΠΏΡ€Π΅Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ строку с Q Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ Π² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ΠΎ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ eval ΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ трСбуСтся Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠΌ сСлСктС. Π’Π°ΠΊΠΆΠ΅ ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ preprocess Π·Π°Π΄Π°Π½Π° ΠΊΠ°ΠΊ проСкция (Ρ‚.Π΅. функция с частично ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌΠΈ) Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ сСлСкт, ΠΎΠ΄ΠΈΠ½ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ (Ρ‚Π°Π±Π»ΠΈΡ†Π°) отсутствуСт. Если ΠΌΡ‹ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ preprocess ΠΊ Ρ‚Π°Π±Π»ΠΈΡ†Π΅, Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ ΡƒΠΆΠ°Ρ‚ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ.

Π’Ρ‚ΠΎΡ€ΠΎΠΉ этап – это ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ Π°Π³Ρ€Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. НапишСм сначала Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ Π² псСвдокодС:

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 вмСсто Ρ†ΠΈΠΊΠ»ΠΎΠ² принято ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ map/reduce. Но ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Q – Π²Π΅ΠΊΡ‚ΠΎΡ€Π½Ρ‹ΠΉ язык ΠΈ всС ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ спокойно ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΊΠΎ всСм символам сразу, Ρ‚ΠΎ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΏΡ€ΠΈΠ±Π»ΠΈΠΆΠ΅Π½ΠΈΠΈ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΠ±ΠΎΠΉΡ‚ΠΈΡΡŒ Π²ΠΎΠΎΠ±Ρ‰Π΅ Π±Π΅Π· Ρ†ΠΈΠΊΠ»Π°, продСлывая ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ со всСми символами сразу:

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

Но ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠΎΠΉΡ‚ΠΈ ΠΈ дальшС, Π² Q Π΅ΡΡ‚ΡŒ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΈ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΌΠΎΡ‰Π½Ρ‹ΠΉ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ – ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½Π½ΠΎΠ³ΠΎ присваивания. Он позволяСт ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π½Π°Π±ΠΎΡ€ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Π² слоТной структурС Π΄Π°Π½Π½Ρ‹Ρ… ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ список индСксов, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ΠΎΠ². Π’ нашСм случаС ΠΎΠ½ выглядит Ρ‚Π°ΠΊ:

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

К соТалСнию, для присвоСния Π² Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ Π½ΡƒΠΆΠ΅Π½ список строк, Π° Π½Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΊ, ΠΈ приходится Ρ‚Ρ€Π°Π½ΡΠΏΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρƒ (список ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΊ Π² список строк) с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ flip. Для большой Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ это Π½Π°ΠΊΠ»Π°Π΄Π½ΠΎ, поэтому вмСсто этого ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌ ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½Π½ΠΎΠ΅ присваиваниС ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ΅ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ map (которая выглядит ΠΊΠ°ΠΊ апостроф):

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

ΠœΡ‹ снова ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ ΠΏΡ€ΠΎΠ΅ΠΊΡ†ΠΈΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π’Π°ΠΊΠΆΠ΅ Π·Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅, Ρ‡Ρ‚ΠΎ Π² Q созданиС списка – это Ρ‚ΠΎΠΆΠ΅ функция ΠΈ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ Π΅Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ each(map), Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ список списков.

Π§Ρ‚ΠΎΠ±Ρ‹ Π½Π°Π±ΠΎΡ€ вычисляСмых ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΊ Π½Π΅ Π±Ρ‹Π» фиксирован, создадим Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π²Ρ‹ΡˆΠ΅ динамичСски. ΠžΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ сначала Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для вычислСния ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ row ΠΈ inp для ссылки Π½Π° Π°Π³Ρ€Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΈ Π²Ρ…ΠΎΠ΄Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅:

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

НСкоторыС ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ особыС, ΠΈΡ… ΠΏΠ΅Ρ€Π²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡ‚ΡŒΡΡ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ. ΠœΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΎΠ½ΠΎ ΠΏΠ΅Ρ€Π²ΠΎΠ΅ ΠΏΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ΅ row[`numTrades] – Ссли Π² Π½Π΅ΠΉ 0, Ρ‚ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠ΅Ρ€Π²ΠΎΠ΅. Π’ Q Π΅ΡΡ‚ΡŒ функция Π²Ρ‹Π±ΠΎΡ€Π° β€” ?[Boolean list;list1;list2] – которая Π²Ρ‹Π±ΠΈΡ€Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· списка 1 ΠΈΠ»ΠΈ 2 Π² зависимости ΠΎΡ‚ условия Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π΅:

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

Π’ΡƒΡ‚ я Π²Ρ‹Π·Π²Π°Π» ΠΎΠ±ΠΎΠ±Ρ‰Π΅Π½Π½ΠΎΠ΅ присваиваниС с ΠΌΠΎΠ΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ (Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π² Ρ„ΠΈΠ³ΡƒΡ€Π½Ρ‹Ρ… скобках). Π’ Π½Π΅Π΅ пСрСдаСтся Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚) ΠΈ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ я ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽ Π² 4-ΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π΅.

ΠžΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ аккумуляторныС ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ для Π½ΠΈΡ… функция ΠΎΠ΄Π½Π° ΠΈ Ρ‚Π° ΠΆΠ΅:

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

Π­Ρ‚ΠΎ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠ΅ ΠΏΠΎ ΠΌΠ΅Ρ€ΠΊΠ°ΠΌ Q присваиваниС, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΡ€ΠΈΡΠ²Π°ΠΈΠ²Π°ΡŽ я сразу список Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ. НаконСц, создадим Π³Π»Π°Π²Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ:

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

Π­Ρ‚ΠΈΠΌ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ я динамичСски создаю Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈΠ· строки, которая содСрТит Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ я ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΠ» Π²Ρ‹ΡˆΠ΅. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Π³Π»ΡΠ΄Π΅Ρ‚ΡŒ Ρ‚Π°ΠΊ:

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

ΠŸΠΎΡ€ΡΠ΄ΠΎΠΊ вычислСния ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΊ ΠΈΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² Q порядок вычислСния справа Π½Π°Π»Π΅Π²ΠΎ.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρƒ нас Π΅ΡΡ‚ΡŒ Π΄Π²Π΅ основныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ для вычислСний, ΠΎΡΡ‚Π°Π»ΠΎΡΡŒ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ инфраструктуры ΠΈ сСрвис Π³ΠΎΡ‚ΠΎΠ².

Π€ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹Π΅ шаги

Π£ нас Π΅ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ preprocess ΠΈ updateAgg, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄Π΅Π»Π°ΡŽΡ‚ всю Ρ€Π°Π±ΠΎΡ‚Ρƒ. Но Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΅Ρ‰Π΅ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Ρ‡Π΅Ρ€Π΅Π· ΠΌΠΈΠ½ΡƒΡ‚Ρ‹ ΠΈ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ индСксы для Π°Π³Ρ€Π΅Π³Π°Ρ†ΠΈΠΈ. Π’ ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ 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
 }

Π’Π°ΠΊΠΆΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ roll, которая Π±ΡƒΠ΄Π΅Ρ‚ ΠΌΠ΅Π½ΡΡ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰ΡƒΡŽ ΠΌΠΈΠ½ΡƒΡ‚Ρƒ:

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

Нам понадобится функция для добавлСния Π½ΠΎΠ²Ρ‹Ρ… символов:

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

И, Π½Π°ΠΊΠΎΠ½Π΅Ρ†, функция upd (Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ этой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для Q сСрвисов), которая вызываСтся ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΠΌ, для добавлСния Π΄Π°Π½Π½Ρ‹Ρ…:

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

Π’ΠΎΡ‚ ΠΈ всС. Π’ΠΎΡ‚ ΠΏΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ нашСго сСрвиса, ΠΊΠ°ΠΊ ΠΈ ΠΎΠ±Π΅Ρ‰Π°Π»ΠΎΡΡŒ, всСго нСсколько строк:

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

ВСстированиС

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ сСрвиса. Для этого запустим Π΅Π³ΠΎ Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΌ процСссС (помСститС ΠΊΠΎΠ΄ Π² Ρ„Π°ΠΉΠ» service.q) ΠΈ Π²Ρ‹Π·ΠΎΠ²ΠΈΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ init:

q service.q –p 5566

q)init[]

Π’ Π΄Ρ€ΡƒΠ³ΠΎΠΉ консоли запуститС Π²Ρ‚ΠΎΡ€ΠΎΠΉ Q процСсс ΠΈ ΠΏΠΎΠ΄ΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚Π΅ΡΡŒ ΠΊ ΠΏΠ΅Ρ€Π²ΠΎΠΌΡƒ:

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

Π‘Π½Π°Ρ‡Π°Π»Π° создадим список символов – 10000 ΡˆΡ‚ΡƒΠΊ ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для создания случайной Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹. Π’ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ консоли:

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

Π― Π΄ΠΎΠ±Π°Π²ΠΈΠ» Π² список символов Ρ‚Ρ€ΠΈ настоящих, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Ρ‹Π»ΠΎ ΡƒΠ΄ΠΎΠ±Π½Π΅Π΅ ΠΈΡΠΊΠ°Ρ‚ΡŒ ΠΈΡ… Π² Ρ‚Π°Π±Π»ΠΈΡ†Π΅. Ѐункция rnd создаСт ΡΠ»ΡƒΡ‡Π°ΠΉΠ½ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ с n строками, Π³Π΄Π΅ врСмя мСняСтся ΠΎΡ‚ t Π΄ΠΎ t+25 миллисСкунд.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΡΠ»Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π² сСрвис (Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΏΠ΅Ρ€Π²Ρ‹Π΅ Π΄Π΅ΡΡΡ‚ΡŒ часов):

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

МоТно ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π² сСрвисС, Ρ‡Ρ‚ΠΎ Ρ‚Π°Π±Π»ΠΈΡ†Π° обновилась:

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

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:

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

ΠŸΡ€ΠΎΠ²Π΅Π΄Π΅ΠΌ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ Π½Π°Π³Ρ€ΡƒΠ·ΠΎΡ‡Π½ΠΎΠ΅ тСстированиС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹ΡΡΠ½ΠΈΡ‚ΡŒ сколько Π΄Π°Π½Π½Ρ‹Ρ… сСрвис ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Π² ΠΌΠΈΠ½ΡƒΡ‚Ρƒ. Напомню, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ установили ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π» для Π°ΠΏΠ΄Π΅ΠΉΡ‚ΠΎΠ² Π² 25 миллисСкунд. БоотвСтствСнно, сСрвис Π΄ΠΎΠ»ΠΆΠ΅Π½ (Π² срСднСм) ΡƒΠΊΠ»Π°Π΄Ρ‹Π²Π°Ρ‚ΡŒΡΡ хотя Π±Ρ‹ Π² 20 миллисСкунд Π½Π° Π°ΠΏΠ΄Π΅ΠΉΡ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π΄Π°Ρ‚ΡŒ врСмя ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΌ Π·Π°ΠΏΡ€ΠΎΡΠΈΡ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅. Π’Π²Π΅Π΄ΠΈΡ‚Π΅ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ процСссС:

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 – это Π΄Π²Π΅ ΠΌΠΈΠ½ΡƒΡ‚Ρ‹. МоТно ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ сначала для 1000 строк ΠΊΠ°ΠΆΠ΄Ρ‹Π΅ 25 миллисСкунд:

start 1000

Π’ ΠΌΠΎΠ΅ΠΌ случаС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ получаСтся Π² Ρ€Π°ΠΉΠΎΠ½Π΅ ΠΏΠ°Ρ€Ρ‹ миллисСкунд Π½Π° Π°ΠΏΠ΄Π΅ΠΉΡ‚. Π’Π°ΠΊ Ρ‡Ρ‚ΠΎ я сразу ΡƒΠ²Π΅Π»ΠΈΡ‡Ρƒ количСство строк Π΄ΠΎ 10.000:

start 10000

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:

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

Π‘Π½ΠΎΠ²Π° Π½ΠΈΡ‡Π΅Π³ΠΎ особСнного, Π° вСдь это 24 ΠΌΠΈΠ»Π»ΠΈΠΎΠ½Π° строк Π² ΠΌΠΈΠ½ΡƒΡ‚Ρƒ, 400 тысяч Π² сСкунду. Π‘ΠΎΠ»ΡŒΡˆΠ΅ 25 миллисСкунд Π°ΠΏΠ΄Π΅ΠΉΡ‚ Ρ‚ΠΎΡ€ΠΌΠΎΠ·ΠΈΠ» Ρ‚ΠΎΠ»ΡŒΠΊΠΎ 5 Ρ€Π°Π·, Π²ΠΈΠ΄ΠΈΠΌΠΎ ΠΏΡ€ΠΈ смСнС ΠΌΠΈΠ½ΡƒΡ‚Ρ‹. Π£Π²Π΅Π»ΠΈΡ‡ΠΈΠΌ Π΄ΠΎ 100.000:

start 100000

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚:

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

Как Π²ΠΈΠ΄ΠΈΠΌ, сСрвис Π΅Π΄Π²Π° справляСтся, Π½ΠΎ Ρ‚Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ Π΅ΠΌΡƒ удаСтся ΡƒΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒΡΡ Π½Π° ΠΏΠ»Π°Π²Ρƒ. Π’Π°ΠΊΠΎΠΉ объСм Π΄Π°Π½Π½Ρ‹Ρ… (240 ΠΌΠΈΠ»Π»ΠΈΠΎΠ½ΠΎΠ² строк Π² ΠΌΠΈΠ½ΡƒΡ‚Ρƒ) Ρ‡Ρ€Π΅Π·Π²Ρ‹Ρ‡Π°ΠΉΠ½ΠΎ Π²Π΅Π»ΠΈΠΊ, Π² Ρ‚Π°ΠΊΠΈΡ… случаях принято Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ нСсколько ΠΊΠ»ΠΎΠ½ΠΎΠ² (ΠΈΠ»ΠΈ Π΄Π°ΠΆΠ΅ дСсятков ΠΊΠ»ΠΎΠ½ΠΎΠ²) сСрвиса, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‡Π°ΡΡ‚ΡŒ символов. Π’Π΅ΠΌ Π½Π΅ ΠΌΠ΅Π½Π΅Π΅, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²ΠΏΠ΅Ρ‡Π°Ρ‚Π»ΡΡŽΡ‰ΠΈΠΉ для ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌΠΎΠ³ΠΎ языка, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ Π² ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ Π½Π° Ρ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ….

ΠœΠΎΠΆΠ΅Ρ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ вопрос, ΠΏΠΎΡ‡Π΅ΠΌΡƒ врСмя растСт Π½Π΅Π»ΠΈΠ½Π΅ΠΉΠ½ΠΎ вмСстС с Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π°ΠΏΠ΄Π΅ΠΉΡ‚Π°. ΠŸΡ€ΠΈΡ‡ΠΈΠ½Π° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ ΡƒΠΆΠΈΠΌΠ°ΡŽΡ‰Π°Ρ функция – это фактичСски Π‘ функция, которая Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π³ΠΎΡ€Π°Π·Π΄ΠΎ эффСктивнСС updateAgg. Начиная с ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Ρ‚ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π°ΠΏΠ΄Π΅ΠΉΡ‚Π° (Π² Ρ€Π°ΠΉΠΎΠ½Π΅ 10.000), updateAgg достигаСт своСго ΠΏΠΎΡ‚ΠΎΠ»ΠΊΠ° ΠΈ дальшС Π΅Π΅ врСмя выполнСния Π½Π΅ зависит ΠΎΡ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π°ΠΏΠ΄Π΅ΠΉΡ‚Π°. ИмСнно Π·Π° счСт ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ шага Q сСрвис Π² состоянии ΠΏΠ΅Ρ€Π΅Π²Π°Ρ€ΠΈΠ²Π°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΌΡ‹ Π΄Π°Π½Π½Ρ‹Ρ…. Π­Ρ‚ΠΎ ΠΏΠΎΠ΄Ρ‡Π΅Ρ€ΠΊΠΈΠ²Π°Π΅Ρ‚, насколько Π²Π°ΠΆΠ½ΠΎ, работая с большими Π΄Π°Π½Π½Ρ‹ΠΌΠΈ, Π²Ρ‹Π±ΠΈΡ€Π°Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΉ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ. Π•Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ ΠΌΠΎΠΌΠ΅Π½Ρ‚ – ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ Ρ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… Π² памяти. Если Π±Ρ‹ Π΄Π°Π½Π½Ρ‹Π΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡΡŒ Π½Π΅ ΠΏΠΎ-ΠΊΠΎΠ»ΠΎΠ½ΠΎΡ‡Π½ΠΎ ΠΈΠ»ΠΈ Π½Π΅ Π±Ρ‹Π»ΠΈ упорядочСны ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, Ρ‚ΠΎ ΠΌΡ‹ Π±Ρ‹ познакомились с Ρ‚Π°ΠΊΠΎΠΉ Π²Π΅Ρ‰ΡŒΡŽ, ΠΊΠ°ΠΊ TLB cache miss – отсутствиС адрСса страницы памяти Π² кэшС адрСсов процСссора. Поиск адрСса Π·Π°Π½ΠΈΠΌΠ°Π΅Ρ‚ Π³Π΄Π΅-Ρ‚ΠΎ Π² 30 Ρ€Π°Π· большС Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ Π² случаС Π½Π΅ΡƒΠ΄Π°Ρ‡ΠΈ ΠΈ Π² случаС рассСянных Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π°ΠΌΠ΅Π΄Π»ΠΈΡ‚ΡŒ сСрвис Π² нСсколько Ρ€Π°Π·.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ я ΠΏΠΎΠΊΠ°Π·Π°Π», Ρ‡Ρ‚ΠΎ Π±Π°Π·Π° KDB+ ΠΈ Q ΠΏΡ€ΠΈΠ³ΠΎΠ΄Π½Ρ‹ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для хранСния Π±ΠΎΠ»ΡŒΡˆΠΈΡ… Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ простого доступа ΠΊ Π½ΠΈΠΌ Ρ‡Π΅Ρ€Π΅Π· сСлСкт, Π½ΠΎ ΠΈ для создания сСрвисов ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ способны ΠΏΠ΅Ρ€Π΅Π²Π°Ρ€ΠΈΠ²Π°Ρ‚ΡŒ сотни ΠΌΠΈΠ»Π»ΠΈΠΎΠ½ΠΎΠ² строк/Π³ΠΈΠ³Π°Π±Π°ΠΉΡ‚Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ… Π΄Π°ΠΆΠ΅ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ взятом Q процСссС. Π‘Π°ΠΌ язык Q позволяСт ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΊΡ€Π°Ρ‚ΠΊΠΎ ΠΈ эффСктивно Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹, связанныС с ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ Π΄Π°Π½Π½Ρ‹Ρ… Π·Π° счСт своСй Π²Π΅ΠΊΡ‚ΠΎΡ€Π½ΠΎΠΉ ΠΏΡ€ΠΈΡ€ΠΎΠ΄Ρ‹, встроСнного ΠΈΠ½Ρ‚Π΅Ρ€ΠΏΡ€Π΅Ρ‚Π°Ρ‚ΠΎΡ€Π° Π΄ΠΈΠ°Π»Π΅ΠΊΡ‚Π° SQL ΠΈ ΠΎΡ‡Π΅Π½ΡŒ ΡƒΠ΄Π°Ρ‡Π½ΠΎΠ³ΠΎ Π½Π°Π±ΠΎΡ€Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ.

Π― Π·Π°ΠΌΠ΅Ρ‡Ρƒ, Ρ‡Ρ‚ΠΎ ΠΈΠ·Π»ΠΎΠΆΠ΅Π½Π½ΠΎΠ΅ Π²Ρ‹ΡˆΠ΅, это лишь Ρ‡Π°ΡΡ‚ΡŒ возмоТностСй Q, Ρƒ Π½Π΅Π³ΠΎ Π΅ΡΡ‚ΡŒ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹Π΅ особСнности. НапримСр, Ρ‡Ρ€Π΅Π·Π²Ρ‹Ρ‡Π°ΠΉΠ½ΠΎ простой IPC ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ стираСт Π³Ρ€Π°Π½ΠΈΡ†Ρƒ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌΠΈ Q процСссами ΠΈ позволяСт ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡ‚ΡŒ сотни этих процСссов Π² Π΅Π΄ΠΈΠ½ΡƒΡŽ ΡΠ΅Ρ‚ΡŒ, которая ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°ΡΠΏΠΎΠ»Π°Π³Π°Ρ‚ΡŒΡΡ Π½Π° дСсятках сСрвСров Π² Ρ€Π°Π·Π½Ρ‹Ρ… ΠΊΠΎΠ½Ρ†Π°Ρ… свСта.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ