@Branko, thanks for sharing. This is an interesting idea.
I noticed a problem in the algorithm that result in overbuying your positions.
The way portfolio.positions_value and portfolio.cash are calculated by the backtester is not very useful for hedged positions. The short position is subtracted from the long position. As a result the overall position can run wild but the two variables that are supposed to measure the position remain neutral (close to zero).
So in calculate_direction() where you test for "cash" the result is not going to be what you expect. I suggest directly checking to see if you have a position and not using the aggregate value:
# this boolean test reveals if a position is already established
if context.portfolio.positions[context.stocks].amount == 0:
# this boolean test is highly misleading because the variables are miscalculated by the backtester
if (context.portfolio.positions_value + context.portfolio.cash) > 0:
In addition you had a short circuit test that would exit from handle_data() if a_order and b_order equal zero. I didn't trace all the logic to find out if this is a problem but in general I wouldn't want to have logic that halted before testing calculate_close_trades()
if a_order == 0 and b_order == 0: return
So I commented out that test. As a result calculate_close_trades() will likely be called even if no position is established. I added a quick test inside the function to prevent an error caused by trying to access variable keys that haven't been set yet.
if not signal in context.close_trades: return
The modified backtest is attached.