\d .sim / generate simulated security paths / (s)igma, (r)ate, (t)ime path:{[s;r;t] z:.stat.norminv count[t]?1f; p:prds .stat.gbm[s;r;deltas[first t;t]] z; p} / generate price path / security (id), (S)pot, (s)igma, (r)ate, (d)ate/(t)i(m)e genp:{[id;S;s;r;dtm] t:abs type dtm; tm:("np" t in 12 14 15h)$dtm; p:S*path[s;r;tm%365D06]; c:`id,`time`date[t=14h],`price; p:flip c!(id;dtm;p); p} / round price to nearest tick (up and down) tickrnd:{if[99h=type x;x@:y];(y;x+y:x*floor y%x)} / randomly delay a timeseries delay:{abs[type x]$x+next deltas[x]*count[x]?1f} / randomly throw away elements of list filter:{y asc (neg"j"$x*n)?n:count y} / generate bid/ask quotes / (t)ick (s)ize, (q)uote (s)ize, (p)rice path genq:{[ts;qs;p] q:p,'flip `bp`ap!tickrnd[ts] p `price; q:q,'flip `bs`as!1+count[p]?/:2#qs; q:`id`time`bs`bp`ap`as#q; q} / generate trade event / (b)id/ask flag, pct:percent fills / (b)id (s)ize, (b)id (p)rice, (a)sk (p)rice, (a)sk (s)izie trd:{[b;pct;bs;bp;ap;as](ceiling pct*?[b;bs;as];?[b;bp;ap])} / generate trade event / (q)uote table and (pct) fill rate gent:{[pct;q] q:filter[pct] raze (-1_@[;`time;delay] q@) each group q `id; t:q,' flip `ts`tp!trd[n?0b;(n:count q)?1f] . q `bs`bp`ap`as; t:`id`time`ts`tp#t; t}