Keywords

all

Everything is true

min$["b"]

This takes advantage of the fact that any value can be cast to a boolean and return 0b if the value is 0 and 1b otherwise.

In this case, the input is cast to a boolean, and the minimum boolean value is taken from the result.

As such, if there are any values which are 0 in the input, those will return 0b when cast to boolean, and will be the minimum boolean value, hence the result would be 0b.

q)list:1 2 3 0 -1


q)"b"$list

11101b


q)min "b"$list

0b


q)all[list]~min "b"$list

1b

any

Something is true

max$["b"]

This works exactly the same as 'all' but uses 'max' instead of 'min' to show if any of the boolean values are true.

asc

Ascending sort

Sort and grade: ascending

k){$[99h=@x;(!x)[i]!`s#r i:<r:. x;`s=-2!x;x;0h>@x;'`rank;`s#x@<x]}


{

$[99h=type x;

   (key x)[i]!`s#r i: iasc r:value x;

   `s=attr x;

      x;

      0h>type x;

         '`rank;

         `s# x iasc x

]

 }

avgs

Running averages

k){(+\x)%+\~^x}


(sums x) % sums not null x

This is smart and simple. Take the running sum of x, and divide it by the running count of non-null items in x.

ceiling

Round up

-_-:


neg floor neg x

Apply the in-build kdb 'floor' function '_' on the negative of x, which will round it 'up' closer to 0. Apply neg again to get back to original sign.

cols

Column names of a table

{$[.Q.qp x:.Q.v x;.Q.pf,!+x;98h=@x;!+x;11h=@!x;!x;!+0!x]}


{

   $[.Q.qp x:.Q.v x;

      .Q.pf,!+x;

      98h= type x;

         key flip x;

         11h=type key x;

            key x;

            key flip 0!x

   ]

 }

cross

Cross-product

k){n:#m:&(#x)##y;$[99h=@x;((!x)[m],'n#!y)!(. x)[m],'n#. y;((),x)[m],'n#y]}


{

   n:count m:where (count x) # count y;

   $[99h= type x;

      (key[x][m],'n#key[y])!(value x)[m],'n#value y;

      ((),x)[m],'n#y

   ]

 }

cut

Cut a list or table into sub-arrays / cut a list or table into a matrix of x columns

k){$[0h>@x;x*!-_-(#y)%x;x]_y}


{

   $[0h>type x;

      x* til ceiling (count y)%x;

      x

   ]_ y

 }

desc

Sort and grade: descending

k){$[99h=@x;(!x)[i]!r i:>r:. x;0h>@x;'`rank;x@>x]}


{

   $[99h=type x;

      (key x)[i] ! r i: idesc r:value x;

      0h>type x;

         '`rank;

         x idesc x

   ]

 }

differ

Find where list items change value

$["b"]~~':


"b"$not (~) prior x

Using the each prior iterator, check if each item in the list matches the previous item in the list. Inverse this to return 'true' where each item in the list does NOT match the previous item. 

Note: not sure why there needs to be a cast here.

dsave

Write global tables to disk as splayed, enumerated, indexed kdb+ tables.

k){.[*x;1_x,y,`;:;@[;*!+a;`p#].Q.en[*x]a:. y];y}/:


{

   .[first x; 1_x,y,`; :;


 @[;*!+a;`p#].Q.en[first x]a:value y

     ];

    y

 }/:


ema

Exponential moving average

k){(*y)(1f-x)\x*y}


(first y) (1f-x)\x*y

To better understand this we must understand the formula for the exponential moving average (EMA):

EMA = Closing price * multiplier + EMA (previous day) * (1-multiplier)

So let's break it down, with the following inputs, x:2, y:2 2 3 1

except

Exclude items from a list

k){x@&~x in y}


x where not x in y

Self-explanatory.

fkeys

Foreign-key columns of a table

k){(&~^x)#x:.Q.fk'.Q.V x}


(where not null x)#x:.Q.fk each .Q.V x

gtime

Convert timestamp to UTC.

k){t+x-%t:x+x-%x}


diff:(.z.P-.z.p);

t + x - diff + t: x + x - diff + x

This makes use of the (apparently undocumented) override of '%' in k (see ltime),  which adds the difference between the shell timezone and UTC to the input.

This has been represented above by subtracting .z.P and .z.p.

hsym

Symbol/s to file or process symbol/s

$["s"]!'[-1]


"s"$-1!'x

Basically this just making use of the -1! internal function.

iasc and idesc 

Ascending grade  / descending grade

k){$[0h>@x;'`rank;<x]}

k){$[0h>@x;'`rank;>x]}

Return a rank error if x is an atom. Otherwise, use the k ascend/descend operator.

inter

Intersection of two lists or dictionaries

k){x@&x in y}


x where x in y

Self-explanatory.

keys

Key column/s of a table

{$[98h=@x:.Q.v x;0#`;!+!x]}


{

   $[98h=type x:.Q.v x;

      0#`;

      key flip key x

   ]

}

load

Load binary data from a file

k){$[1=#p:`\:*|`\:x:-1!x;set[*p;. x];set[*p].h.xt[p 1]@0:x]}'


{

   $[1=count p:` vs first reverse ` vs x:hsym x;

      set[first p; get x];

      set[first p; .h.xt[p 1; read0 x]

} each x

According to code.kx, input can be one of: a symbol of a file in the current dir (with no file extension), a filehandle (with no file extension) or a directory. 

The 'false' statement in this code is only valid when the input is a json file with a '.json' filepath. I am unable to see this documented on the main code.kx website. 

For each input apply the following logic:

lower

Shift case

k){$[$[(~@x)&10h~@*x;&/10h=@:'x;0b];_x;~t&(77h>t)|99h<t:abs@@x;.z.s'x;19h<t;.z.s@. x;~t in 10 11h;'`type;_x]}


{

   isMixedListOfStrings:$[(not type x)&10h~type first x;

      min 10h= type each x;

      0b

   ];


   $[isMixedListOfStrings;

      _x;

      not t&(77h>t)|99h<t:abs type x;

         .z.s each x;

         19h<t;

            .z.s get x;

            ~t in 10 11h;

               '`type;

             _x

   ]

 }

ltime

Convert UTC timestamp to local time.

%:


x + (.z.P - .z.p)

This uses the k verb '%' which does not appear to be well documented. Essentially it uses the shell timezone setting e.g. 

(UTC-05:00) Eastern Time (US & Canada)

Eastern Standard Time

And basically performs the calculation from there (in this example it would subtract 5 hours from the timestamp)

ltrim

Remove leading nulls from a list

k){$[~t&(77h>t)|99h<t:@x;.z.s'x;^*x;((^x)?0b)_x;x]}


{

   $[not t&(77h>t)|99h<t:type x;

      .z.s each x;

      null first x;

         ((null x)?0b)_x;

         x

   ]

 }

mavg

Moving averages

k){msum[x;0.0^y]%mcount[x;y]}


{

   msum[x;0.0^y]%mcount[x;y]

 }

This is dividing the running sum with the running count over the same values, producing a moving average.

mcount

Moving counts

k){msum[x;~^y]}


{

msum[x;not null y]

 }

Easy - take a boolean list where y is not null and simply run an msum against it.

mdev

Moving deviations

k){sqrt mavg[x;y*y]-m*m:mavg[x;y:"f"$y]}


{

   sqrt mavg[x;y*y] - m*m:mavg[x;y:"f"$y]]

 }

med

Median

k){avg x(<x)@_.5*-1 0+#x,:()}


{

   if[1=count x; x:enlist x];

   avg x (iasc x) floor .5*-1 0+count x

 }

meta

Metadata for a table

{([!c].Q.ty't;f:.Q.fk't;a:-2!'t:. c:.Q.V x)}


{

   a:attr each t:value c:.Q.V x;

   f:.Q.fk each t;

   ([key c] .Q.ty each t; f; a)

 }

Create a table with:

mins

Minimums

&\


(&) scan x

This is utilising the 'lesser' operator with the 'scan' iterator to take each item in the list, compare it with the next one, and return the lesser of the two. Repeat until the entire list has been traversed. 

mmin and mmax

Moving minimums / moving maximums

k){(x-1)&':/y} 

k){(x-1)|':/y}


(&':)/[3;4 2 3 4 0 4 3 2 2 10 9 0 9 3]


or, for easier understanding:


do[x-1; y:(&) prior y]; y

To understand these you must first understand the 'do' iterator and the each-prior (':) iterator.

This performs the same action x-1 times: traverse the list and compare the value of the current item with the item before it (min or max), replace the current value with the previous value if it is indeed greater or less than the current value.

By repeating this x-1 times, the result is essentially an x-1 moving min/max. 

mmu

Matrix multiply, dot product

$

There isn't much to explain here! If you are not familiar with matrix multiplication, best to brush up on it.

mod

Modulus

k){x-y*x div y}


{x-y*x div y}

This is simple maths - find the number of times y goes into x, multiply that by y to get the full amount and then take that from x to return the remainder.

msum

Moving sums

k){$[99h=@y;(!y)!.z.s[x;. y];y-(-x)_(0i*x#y),y:+\y]}


{

$[99h=type y;

   (key y)!.z.s[x;value y];

   y- neg[x]_(0i*x#y),y: sums y

]

 }

Essentially, there will be no difference between 'msum' and 'sums' for the first x numbers, which is why that is the number of zeroes added to the front - deducting 0 from the running sum just returns the running sum so far. For the next numbers, they are essentially the 'updated' running sum i.e. starting from the first non-zero, deducted from the total running sum.

next

Next item/s in a list

k){$[0h>@x;'`rank;1_x,,x 0N]}


{

  $[0h > type x;

    '`rank;

    1_x,,x 0N

  ]

 }

If is not a list, return a type error. Else:

Return the same list but with the first value removed and a null value added.

parse

Parse a string

k){$["\\"=*x;(system;1_x);-5!x]}


{

  $["\\" = first x;

    (system;1_x);

    -5!x

  ]

 }

This is basically a wrapper for the -5! internal function.

There is one check if the string represents a system command (with two backslashes as the first would be an escape character). In this case the parse returns a parsed system command.

rand

Pick randomly

k){*1?x}


first 1?x

Uses the 'roll' overload of the question mark character. Just using a 1?x returns a one item list, so 'first' ensures it is an atom.

rank

Position in the sorted list

k){$[0h>@x;'`rank;<<x]}


{

  $[0h > type x;

    '`rank;

    iasc iasc x

  ]

 }

Fail with a rank error if not a list. Otherwise:

Perform iasc once to get the positions of where each item in the list should be if sorted, then perform it again to show at each position, which item in the list should be there. 

rload

Load a splayed table from a directory

k){x:-1!x;.[*|`\:x;();:;.     x]}'


{

  x: hsym x;

  .[first reverse ` vs x; (); :; get x]

 } each x

For each input (splayed table):

Still trying to figure out what all the whitespace is for... 

rotate

Shift the items of a list to the left or right

k){$[0h>@y;'`rank;98h<@y;'`type;#y;,/|(0;mod[x;#y])_y;y]}


{

  $[0h > type y;

    '`rank;

    98h < type y;

      '`type;

      count y;

        ,/|(0;mod[x;count y])_y;

        y

  ]

 }

rsave

Write a table splayed to a directory

k){x:-1!x;.[`/:x,`;();:;.*|`\:x]}'


{

  x:hsym x;

  .[` sv x,`; (); :; get first reverse ` vs x]

 } each x

This is essentially getting the table named x and setting it down (using dot amend) with filename 'x' in the current directory.

rtrim

Remove trailing nulls from a list

k){$[~t&(77h>t)|99h<t:@x;.z.s'x;^last x;(-(|^x)?0b)_x;x]}


{

  $[not t&(77h>t)|99h<t:type x;

    .z.s each x;

    null last x;

      (-(reverse null x)?0b)_x;

      x

  ]

 }

save

Write a global variable to file

k){$[1=#p:`\:*|`\:x:-1!x;set[x;. *p];   x 0:.h.tx[p 1]@.*p]}'


{

  $[1=count p:` vs first reverse ` vs x:hsym x;

    set[x; get first p];

    x 0: .h.tx[p 1; get first p]

  ]

 } each x

According to code.kx, input can be one of: a symbol of a file in the current dir (with no file extension), a filehandle (with no file extension) or a directory. 

The 'false' statement in this code is only valid when the input is a json file with a '.json' filepath. I am unable to see this documented on the main code.kx website. 

For each input apply the following logic:

scov

Sample covariance

k){(n*cov[x;y])%-1+n:(#x)-+/^x+y}


{

  (n*cov[x;y])%-1+n:(#x)-+/^x+y

 }

sdev

Standard deviation

k){sqrt svar x}


{

  sqrt svar x

 }

This is simply getting the square root of the sample variance of x.

set

Assign a value to a global variable / persist an object as a file or directory

k){$[@x;.[x;();:;y];-19!((,y),x)]}


{

  $[type x;

    .[x;();:;y];

    -19!((,y),x)

  ]

 }

show

Format and display at the console.

k){1 .Q.s x;}


{

  1 .Q.s x;

 }

Writes the output of .Q.s[x] to the stdout file handle. As the file handle is returned when that query is successful, there is a deliberate semi-colon added to prevent any return value. 

signum

Sign function

k){(x>0)-x<0}


{

  (x>0)-x<0

 }

Two boolen lists are created: one showing where x is greater than 0 and one showing where x is less than 0.

When these lists are subtracted, positive numbers return 1, negative numbers return -1 and 0 returns 0.

ssr

Search string replace

k){,/@[x;1+2*!_.5*#x:(0,/(0,{n:x?"[";$[n=#x;n;n+.z.s$[(#x)=p:x?"]";'"unmatched ]";p]_x:(n+2+"^"=x n+1)_x]}y,"")+/:x ss y)_x;$[100h>@z;:[;z];z]]}


numberOfChars:{

  n:x?"[";

  $[n=count x;

    n;

    [

      x:(n+2+"^"=x n+1)_x;

      n+.z.s $[(count x)=p:x?"]";  '"unmatched ]"; p] _x

    ]

 }


y:y,"";

ind:(0,numberOfChars y);

ind:(0,/(ind)+/:x ss y)_x;

ind:1+2*til floor .5 * count ind;

raze @[x; ind; $[100h > type z; :[;z]; z]]

This one is quite long so has been slightly re-organised to (hopefully) make it clearer.

sublist

Select a sublist of a list

k){$[99h=@y;sublist[x;!y]!sublist[x;. y];~0h>@x;$[.Q.qp y;.Q.ind[y];y]i+!"j"$0|x[1]&(#y)-i:*x;abs[x]<#y;x#y;y]}


{

  $[99h=type y;

    sublist[x;key y]!sublist[x;value y];

    not 0h>type x;

      $[.Q.qp y;

        .Q.ind[y];

        y

      ]i+til "j"$0|x[1]&(count y)-i:first x;

      abs[x]<count y;

        x#y;

        y

   ]

 }

sv

Scalar from vector

k){x/:y}

svar

Sample variance

k){(n*var x)%-1+n:(#x)-+/^x}


{

  (n*var x)%-1+n:(count x)-sum null x

}

system

Execute a system command

.,["\\"]


value "\\", x

tables

List of tables in a namespace

k){."\\a ",$$[^x;`;x]}


{

  system "a ", string $[null x;`;x]

 }

This is basically running \a x

til

First x natural numbers

k){$[0>@x;!x;'`type]}


{

  $[0> type x;

    (!)x;

    '`type

  ]

 }

This just makes use of the ! operator in k which is essentially 'til'

trim

Remove leading and trailing nulls from a list

k){ltrim rtrim x}


{

  ltrim rtrim x

 }

See the sections on ltrim and rtrim.

ungroup

Ungroup

k){$[#x:0!x;,/+:'x;x]}


{

  $[count x:0!x;

    raze flip each x;

    x

  ]

 }

This takes advantage of the following behaviour in 'flip':

If an atom(s) are provided, they are extended to match the length of the list(s).

upper

Shift case

k){$[$[(~@x)&10h~@*x;&/10h=@:'x;0b];.Q.Aa x;~t&(77h>t)|99h<t:abs@@x;.z.s'x;19h<t;.z.s@. x;~t in 10 11h;'`type;$[11h=t;`$.Q.Aa@$x;.Q.Aa x]]}


{

  isListOfStrings:$[(not type x)&10h~type first x;min 10h=type each ;0b];

  $[isListOfStrings;

    .Q.Aa x;

    not t and (77h>t) or 99h<t:abs type x;

      .z.s each x;

      19h<t;

        .z.s value x;

        not t in 10 11h;

          '`type;

          $[11h=t;`$.Q.Aa string x;.Q.Aa x]

  ]

 }

upsert

Overwrite or append records to a table

.[;();,;]

This uses the general form of apply to add the new records to the table using the ',' binary operator. This also gives the intended behaviour for keyed tables as joining a dictionary to a dictionary with the same key will overwrite the value in that key:

q)(`a`b!1 2),`b`c!10 20

a| 1

b| 10

c| 20

view

Expression defining a view

k){$`. .`\:x}


{

  string `.[` vs x]

 }

A view will exist in the root namespace i.e. `. 

'view' retrieves it from the root namespace.

views

List views defined in the default namespace

k){."\\b ",$$[^x;`;x]}


{

  system "b ",string $[null x;`;x]

 }

This is using the system "b" command which lists views in the provided namespace

Note this function implies that you can define views in the non-default namespace - please see this stackoverflow answer by Igor Korkhov for more details.

vs

Vector from scalar

k){x\:y}

ww

k){[a;w;f;y;z]f,:();e:1_z;z:*z;y,'n#+(:/'f)!+{[e;d;a;b]e .'d@\:\:a+!b-a}[*:'e;z f:1_'e]/'$[n:#*w;+$[#g;(g#z)?g#y;0]|/:a+$[#g:-1_f;(f#z)bin@[f#y;*|f;:;]@;z[*f]bin]'w;,0 0]}

This is not documented.

xasc

Sort a table in ascending order of specified columns.

k){$[$[#x;~`s=-2!(0!.Q.v y)x;0];.Q.ft[@[;*x;`s#]].Q.ord[<:;x]y;y]}


{

  notEmptyOrAlreadySorted:$[count x; not `s=attr (0!.Q.v y)x;0];

  $[notEmptyOrAlreadySorted;

    .Q.ft[ @[;first x;`s#]; .Q.ord[iasc;x;y]];

    y

  ]

 }

xbar

Round down

k){x*y div x:$[16h=abs[@x];"j"$x;x]}


{

  x:$[16h=abs[type x]; "j"$x; x];

  x*y div x;

 }

Perform 'y div x' to find out how many times x goes into each y, multiply this by 'x' again (similar to rounding down to the nearest whole x).

I am not sure why timespan gets special treatment here over the other temporal types.

xcol

Rename table columns

k){.Q.ft[{+$[99h=@x;@[!y;(!y)?!x;:;. x];x,(#x)_!y]!. y:+y}x]y}


{

  renameColsFunc:{

    flip $[99h=type x; @[key y; (key y)?key x; :; value x]; x,(count x)_key y]!value y:flip y

  }[x;];

  .Q.ft[renameColsfunc;y]

 }

For the function that performs the column renames:

xcols

Reorder table columns

k){(x,f@&~(f:cols y)in x)#y}


{

  (x,f where not (f:cols y)in x)#y

 }

Take columns from table y starting with those specificed in list 'x' and followed by any leftover in their original order.

xdesc

Sorts a table in descending order of specified columns. 

k){$[#x;.Q.ord[>:;x]y;y]}


{

  $[count x; .Q.ord[idesc; x; y]; y]

 }

Use .Q.ord to sort table y descending by column x.

xgroup

Groups a table by values in selected columns

k){x,:();a:x#y:0!y;$[#x_:y;+:'x@=a;a!+f!(#f:!+x)#()]}


{

  x,:();

  a:x#y:0!y;

  $[count x:x _ y;

    flip each x group a;

    a! flip f!(count f:key flip x)#()

  ]

 }

xkey

Set specified columns as primary keys of a table

k){(#x)!.[0!y;();xcols x]}


{

  (count x)! .[0!y; (); xcols[x;] ]

 }

Re-order the columns of 'y' so those of 'x' are at the start. Key the table on that number of columns.

xlog

Logarithm

k){log[y]%log x}


{

  log[y]%log x

 }

Self-explanatory.

xprev

Nearby items in a list

k){$[0h>@y;'`rank;y(!#y)-x]}


{

  $[0h>type y;

    '`rank;

    y(til count y)-x

  ]

 }

Make a list of '(y index)-x' and return the values of 'y' at those indices. 

xrank

Group by value

k){$[0h>@y;'`rank;_y*x%#y:<<y]}


{

  $[0h>type y;

    '`rank;

    floor y* x%count y:iasc iasc y

  ]

 }

If y is a list: