5 ms·
I enjoyed this post, thank you! For the benefit of anyone else reading, some context that I felt would have helped: The toy problem being considered is the foll
by svat 4y ago
I enjoyed this post, thank you! For the benefit of anyone else reading, some context that I felt would have helped: The toy problem being considered is the following. You are given a sequence of historical prices (of a single stock or index or whatever), one for each day:
day 1 2 3 ... n
price p1 p2 p3 ... pn
The task is to annotate each day i with a (retroactive) decision z_i ∈ {buy, sell, do nothing}, and do this optimally, subject to the constraint that you cannot sell before you buy, cannot "buy" twice without an intervening "sell" and vice-versa, etc. And there are indeed dynamic-programming algorithms to solve this quickly, which you can find on Leetcode writeups and whatnot.
(Whether or not this has any resemblance to real-world trading is not the point of the toy problem, which is about computational techniques. See e.g. Knuth's article “Are toy problems useful?” from Chapter 10 of https://cs.stanford.edu/~knuth/cs.html https://cs.stanford.edu/~knuth/cs.html, or “Puzzles versus the real world” on pages 7–9 of TAOCP Vol 4A.)
Another way to model it is with two-valued y_i ∈ {do nothing, "change state"}, where "change state" means buy if you haven't bought and sell if you have, with the last day's decision forced (you have to end in the sold state), which shows why there are 2^{n-1} possibilities to optimize over.
But there's yet another way of modeling the problem, presented in this post, where we have 2n-2 boolean variables x1, x2, x3, x4, … denoting respectively the choices of whether or not to "buy on day 1", "sell on day 2", "buy on day 2", "sell on day 3", and so on, and now the problem becomes one of the form:
maximize w1x1 + w2x2 + w3x3 + …
such that f(x1, x2, x3, ...) = 1
where f is a boolean function denoting whether the 0-1 values assigned to the x_i variables is "valid" (does not have both buy and sell on the same date, has a buy before a sell, etc).
Now, this may seem hard to optimize over, but BDDs (binary decision diagrams) are a data structure that can represent such functions compactly, and in this case (because of the problem structure) the entire truth table (over all possible 2^{2n-2} assignments to xi, with 2^{n-1} "true" values among them) can be represented as a BDD with 2.5n nodes, and with a standard algorithm can be optimized over.
This gives an algorithm that is just as fast as the dynamic programming algorithm (almost? asymptotically?), and is a fun exercise to play with BDDs, which this post describes very well.
- taeric 4y agoThanks! Better description of the toy than I put on the page. :) I haven't used a bdd before, so I was surprised this worked as well as it did. I haven't tried this with DP, but the solutions I saw that did weren't able to handle this much data. I'm assuming I just saw sub optimal solutions?
- vitus 4y agoI might be misunderstanding the problem statement, but my take: My impression is that for N max trades and M days of data, the "obvious" DP solution should be 2*N entries and O(NM) time, by tracking best profit for n trades whether you have the stock, where your update looks something like profit[trade_count=n, day=m, has_stock] = max(profit[trade_count=n, day=m-1, has_stock], profit[trade_count=n-1, day=n-1, has_stock] + transaction_cost[day=n, has_stock]) -- namely, as you've described in the article, either do nothing, or make a trade. Of course, you wouldn't store the full history -- you'd only need yesterday's data and today's update. Adding accounting to track the trade history is doable without bloating runtime too much, but it does increase space usage substantially. That said, if you don't have to keep to a strict number of trades, the DP solution should be able to fit in constant space (well, linear in number of days if you want to keep track of history for the best sequence of trades). I really like the idea in the article of adding a transaction cost and varying that to constrict the number of trades -- it reminds me of a cooling schedule for simulated annealing, and it's definitely not an approach I see interview candidates reaching for regularly.
- taeric 4y agoThat all sounds reasonable. I'm not sure what the solutions I saw were trying. They definitely went slower, though. Hours for one of the solutions I saw.