Code Examples and Templates
Overview
Having access to code examples and templates can accelerate the development process and ensure that your UDAs adhere to best practices. This section provides a collection of examples and templates to help you get started.
Code Examples
// Custom UDA code.
.kxi.packages.file.load"common.q" / Example loading other file dependancies
\d .customUDA
// Example 1 - Custom count by UDA.
// Define query function.
//
// @desc Define a new API. Counts number of entries by specified columns.
// @param table {symbol} Table name.
// @param byCols {symbol|symbol[]} Column(s) to count by.
// @param startTS {timestamp} Start time (inclusive).
// @param endTS {timestamp} End time (exclusive).
// @return {table} Count by specified columns.
countByQuery:{[table;startTS;endTS;byCols]
byCols,:();
bc:$[`date in byCols;
[byCols:(byCols except`date),`realTime;
(x,`date)!(x:-1_byCols),enlist($;"d";`realTime)];
{x!x}byCols];
t:.kxi.selectTable`table`startTS`endTS`filter!(table;startTS;endTS;enlist(within;`realTime;(startTS;endTS)));
?[t;();bc;enlist[`cnt]!enlist(count;`i)]
}
// Define aggregation function.
//
// @desc Agg function that does a plus join on a list of tables.
// @param tbls {table[]} List plus-joinable tables.
// @return {table} Plus join.
countByAgg:{[tbls]
.kxi.response.ok(pj/)0^((union/)key each tbls)#/:tbls
}
\d .
// Define metadata.
metadata:.kxi.metaDescription["Custom UDA - does a count by."],
.kxi.metaMisc[enlist[`safe]!enlist 1b],
.kxi.metaParam[`name`type`isReq`description!(`table;-11h;1b;"Table name.")],
.kxi.metaParam[`name`type`isReq`description!(`byCols;11 -11h;1b;"Column(s) to count by.")],
.kxi.metaParam[`name`type`isReq`description!(`startTS;-12h;1b;"Start time (inclusive).")],
.kxi.metaParam[`name`type`isReq`description!(`endTS;-12h;1b;"End time (exclusive).")],
.kxi.metaReturn`type`description!(98h;"Count by specified columns.");
// Registration.
.kxi.registerUDA `name`query`aggregation`metadata!(`.customUDA.countBy;`.customUDA.countByQuery;`.customUDA.countByAgg;metadata);
// Example qIPC requests.
// GATEWAY variable below is defined as an IPC connection to the Service Gateway.
// args:`table`startTS`endTS`byCols!(`trade;"p"$.z.D-3;"p".z.D-2;`date`sym)
// show each GATEWAY(`.customUDA.countBy;args;`;()!())
\d .customUDA
// Example 2 - Join Trade and Quote tables
// Define query function.
//
// @desc Define a new API. Get trade data for specified date range.
// @param startTS {timestamp} Start time (inclusive).
// @param endTS {timestamp} End time (exclusive).
// @param s {symbol|symbol[]} Market data symbols to query for.
// @return {table} Count by specified columns.
queryMktData:{[startTS;endTS;syms]
if[`~syms;
:.kxi.response.error[.kxi.response.ac.INPUT;"Must enter a non null symbol(s) to query";()]];
symFilt:(in;`sym;enlist syms);
filter:((within;`realTime;(startTS;endTS));symFilt);
t:.kxi.selectTable`table`startTS`endTS`filter!(`trade;startTS;endTS;filter);
.kxi.response.ok t
}
// Define aggregation function.
//
// @desc Get symbol and timerange for quote data, then defer the final result until we retrieve the quote data.
// @param trade {table} Trade data from the query result.
aggMktData:{[trade]
trade:raze trade; / Raze as data coming from multiple DAPs
.kxi.context.set[`trade;trade]; / Save trade data in context
symFilt:exec distinct sym from trade;
args:`table`startTS`endTS`agg`sortCols!
(`quote;"p"$"d"$min trade`realTime;1+max trade`realTime;
`sym`realTime`ask`askSize`bid`bidSize;`sym`realTime); / Args for quote getData
.kxi.response.callAPI[`.kxi.getData;args;`.customUDA.aggMktDataResume;()!()]
}
// Aggregation defer resume.
// @desc Resume deferred request and join together trade and quote data.
// @param quote {table} Quote data.
// @return Joined trade and quote data for specified syms with numeric values rounded to 2 decimal places.
aggMktDataResume:{[quote]
trade:.kxi.context.get`trade; / Recover trade data from context
res:aj[`sym`realTime;trade;quote]; / Join
round:{("j"$100*x)%100}; / Round to two decimals
.kxi.response.ok update round price,round bid,round ask from res
}
\d .
// Define metadata.
metadata:.kxi.metaDescription["Custom UDA - join trade and quote data."],
.kxi.metaMisc[enlist[`safe]!enlist 1b],
.kxi.metaParam[`name`type`isReq`description!(`startTS;-12h;1b;"Start time (inclusive).")],
.kxi.metaParam[`name`type`isReq`description!(`endTS;-12h;1b;"End time (exclusive).")],
.kxi.metaParam[`name`type`isReq`description!(`syms;11 -11h;1b;"Sym values to query on. Must be a non-null value.")],
.kxi.metaReturn`type`description!(98h;"Joined trade and quote data.");
// Registration.
.kxi.registerUDA `name`query`aggregation`metadata!(`.customUDA.getMktData;`.customUDA.queryMktData;`.customUDA.aggMktData;metadata);
// Example qIPC requests.
// GATEWAY variable below is defined as an IPC connection to the Service Gateway.
// args:`startTS`endTS`syms!("p"$.z.D-3;"p".z.D-2;`DNDF.CAN)
// show each GATEWAY(`.customUDA.getMktData;args;`;()!())