Skip to content

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;`;()!())