I've a table t
as
q)trades: ([]
signalTime: 2024.01.05 2024.01.12 2024.01.19 2024.01.25 2024.02.02 2024.02.09 2024.02.16 2024.02.23 2024.03.01 2024.03.07;
exitTime: 2024.01.25 2024.02.01 2024.02.08 2024.02.15 2024.02.22 2024.02.29 2024.03.07 2024.03.14 2024.03.21 2024.03.28
);
signalTime exitTime
----------------------
2024.01.05 2024.01.25
2024.01.12 2024.02.01
2024.01.19 2024.02.08
2024.01.25 2024.02.15
2024.02.02 2024.02.22
2024.02.09 2024.02.29
2024.02.16 2024.03.07
2024.02.23 2024.03.14
2024.03.01 2024.03.21
2024.03.07 2024.03.28
I would like to only keep trades whose intervening dates (between signalTime
and exitTime
) do not overlap with those of any other trades (rows). Alternatively, there should be only one trade during any given date. The expected output should be
signalTime exitTime
----------------------
2024.01.05 2024.01.25
2024.02.02 2024.02.22
2024.02.23 2024.03.14
While I'm able to conceive a solution using a do
loop, how do i achieve this in more efficient, idiomatic q
?
Here's my feeble attempt at the solution using a do
loop though it's not quite correct.
removeOverlappingTrades:{[t]
n: count t;
accept: n#0b;
accept[0]: 1b;
lastExitTime: t[`exitTime][0];
do[n-1; {[t;lastExitTime;accept;x]
i: x+1; // Current index
if[t[`signalTime][i] >= lastExitTime;
accept[i]: 1b;
lastExitTime: t[`exitTime][i];
];
}[t;lastExitTime;accept] each til n-1];
t where accept
};
// Add a dummy row to ensure the first row gets selected
// Add a boolean `b` column to capture results
q)r:update b:0b from ([] signalTime:enlist -0Wd;exitTime:enlist -0Wd),trades
q)r
signalTime exitTime b
-----------------------
-0W -0W 0
2024.01.05 2024.01.25 0
2024.01.12 2024.02.01 0
2024.01.19 2024.02.08 0
2024.01.25 2024.02.15 0
2024.02.02 2024.02.22 0
2024.02.09 2024.02.29 0
2024.02.16 2024.03.07 0
2024.02.23 2024.03.14 0
2024.03.01 2024.03.21 0
2024.03.07 2024.03.28 0
//scan through the table
//capturing when a new trade has no overlap with the prevailing
q)r:{[x;y] $[y[`signalTime]>x[`exitTime];
[y[`b]:1b;y]; //New window opens, keep y with 1b set
[x[`b]:0b;x]] //No new window, keep x with 0b set
} scan r
q)r
signalTime exitTime b
-----------------------
-0W -0W 0
2024.01.05 2024.01.25 1
2024.01.05 2024.01.25 0
2024.01.05 2024.01.25 0
2024.01.05 2024.01.25 0
2024.02.02 2024.02.22 1
2024.02.02 2024.02.22 0
2024.02.02 2024.02.22 0
2024.02.23 2024.03.14 1
2024.02.23 2024.03.14 0
2024.02.23 2024.03.14 0
//Filter only when new windows opened
q)select from r where b
signalTime exitTime b
-----------------------
2024.01.05 2024.01.25 1
2024.02.02 2024.02.22 1
2024.02.23 2024.03.14 1