Append columns to empty table - Q/KDB+ - kdb

I'm pulling data from a source that returns tick data for stocks (timespan + float prices).
I need to build 1 table that has the tick data for each stock, while inserting new timespan index values for each one. Example:
AAPL:
t0 101.20
t3 102.10
GOOG:
t1 850.50
t2 860.10
Table:
AAPL GOOG
t0 101.20 NA
t1 NA 850.50
t2 NA 860.10
t3 102.10 NA
There would be many symbols, so I can't just manually type AAPL, GOOG etc.

While it would be possible to set up a table like you have described it would not be advisable. You would be better to set up a column to record each stock, sym in this case:
t sym price
-------------------------------------------
2018.02.05D14:11:09.241245000 AAPL 101.7808
2018.02.05D14:11:09.241246000 GOOG 103.0177
2018.02.05D14:11:09.241246000 AAPL 107.8503
2018.02.05D14:11:09.241247000 GOOG 105.3471

Related

query for selecting N records

I have a table tab that has cols date,sym,value and is sorted from oldest date to the recent.
I am trying to select the past N records for each sym and am not sure of the query for this. I know that I can select based on date being within a range but I needed it based on sym irrespective if value appeared on consecutive dates or not.
You could do this with fby and the virtual row number column i:
https://code.kx.com/q/ref/fby/
q){ select from tab where ({y in x#y}[x];i) fby sym }[-2]
date sym time src price size
------------------------------------------------------------
2014.04.21 AAPL 2014.04.21D16:29:03.253000000 N 24.98 3561
2014.04.21 AAPL 2014.04.21D16:29:03.558000000 N 24.98 2733
2014.04.21 CSCO 2014.04.21D16:28:56.265000000 O 35.6 8390
2014.04.21 CSCO 2014.04.21D16:29:44.572000000 L 35.61 2286
2014.04.21 DELL 2014.04.21D16:29:35.374000000 L 29.57 1444
2014.04.21 DELL 2014.04.21D16:29:39.979000000 N 29.56 216
2014.04.21 GOOG 2014.04.21D16:29:50.569000000 N 41.87 722
2014.04.21 GOOG 2014.04.21D16:29:58.633000000 O 41.9 437
Edit: Faster way would be to use functional exec with the 5th argument n(number of records) for each sym.
raze{
//[table;where;by;cols;rows]
?[tab;enlist (in;`sym;enlist x);0b;();y]
}[;-2]'[distinct tab[`sym]]
https://code.kx.com/q/basics/funsql/
Matt's suggestions using an fby and functional select are best if you want all columns in the table returned. If you only need the date, sym & price columns returned you could use
q)ungroup select -2#date,-2#price by sym from trade
sym date price
----------------------
APPL 2021.03.13 111.77
APPL 2021.03.13 111.85
CAT 2021.03.13 246
CAT 2021.03.13 246.27
GOOG 2021.03.13 206.24
GOOG 2021.03.13 206.21
NYSE 2021.03.13 60.67
NYSE 2021.03.13 60.97
Note that this can become tedious when selecting a large number of columns. In those cases it's better to stick with Matt's suggestions.

KDB query returns more 2 columns instead of 1 for max filter

I just want to create one report where I need max price for each symbol so I wrote following query which works fine on PROD but fails on UAT. So just wanted to know if following query is the appropriate or not.
select from (select sum price by sym,time,src from Table where date within(2019.12.01;2019.12.31) ) where size=(max;price) fby tier
Above query returns 2 column for each symbol instead of 1. Following is the result inner query i.e select sum price by sym,time,src from Table where date within(2019.12.01;2019.12.31)
t:([]time:8#2019.03.11D09:00+"v"$0 4 8 10;sym:8#`GOOG`GOOG`MSFT`MSFT;src:8#`L`O`N`O;price:36.01 35.01 35.5 31.1 39.01 38.01 33.5 32.1;size:8#1427 708 7810 1100)
time sym src price
--------------------------------------------
2019.03.11D09:00:00.000000000 GOOG L 36.01
2019.03.11D09:00:04.000000000 GOOG O 35.01
2019.03.11D09:00:08.000000000 MSFT N 35.5
2019.03.11D09:00:10.000000000 MSFT O 31.1
2019.03.11D09:00:00.000000000 GOOG L 39.01
2019.03.11D09:00:04.000000000 GOOG O 38.01
2019.03.11D09:00:08.000000000 MSFT N 33.5
2019.03.11D09:00:10.000000000 MSFT O 32.1
And output for select from (select sum price by sym,time,src from Table where date within(2019.12.01;2019.12.31) ) where size=(max;price) fby tier is :
t[0,2,4,7]
time sym src price
---------------------------------------------
2019.03.11D09:00:00.000000000 GOOG L 36.01
2019.03.11D09:00:08.000000000 MSFT N 35.5
2019.03.11D09:00:00.000000000 GOOG L 39.01
2019.03.11D09:00:10.000000000 MSFT O 32.1
I suspect that there is something missing with the dataset that you have provided in the question. The results of your inner queries are all floats with remainders, as size is a long, it doesn't make any sense that size=(max;price) is returning any results.
To answer your question in the most general of sense, to get the max price by sym is
select from t where price=(max;price) fby sym
Applying this to the inner result you have provided
q)select from t where price=(max;price) fby sym
time sym src price size
-------------------------------------------------
2019.03.11D09:00:08.000000000 MSFT N 35.5 7810
2019.03.11D09:00:00.000000000 GOOG L 39.01 1427

How do I get this output from MySQL

I have a table called nasdaq_transactions looks like below
Ticker Close Date
GOOG 1195.06 08/15/2018
AAPL 215.15 08/15/2018
MSFT 104.56 08/15/2018
GOOG 1198.11 08/16/2018
AAPL 216.1 08/16/2018
MSFT 105.1 08/16/2018
GOOG 1200.96 08/17/2018
AAPL 217.58 08/17/2018
MSFT 107.58 08/17/2018
Want to build a query that gives a output
Ticker 08/15/2018 08/16/2018 08/17/2018
GOOG 1196.06 1198.11 1200.96
AAPL 215.15 216.1 217.58
MSFT 104.56 105.1 107.58
There are several ways that you can transform data from multiple rows into columns.
In SQL Server you can use the PIVOT function to transform the data from rows to columns:
select * from
(
select Ticker, Date
from nasdaq_transactions
)
pivot
(
max(value)
for columnname in ('08/15/2018', '08/16/2018', '08/17/2018')
) piv;
I have given you a sample code. Refer to it and apply accordingly.

Split single column to multiple columns in KDB

I want to split values in a column to multiple columns after applying a complex function.
e.g. For the following trade table t , I want to split the sym into 2 separate columns sym and src. However, the function I would be applying would be slightly complex.
q)t:([] time:10:01:01 10:01:03 10:01:04;sym:`goog.l`vod.l`apple.o;qty:100 200 150)
time sym qty
--------------------
10:01:01 goog.l 100
10:01:03 vod.l 200
10:01:04 apple.o 150
If your table is very big and the sym column is very repetitive (which it looks like it will be if it's tick data) then the following will be much quicker:
f:{` vs'x}
#[t;`col1`col2;:;flip .Q.fu[f]t`sym]
You can create a table of sym and src by splitting on ., creating a dictionary then using flip to create a table:
q)show r:exec flip`sym`src!flip` vs/:sym from t
sym src
---------
goog l
vod l
apple o
This can be joined to the original table using each-both ,':
q)t,'r
time sym qty src
----------------------
10:01:01 goog 100 l
10:01:03 vod 200 l
10:01:04 apple 150 o
If column order is important then this can be fixed with xcols:
q)`time`sym`src xcols t,'r
time sym src qty
----------------------
10:01:01 goog l 100
10:01:03 vod l 200
10:01:04 apple o 150
One of the way to get this done is :
q)update sym:sym[;0] , mkt:sym[;1] from update ` vs/:sym from t
time sym qty mkt
----------------------
10:01:01 goog 100 l
10:01:03 vod 200 l
10:01:04 apple 150 o
If you are not intrested in any other columns except the one from the table that needs spliting then
q)exec {`s`mkt!` vs x}each sym from t
s mkt
---------
goog l
vod l
apple o
Another option would be;
q)(,'/)(t;flip`sym`src!exec flip ` vs'sym from t)
time sym qty src
----------------------
10:01:01 goog 100 l
10:01:03 vod 200 l
10:01:04 apple 150 o

How to generate datatable by iterating through multiple lists? (KDB)

I have a function quotes[ticker;startDate;endDate], and a function indexConstituents[index;startDate;endDate] that yield the below:
daterange: 2017.12.05,2017.12.06;
quotes'[AAPL;daterange]
date time sym price
2017.12.05 09:45 AAPL 101.20
2017.12.06 09:45 AAPL 102.30
quotes'[GOOG;daterange]
date time sym price
2017.12.05 10:00 GOOG 800.50
quotes'[BBRY;daterange]
date time sym price
2017.12.06 11:15 BBRY 02.10
and
indexConstituents'[DJIA;daterange]
date sym shares divisor
2017.12.05 AAPL 20 2
2017.12.05 GOOG 5 1
2017.12.06 AAPL 10 1.5
2017.12.06 BBRY 100 1
I need a way to run the indexConstituents function as normal to yield a list of constituents over a set of days (as in the second table above), then fetch the data from table 1 for each constituent. Finally, I need to join the data from both tables to yield the below:
data:
date time sym price shares divisor
2017.12.05 09:45 AAPL 101.20 20 2
2017.12.06 09:45 AAPL 101.30 10 1.5
2017.12.05 10:00 GOOG 800.50 5 1
2017.12.06 11:15 BBRY 02.10 200 1
Code for the first two tables:
([] date:2017.12.05,2017.12.06; time:09:45,09:45; sym:`AAPL,`AAPL; price:101.20,102.30)
([] date:2017.12.05,2017.12.05,2017.12.06,2017.12.06; sym:`AAPL,`GOOG,`AAPL,`BBRY; shares:20f,5f,10f,100f; divisor:2f,1f,1.5f,1f)
I think the best approach is to assign the resultant table from indexConstituents'[DJIA;daterange] to a variable, so that we can then pull out the sym column and apply distinct to it.
You can then use that list of syms as your first argument to the quotes.
Finally join the two resultant tables together.
idx:indexConstituents'[DJIA;daterange];
q:quotes\:/:[distinct idx`sym;daterange];
q lj 2!idx
Hope this helps!