src | ||
.gitignore | ||
.prettierrc | ||
package.json | ||
README.md | ||
test | ||
yarn.lock |
Quick attempt at an optimal portfolio balancer.
Notes:
- The balancing algorithm is not currently optimal (Work in progress). See Closeness section
- No external stock API is used. The given API gives only daily time-series output. This application is built as a stream processing system which would allow automatic rebalancing for specific events such as a price change of more than X%. I may add a randomized price generator as an input.
Install
yarn
To run
Using the pre-seed file with pricing from Jul 12th:
< test node .
Using the pre-seed file and allowing interactive commands:
cat test - | node .
Interactive Commands:
<TICKER>:<price>
Sets the stock price for the given ticker
example:
AAPL:152.3
rebalance:<account_id>
Triggers a rebalance for the given account ID
example:
rebalance:1
note: Account 1 is there by default.
Closeness
The problem of portfolio balancing can be described as such:
Minimize:
w_f - w_t
e.g.
SUM( |c_i*p_i - t_i| ) for stocks i
or
SUM( (c_i*p_i - t_i)^2 ) for stocks i
Subject to:
SUM( c_i*p_i ) <= T
c_i are Integers >= 0 (Except USD)
Where
w_f is the final portfolio
w_t is the target portfolio
c_i is the number of shares of stock i
p_i is the price of stock i
t_i is the total optimal fractional amount invested in stock i
e.g. % allocation * total portfolio value
This problem statement falls in the Mixed Integers Quadratic Programming category. This problem can be solved through enumeration in exponential time 2^n
where n is the total
number of possible stocks purchase (not just ticker), which is very much impractical. Optimisations can be applied to reduce it to 2^n
where n is the total number of tickers,
although still exponential. From there (or possibly through a simplified problem statement), this can possibly be solved in pseudo-polynomial time using algorithms such as
branch-and-bound or Quadknap.
Currently, the algorithm used is non-optimal in some edge-cases but produces very close results in most cases. That algorithm runs in linear time (quasilinear if tickers are not previously sorted) and can be used to evaluate the bounds in a branch-and-bound algorithm for potentially optimal results.
Unfortunately, time constraints prevented me from finishing the implementation as of Sunday July 12th. I will update this README if that changes.