Discrepancy Between Expected and Actual Returns When Buying and Selling the Same Stock on the Same Date and Price
Ajay-Razor opened this issue · 2 comments
I am trying to understand how selling works in bt. I found that when buying and selling the same stock on the same date and at the same price, if I gain +2% from the buy side, then I should incur a -2% loss on the sell side. However, the numbers are coming out quite oddly.
This is code
`import pandas as pd
import bt
dates=pd.date_range('2023-01-01','2023-01-10')
x=[8.52, 8.62, 8.36, 8.54, 7.97, 8.34, 8.1, 7.81, 7.88, 7.28]
price=pd.DataFrame(x,index=dates,columns=['A'])
s = bt.Strategy("Buy", [bt.algos.RunOnDate(*dates[::5]), # Buy Strategy
bt.algos.WeighSpecified(**{'A':1}),
bt.algos.Rebalance()])
bt_backtest1 = bt.Backtest(s, price, initial_capital=100000, integer_positions=True)
s = bt.Strategy("Sell", [bt.algos.RunOnDate(*dates[::5]), # Sell Strategy
bt.algos.WeighSpecified(**{'A':-1}),
bt.algos.Rebalance()])
bt_backtest2 = bt.Backtest(s, price, initial_capital=100000, integer_positions=True)
btl=[bt_backtest1,bt_backtest2]
result=bt.run(*btl)
rt =(result.prices/result.prices.shift(1))-1 # daily return
rt=rt.round(5)
print('buy daily Returns :-->',rt['Buy'].values.tolist())
print('Sell daily Returns :-->',rt['Sell'].values.tolist())
buy daily Returns :--> [nan, 0.0, 0.01174, -0.03016, 0.02153, -0.06674, 0.04642, -0.02878, -0.0358, 0.00896, -0.07614]
Sell daily Returns :--> [nan, 0.0, -0.01174, 0.03088, -0.02074, 0.06706, -0.0408, 0.02878, 0.0338, -0.00789, 0.06818]
`
I believe that returns from the buy and sell sides should be equal and opposite. Does bt follow a different logic or involve any special factors when it comes to selling? Please help me figure this out.
You are only rebalancing your strategy every 5 days. See dates[::5]. That is no big issue for a long position (in particular if you were to set integer_positions=False), there would be no cash at all and your portfolio is fully invested all the time. The same doesn't apply for a short strategy. If the stock goes up, you are losing money and can afford to held less units of the stock etc. etc.
Take a look at the resulting positions of your strategies using bt_backtest1.positions etc.
With daily rebalancing (dates[::1] and integer_positions=False) your issue disappears. If using integer_positions=True, there are small numerical issues due to a marginal cash holding.
buy daily Returns :--> [nan, 0.0, 0.01174, -0.03016, 0.02153, -0.06674, 0.04642, -0.02878, -0.0358, 0.00896, -0.07614]
Sell daily Returns :--> [nan, 0.0, -0.01174, 0.03016, -0.02153, 0.06674, -0.04642, 0.02878, 0.0358, -0.00896, 0.07614]
You are only rebalancing your strategy every 5 days. See dates[::5]. That is no big issue for a long position (in particular if you were to set integer_positions=False), there would be no cash at all and your portfolio is fully invested all the time. The same doesn't apply for a short strategy. If the stock goes up, you are losing money and can afford to held less units of the stock etc. etc.
Take a look at the resulting positions of your strategies using bt_backtest1.positions etc.
With daily rebalancing (dates[::1] and integer_positions=False) your issue disappears. If using integer_positions=True, there are small numerical issues due to a marginal cash holding. buy daily Returns :--> [nan, 0.0, 0.01174, -0.03016, 0.02153, -0.06674, 0.04642, -0.02878, -0.0358, 0.00896, -0.07614] Sell daily Returns :--> [nan, 0.0, -0.01174, 0.03016, -0.02153, 0.06674, -0.04642, 0.02878, 0.0358, -0.00896, 0.07614]
Thanks