I still don't get it :) ...
Well, what I do, is the displacement vector is always scaled by time, so every displacement vector is just a per tick average of the enemy's movement. Bullet power is forgotten, like with GFs. So if the bot moved forward 30 and left 50, relative to their initial heading, and this was over 10 ticks, the displacement vector recorded would be (3, -5). To select which displacement vectors to use, I do it the same as for GuessFactors or anything else, by recording other attribute data for inputs and doing a KNN search. In fact, all of my gun code is exactly the same except for the method that translates their movement over the time of the wave to a GuessFactor or Displacement Vector, and back into a firing angle relative to the absolute bearing to the enemy.
To project the displacement vectors into firing angles, I go tick by tick, adding the dx and dy of the displacement vector to their current position (you can do the trig once and cache it, since the angle isn't changing) and advancing my wave by bullet velocity until the bullet would pass their position. It's true you might want bullet power to also be one of the attribute inputs. I do this in Diamond's main gun (though it's GF). But it's not hugely important.
So, I'd say yes, use waves. You could use any timer, but waves mean the timer is bullet flight time, which is a reasonable choice. If you want to go to a lot of trouble not to suffer the loss of fidelity in dividing and re-inflating all the vectors by bullet time, it would probably be simpler to just do real Play It Forward from the raw movement logs.
Does any of that make sense / help? You could also check out Diamond's wave class or BrokenSword for a really basic version of how I use them. (Though I store them as polar coordinates in BrokenSword, for code size. ;))