Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Transaction Details not making sense

Has anyone else experienced Transaction Details not matching what you expected your algorithm to do?

In this case, I expected the algorithm to be 100% invested in either stocks (VTI) or bonds (TLT) depending on the RSI of TLT, rebalanced weekly. So every week I'd expect to see either no transactions (i.e. stay 100% in VTI or TLT), or two transactions (i.e. sell either VTI or TLT and buy the other).

Instead, there are weeks when I'm already 100% invested in VTI but the algorithm buys a few more shares of VTI … or it switches between VTI and TLT through multiple buys and sells (instead of one transaction for each, as I'd expect).

What am I missing …?

Thanks

4 responses

The transaction details seem fine. It represents how your trading logic plays out.

First, looking at the "Daily Positions and Gains" tab it shows you are indeed always "100%" invested in either VTI or TLT (or cash at the beginning). There will typically also be a little cash or, in the case of a leveraged portfolio, "buying power" in the portfolio because you cannot purchase fractional shares. If VTI, for example is selling for $83/share and you have $900 in your account, then you could purchase 10 share for $830. There would then be $830 in VTI and $70 in cash (there would be transaction costs deducted too which I'll ignore). So, while you can say you're "100%" invested in VTI, there is actually a little bit of cash there too.

Also keep in mind that the backtest automatically adds any dividends that are realized by your holdings to your account in the form of cash. Not sure if that shows up in this specific case but that will increase ones buying power.

This "rounding" (and potentially dividends) is what's causing the weekly buy and sell of a few shares which you see in the "Transaction Details" tab. If the price of VTI fell below $70 in the above example, then there would be enough cash to by one share, so that is what the algorithm does.

If you aren't using leverage you will typically only ever buy shares as the share price goes down (unless you get a dividend to increase cash). However, if you are using leverage (which this algorithm does) then there is the potential for selling shares too. This happens as the algorithm tries to maintain the leverage at a fixed value (in this case 2). Maybe think of it as a self imposed margin call. Change the leverage to 1 and you will see significantly less of the buy/sell behavior.

The real culprit is the "order_target_percent(xxx, 1)" method. Each week it will ensure you are "100%" invested even if it means buying or selling just a few shares.

In real trading you would probably want to add code to avoid this behavior. Transaction costs would make buying and selling anything below a minimum threshold unprofitable.

Make sense?

Thanks, Dan. Makes a lot of sense.

I was wondering whether dividends and margin were factors, but I assumed the algorithm would only do what was explicitly programmed. Good to know what’s happening in the background.

Any suggestions for code to require a minimum # shares or dollar value when I rebalance? I did a quick search but couldn’t find anything.

Thanks,

Mark

One way to keep from trading small amounts is to ensure you have some minimum available funds before you make any buys. One can always sell but check for a minimum before you buy. See the attached code. I added a new variable called "context.min_order_size" and then compared "context.account.available_funds" to that before making any buys. [note that since there's leverage being used the comparison should probably be " if context.account.available_funds > context.min_order_size / lev "]

Notice now that there are only all buys or all sells and no "ones and twos" being traded. However, it also has the consequence that the account will go all to cash for a week after selling and then buy from that available cash. This isn't all bad. One issue with the original algorithm is that it would at times buy before the current holdings were sold. This resulted in an "intraday" leverage much greater than 2. The buy may not have been placed in real trading because there wasn't enough margin available. Look at 2008-2-29 in the original backtest for this behavior.

Checking for funds availability and if there are existing outstanding orders is very important in real trading and should always be part of an "order management" section of ones logic.

In any case, this probably looks more like what you expected to see with all buys then all sells.

Good luck

Awesome. Thanks again!