Forum Replies Created

Page 21 of 21
  • rocuinneagain

    Member
    October 1, 2021 at 12:00 am in reply to: wavg implementation detail

    Todays release  kdb+4.0 2021.10.01 contains a fix for the issue in your first example:

    q)0 wavg 5
    0n

     

  • rocuinneagain

    Member
    October 1, 2021 at 12:00 am in reply to: Control system command directory used (instead of /tmp)

    You cannot control the use of /tmp but you could possibly use a redirect to send the bulk of output to a different location.

    In a basic form:

    q)system"ls > /my/chosen/path/out.txt 2>&1;"
    q)result:read0`:/my/chosen/path/out.txt
    q)hdel`:/my/chosen/path/out.txt
    `:/my/chosen/path/out.txt
    q)result
    "file1"
    "file2"

     

    You could aim to make a more reusable function.

    For familiarity you could use the TMPDIR environment variable:

    q)setenv[`TMPDIR] "/my/chosen/path"

    Then create a function to run system commands

    systemTMPDIR:{[c] 
      f:first system"mktemp"; //Make a temp file respecting TMPDIR
      c:c," > ",f," 2>&1;echo $?"; //Add redirect to tmp file and capture of exit code
      e:"J"$first system c; //Execute the command
      f:hsym `$f; 
      r:read0 f; //Read the result of the command 
      hdel f; //Delete the tmp file
      $[not 0=e; //Check if the exit code was an error (not 0)
        [-1 last r;'`os]; //If an error print the last line and signal with 'os
        r] //If success return the data 
    }

    On success:

    q)systemTMPDIR"ls"
    "file1"
    "file2"

    On failure:

    q)systemTMPDIR"blah"
    sh: 1: blah: not found
    'os
    [0] systemTMPDIR"blah"
    ^

    *Note: This is just a small example and likely will not behave the exact same as the native ‘system’ in all cases.

  • rocuinneagain

    Member
    September 26, 2021 at 12:00 am in reply to: insert into global table in peach

    No, it is not possible to update a global variable from any thread other the main thread.

    The ‘noupdate’ error is detailed on: https://code.kx.com/q/basics/errors/

    Full list of blocked operations within peach: https://code.kx.com/q/ref/each/#blocked-within-peach

     

     

  • rocuinneagain

    Member
    September 14, 2021 at 12:00 am in reply to: Lists, dictionaries, tables and lists of dictionaries

    1. I might suggest to think about it the other way. Dictionaries are more like special paired lists.

    q)dict:`a`b!1 2
    q)lists:{(key x;value x)} dict
    q)dict
    a| 1
    b| 2
    q)lists
    a b
    1 2
    q)dict `a
    1
    q)lists[0]?`a
    0
    q)lists[1] lists[0]?`a / The same as: dict `a
    1

    https://code.kx.com/q/ref/find/

     

    2. Yes a list of conforming dictionaries is promoted a table

    q)(`a`b!1 2;`a`b!1 2)
    a b
    ---
    1 2
    1 2

    Importantly in memory the way it is actually stored is ‘flipped’ so it is a dictionary of lists. (no longer a list of dictionaries)

    q).Q.s1 (`a`b!1 2;`a`b!1 2)
    "+`a`b!(1 1;2 2)"

     

    This way the keys/column-names only need to be stored once for the whole table and not for each row.

    The columns then are vectors which is more efficient and performant.

     

    There are more details on indexing at depth here :

    https://code.kx.com/q4m3/3_Lists/#38-iterated-indexing-and-indexing-at-depth

     

    The “querying unstructured data” section of this blog may be of interest:
    https://kx.com/blog/kdb-q-insights-parsing-json-files/

    The code in it focuses on tables but can be adapted to lists/dictionaries as well:

    q)asLists:sample cols sample
    q)asLists[0;;`expiry]
    17682D19:58:45.000000000
    `
    `long$()
    ,""
    `long$()
    0N
    ,""

    q)@[`asLists;0;{(enlist[`]!enlist (::))(,)/:x}]
    `asLists
    q)asLists[0;;`expiry]
    17682D19:58:45.000000000
    ::
    ::
    ::
    ::
    ::
    ::
    q)fill:{n:count i:where (::)~/:y;@[y;i;:;n#x]}
    q)fill[0Wn]asLists[0;;`expiry]
    17682D19:58:45.000000000 0W 0W 0W 0W 0W 0W

    
    

     

     

  • rocuinneagain

    Member
    August 17, 2021 at 12:00 am in reply to: Transform Specific Column Values

    Without knowing the full rules and logic here are some thoughts.

    //Table taken from https://www.nasdaqtrader.com/trader.aspx?id=CQSsymbolconvention
    q)symbology:`NASDAQIntegratedPlatformSuffix xkey .Q.id ("****";enlist ",")0:`:symbology.csv
    q)5 sublist symbology
    NASDAQIntegratedPlatformSuffix| Security CQSSuffix CMSS..
    ------------------------------| ---------------------------------------------..
    ,"-"                          | "Preferred" ,"p" "PR"..
    "-A"                          | "Preferred Class "A"*" "pA" "PRA..
    "-B"                          | "Preferred Class "B"*" "pB" "PRB..
    ".A"                          | "Class "A"*" ".A" ,"A"..
    ".B"                          | "Class "B"*" ".B" ,"B"..

     

    //Assuming 4 character root
    q){s:string x;`$(4#s),symbology[4 _ s]`CQSSuffix} each (`$"AAPL.B*";`$"AAPL^#")
    `AAPL`AAPLrw

     

    //Assuming there is always a suffix and first non capital letter is beginning of suffix
    {s:string x;r:first where not s in .Q.A;`$(r#s),symbology[r _ s]`CQSSuffix} each (`$"AAPL.B*";`$"AAPL^#")
    `AAPL`AAPLrw

    Note: ‘.B*’ does not appear in that mapping table so ‘AAPL.B*’ does not receive a new CQS Suffix.

  • rocuinneagain

    Member
    August 17, 2021 at 12:00 am in reply to: Transform Specific Column Values

    ssr is a much slower operation than the above examples.
    Using wildcards such as “*#” is also difficult as it matches more than one suffix (.e.g “#” and “^#”).
    To work around this you can choose the longest matching suffix.

    Using ‘like’ and ‘@’ where possible rather than ‘ssr’ as below is a big speed improvement.

    Searching for “*” is also difficult as it is a wildcard. Instead, I use tab “t” in it’s place.

    If “t” is possibly in your data you would need to change this for another character.

    symbology:.Q.id ("****";enlist ",")0:`:symbology.csv
    update searchNASDAQ:{"*",@[x;where x="*";:;"t"]} each NASDAQ from `symbology
    func:{s:string x;
     m:select from symbology where @[s;where s="*";:;"t"] like/:searchNASDAQ;
     l:max count each m`NASDAQ;
     c:first exec CMS from m where l=count each NASDAQ;
     `$$[c~();s;(neg[l]_s),c]
    };

    In a test it does seem to operate correctly.

    Overall it still has risks as if bad data is sent in the function cannot truly validate what it is doing. Ideally you would have root and suffix separated by a known delimiter such as a space ” ” in the source data.

    -6 sublist {([] symNASDAQ:n;symCMS:func each n:`$"AAPL",/:x)}symbology`NASDAQ
    symNASDAQ symCMS 
    ------------------
    AAPL# AAPLWI 
    AAPL^# AAPLRTWI
    AAPL-# AAPLPRWI
    AAPL.A# AAPLAWI 
    AAPL+# AAPLWSWI
    AAPL~ AAPLTEST

    The extra complexity does come at a cost of speed.

    \ts func each 10000#`$"AAPL+#"
    41 553776

    symbologyOld:`NASDAQ xkey .Q.id (“****”;enlist “,”)0:`:symbology.csv
    \ts {s:string x;`$(4#s),symbologyOld[4 _ s]`CQSSuffix} each 10000#`$”AAPL+#”
    12 554448
    \ts {s:string x;r:first where not s in .Q.A;`$(r#s),symbologyOld[r _ s]`CQSSuffix} each 10000#`$”AAPL+#”
    16 554464

    As you used in your original example .Q.fu is a great tool when performing an intensive task repeatedly.

    Extreme example with only one unique input:

    \ts .Q.fu[func each] 10000#`$"AAPL+#"
    0 394032

    One limitation of .Q.fu is that it has no memory between executions.

    One example of a way to bypass this would be a memory cache.

    The library https://github.com/gitrj95/q-memo could be used.

    In this use-case your function is fast enough that the cache is overkill and should not actually be used but would be useful for very slow operations you may have to run many times.

    l memo.k
    .memo.init[`.;10000h] //Create a cache with 10k limit
    .memo.mk[`func;`memoFunc;`cache.0] //Create a wrapped function to use the cache

    ts memoFunc each 10000#`$(“AAPL~”;”AAPL+#”)
    126 553936

    //The cache pre stores the results
    cache.0
    f a                | r 
    -------------------| ---------
    ::                 | :: 
    ..memoFunc ,`AAPL~ | `AAPLTEST
    ..memoFunc ,`AAPL+#| `AAPLWSWI

     

  • You can use .p.wrap https://code.kx.com/q/ml/embedpy/userguide/#embedpy-objects_1

     

    Small example giving each subplot a title:

    plt:.p.import[`matplotlib;`:pyplot]
    plts:plt[`:subplots;<;pykwargs `ncols`figsize`dpi!(2;24 8;100)]
    .p.wrap[plts[1;0]][`:set_title]"Plot1";
    .p.wrap[plts[1;1]][`:set_title]"Plot2";
    plt[`:show][];

    Results in:

     

     

  • rocuinneagain

    Member
    August 10, 2021 at 12:00 am in reply to: KX Control – stopStateFunct?

    On the KX Platform you should not use .z.exit directly as it performs some inbuilt operations.

    Instead use .ch.addExit which is a handler for you to add your custom behaviour on top of what is inbuilt.

     

    https://code.kx.com/platform/api/IPC/#chaddexit

  • rocuinneagain

    Member
    July 11, 2021 at 12:00 am in reply to: Trouble With Huge CSVs

    Yes the w32 version has a limit to how much memory it can address, w64 does not have this restriction.

     

    You could also stream the data to an on disk table:

    .Q.fs[{`:trade/ upsert flip colnames!("**********";",")0:x}]`:filename
    trade:get `:trade/
Page 21 of 21