Search code examples
kdb+

vectorizing function calls for use with update


expryDt:{[ed] (2_string ed) except "."};

// generate a formatted ticker name for an option
symbol:{[tkr;expiryDate;typ;strike]
    if[not typ in `CALL`PUT`CE`PE; show "typ is not correct. it must be either CALL or PUT or CE or PE"; exit 1];
    r: $[(typ=`CALL) or (typ=`CE); string `C; string `P];
    "" sv (string tkr; expryDt[expiryDate]; r; string strike)
 };

// test
tkr:`IBM;
expiryDate:2025.01.09;
typ:`CALL;
strike:24000i;

show symbol[tkr;expiryDate;typ;strike]; // "IBM250109C24000" OK

My test code for formatting symbols as IBM250109C24000 works just fine. However, when i try and apply it on the table t below it fails since my function symbol is not vectorized. How do i make it work?

t:([] ticker:`IBM`IBM`IBM;
      expiryDate:2025.01.09 2025.01.09 2025.01.09;
      typ:`CALL`PUT`CE;
      strike:24000 24000 24000;
      secType:`OPT`OPT`OPT);
show t;

t:update symbol:symbol[ticker;expiryDate;typ;strike] from t where secType=`OPT; // error

I get the following output on running the code above:

"IBM250109C24000"
ticker expiryDate typ  strike secType
-------------------------------------
IBM    2025.01.09 CALL 24000  OPT    
IBM    2025.01.09 PUT  24000  OPT    
IBM    2025.01.09 CE   24000  OPT    
'type
  [3]  tv_options.q:5: symbol:{[tkr;expiryDate;typ;strike]
    if[not typ in `CALL`PUT`CE`PE; show "typ is not correct. it must be either CALL or PUT or CE or PE"; exit 1];
       ^
    r: $[(typ=`CALL) or (typ=`CE); string `C; string `P];

Solution

  • The easiest way is to use ' https://code.kx.com/q/ref/maps/#case

    t:update symbol:symbol'[ticker;expiryDate;typ;strike] from t where secType=`OPT; // error
    

    But a native vectorised function will perform better. Something like:

    genSymbols:{[tkr;expiryDate;typ;strike]
        if[any not typ in `CALL`PUT`CE`PE;
           '"typ is not correct. it must be either CALL or PUT or CE or PE"];
        r: ?[(typ=`CALL) or (typ=`CE);`C;`P];
        raze each (string tkr; expryDt each expiryDate;string r; string strike)
     };
    
    t:update symbol:genSymbols[ticker;expiryDate;typ;strike] from t where secType=`OPT;
    

    Rather than expryDt each expiryDate if there are not many unique values to expiryDate then you'll see an improvement with .Q.fu[expryDt;expiryDate]