-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix spin-offs calculations #524
Conversation
…ns-calculator into fix-spin-offs-tax-calcs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for implementing this! It needs some test to make sure the calculations are correct.
cgt_calc/main.py
Outdated
) | ||
available_quantity = min(disposal_quantity, same_day_quantity) | ||
if has_key(self.acquisition_list, date_index, symbol): | ||
sd_acquisition = self.acquisition_list[date_index][symbol] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with bnb
for bed_and_breakfast
but this one hurts readability IMO.
sd_acquisition = self.acquisition_list[date_index][symbol] | |
same_day_acquisition = self.acquisition_list[date_index][symbol] |
cgt_calc/main.py
Outdated
) | ||
assert bnb_acquisition.quantity <= acquisition.quantity | ||
|
||
sd_disposal = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sd_disposal = ( | |
same_day_disposal = ( |
cgt_calc/main.py
Outdated
disposal = self.disposal_list[date_index][symbol] | ||
disposal_quantity = disposal.quantity | ||
proceeds_amount = disposal.amount | ||
disposal_fees = disposal.fees |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only used once and not modified, can be used as disposal.fees
cgt_calc/main.py
Outdated
@@ -409,37 +509,30 @@ def process_disposal( | |||
fees=fees, | |||
new_quantity=current_quantity, | |||
new_pool_cost=current_amount, | |||
spin_off=None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's default to None
.
spin_off=None, |
cgt_calc/main.py
Outdated
ticker = input( | ||
"For a spin off, please enter the original ticker from which the new " | ||
"stock was spinned off: " | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How user will understand what split this is about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point :D
cgt_calc/main.py
Outdated
while True: | ||
# This would ideally be fetched from some stock DB but yfinance does not | ||
# provide any info on SpinOffs | ||
ticker = input( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add option to provide required info from text file? To make it possible to rerun script without specifying any input. Ideally, prices from yfinance can be stored there as well. E.g. here after fetching you can store data in some cache file and check its presence.
cgt_calc/main.py
Outdated
total_amount = sum( | ||
t.amount | ||
for transactions in self.acquisition_list.values() | ||
if (t := transactions.get(ticker)) | ||
) - sum( | ||
t.amount | ||
for transactions in self.disposal_list.values() | ||
if (t := transactions.get(ticker)) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use current value from portfolio?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, this is left over from a previous, invalid version of this diff
cgt_calc/main.py
Outdated
for transactions in self.disposal_list.values() | ||
if (t := transactions.get(ticker)) | ||
) | ||
share_of_original_cost = total_amount / (amount + total_amount) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why total amount increased here (amount + total_amount
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assume the market value of MMM shares is £90 per share and SOLV shares
is £10 per share immediately after the spin-off.
The total market value is £90 + £10 = £100.
we need to consider cost basis of "spin-off pool" as value of original stock and new stock.
* Fix calculations for case where there were multiple buy and sell transactions before spin-off - make spin-off a CalculationEntry * Adjust pdf formating * Add test for spin-offs.
Can you rebase on the latest revision? Btw, will it work correct for B&B case like in #511? |
I don't think it will change anything for that B&B case as I am not touching stock splits but B&B should be handled correctly in case of spin-offs (AFAICT, as it just modifies the pool price, I am not tax advisor though :)). |
You're not including the spin_off_handler file in the commit. |
How did it work before is beyond my understanding though, thanks! :D |
Thanks for working on this! 🚀 |
This diff fixes Spin-Off cost calculations (both for source and dest shares). Details of the calculations can be found in the comment of the main method. As we do not have a good DB for spin-offs the "source" share has to be provided by user during the run, the adjustments to the prices are then explained in generated
.pdf
file.Additionally:
I'll add tests after initial review round.