// treetable \p 0 / k4: ?/![t;c;b;a] select:{[t;c;b;a]t:col[t;`i_];cols[:[#c;rows[t]{x@&eval[rows[y]x]z}/[_n;t;c];t];b,();!a;a[];#b;#!a::[4=__abs 4:a;.+(a;a,:());a]]} update:{[t;c;b;a]u:@[select[u;c;b]@[.+2#,!u:col[t;`i_];!a;:;a[]];_n;,/];.[col/[.[t;(f;u`i_);:;u f:!t];g];(g;u`i_);:;u g:(!u)_dvl`i_,!t]} delete:{[t;c;b;a]:[#c;rows[t]i _dvl(i:!*|^t[]){x@&eval[rows[y]x]z}/[_n;t;c];#a;@[_n;f;:;t f:(!t)_dvl(),a];t]} col:{[t;f]@[t;f;:;!*|^t[]]} rows:{[t;i]@[t;_n;@[;i]]} cols:{[t;b;a;e;j;k]:[~j|k;t;@[_n;b,a;:;:[j;:[#*u:t b;+?+u;u],:[k;{{eval[rows[x]z]y}[x;z]'y}[t;=+t b]'e;()];eval[t]'e]]]} / evaluate parse-tree eval:{[t;e]:[4=4:e;t e;(1<#e)&(4:*e)_in 4 7;e[0]._f[t]'1_ e;((1=#e)&(4:**e)_in 4 7)*:/e]} / left-join lj:{[t;u;k]@[t;f;:;u[f:(!u)_dvl k,();:[1=#k;(j:?u@*k)?/:t@*k;(?i)?/:i:(#:'j)_sv(j:?:'u k)?/:'t k]]]} / k4 xcols:{[c;d].+(c,k;d c,k:(!d)_dvl c,:())} xcol:{[c;d].+(c;d c)} xasc:{@[y;_n;@[;0]} e:{[v].[v;(.;`e);:;0]} O:.+(`a`d`A`D;(<:;>:;abs@));O..l:("<";">";"<@";">@";"") l:{[v].[.[v;(.;`l);:;{(O..l((!O),_n)?S var x),$x}'!v];(~`o_`n_;`l);:;(" + -";"Hierarchy->")]} k:{[v].[v;(.;`k);:;(".k.ko`";".k.kn`"),(-2+#!v)#,".k.ks`"]} kn:{if[00)*(1+y)*~z}[i]. Z[`o_`e_;i:*_i]} zz:{Z::construct[T;G;P;A]S} / reset path, sorting reset:{P::.+(`n`v;(,.+(0#`;0#`);,1));S::.()} / path: open/close at a node at:{[b;p;g;n]:[((~L)&(#g)=#n);p;(#p`n)>i:p[`n]?a:.+((#n)#g;n,());.[p;(`v;i);:;b];@[p;_n;,;(a;b)]]} / path: open to group (h=` -> open to leaves) to:{[t;g;h].+(`n`v;(m;&0,#m:?n,,/fan[t;n:,.+(0#`;0#`)]'(1+!#k)#\:k:(g?h)#g))} fan:{y,z{.+(x;y)}/:+x z} / path: find G-valid paths in P valid:{[p;g]@[p;_n;@[;&(!#g){y~(#y)#x}/:g?/:/:!:'p`n]]} / basic rollup functions, list -> atom count:#: sum:+/ avg:{:[0=n:#x;0.;(+/x)%n]} last:*|: first:*: wavg:{:[0=n:+/x;0.;(+/x*y)%n]} / parameters G:0#` / group by P:.+(`n`v;(,.+(0#`;0#`);,1)) / initial state, or e.g. to autoexpand to trader: P:to[T;G]`trader S:.() / sort (column dictionary of `a`d`A`D) C:() / column view (all if ()) F:.() / formats L:0 / show leaves? BG:808080 -1;FG:0 600001 61 5001 / color scheme, e.g. BG:0 0;FG:-1 990001 999901 9901 H:"treetable" / heading label-depenency X:0 / execute every X seconds / run treetable run:{tt X*.01;zz`;V..d::"view[G;A]Z";V..l..d::H;`show$`V;.t..t:".k.tt ",($X*.0001),";.k.zz`";."\\t ",$X} \ / example stocks:.+("SSFSS";,"\t")0:"pnl/stocks.txt" traders:.+("SS";,"\t")0:"pnl/traders.txt" strategies:`statarb`pairs`mergerarb`chart`other`distressed`arbitrage groups:{y,,x(1+()_draw n)_draw-n:#x} traders:ungroup@.+((!traders),`strategy;+groups[strategies]'+traders[]) traders:ungroup@.+((!traders),`symbol;+groups[stocks`symbol]'+traders[]) traders:xcols[`id`unit`trader`strategy`symbol]@[traders;`id;:;!(^traders[])1] trades:.+(`id`symbol`date`time`price`qty;6#,()) trade:{[st;tr;per;d;t] j:&(!c)_lin(m:__floor per*c)_draw-c:(^tr[])1;i:tr[`id;j];s:tr[`symbol;j] p+:-1 0 1[m _draw 3]*(.001*m _draw 0)*p:(.+st`symbol`oprice)s q:-1 1.[m _draw 2]*100*1+m _draw 10 r:.+(`id`symbol`date`time`price`qty;++(i;s;d;t;p;q)) e:.+(`symbol`date`time`price`qty;(,`HEDGE;(first;`date);(first;`time);5.;(-:;(sum;(%;(*;`price;`qty);(*;5.;.9995)))))) join[r]select[r;();`id;e]} calc:{[stocks;traders;per;time] trades::join[trades]trade[stocks;traders;per;*_gtime time]time t:select[trades;();`id`symbol;.+(`trades`qty`cprice`vwap`i_;((count;`id);(sum;`qty);(last;`price);(wavg;`qty;`price);!(^trades[])1))] u:update[t;();();.+(`real`unreal;((*;`qty;`vwap);(*;`qty;`cprice)))] update[lj[lj[u;traders]`id;stocks]`symbol;();();.+(`pnl;,(+;`real;`unreal))]} tt:{T::calc[stocks;traders;x]_t} / parameters G:`strategy`unit`trader`symbol / group by P:.+(`n`v;(,.+(0#`;0#`);,1)) / initial state, or e.g. to autoexpand to trader: P:to[T;G]`trader S:.() / sort (column dictionary of `a`d`A`D) C:() / column view (all if ()) F:.+(`n_`count`qty`volume`trades`pnl;(-20$;8$;8.0$;11.0$;8$;12.2$)) / formats L:0 / show leaves? BG:808080 -1;FG:0 600001 61 5001 / color scheme, e.g. BG:0 0;FG:-1 990001 999901 9901 H:"\"#trades = \",$(^.k.trades[])1" / heading label-dependency X:5 / execute every X seconds / rollups are parse-trees A.count:(count;`qty) A.qty:(sum;`qty) A.volume:(sum;(_abs;`qty)) A.trades:(sum;`trades) A.pnl:(sum;`pnl) A.real:(sum;`real) A.unreal:(sum;`unreal) A.oprice:(avg;`oprice) A.cprice:(avg;`cprice) A.vwap:(avg;`vwap) run` \ click in *o_ to reset click in 1_o_ to open/close at a node click in n_ to drill to the level of that cell click in any other column to sort: asc, desc, asc abs, desc abs, none / static example T:.+("ISSSSFFFFFFSFSSF";,"\t")0:"pnl/pnl.txt";_n;{:[-2=4:x;@[x;&x=0n;:;0];x]}]