Skip to content

Commit

Permalink
Moved "owner" from all stock data to sell method
Browse files Browse the repository at this point in the history
Knowing the "owner" of a sale proceeds is only useful for stock options.
  • Loading branch information
had committed Jul 4, 2023
1 parent 2acd7e1 commit e484de2
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 36 deletions.
20 changes: 8 additions & 12 deletions src/easyfrenchtax/stock_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

@dataclass
class StockGroup:
owner: int # taxpayer 1 or 2, typically, for tax statements
count: int
available: int
acq_price: float
Expand Down Expand Up @@ -121,12 +120,11 @@ def rsu_plan(self, name: str, approval_date: date, symbol: str, currency: str) -
currency=currency
)

def rsu_vesting(self, owner: int, symbol: str, plan_name: str, count: int, acq_date: date, acq_price: float,
def rsu_vesting(self, symbol: str, plan_name: str, count: int, acq_date: date, acq_price: float,
currency: str = None) -> None:
if not currency:
currency = self.rsu_plans[plan_name].currency
self.rsus[symbol].append(StockGroup(
owner=owner,
count=count,
available=count, # new acquisition, so everything available
acq_price=acq_price,
Expand All @@ -136,9 +134,8 @@ def rsu_vesting(self, owner: int, symbol: str, plan_name: str, count: int, acq_d
))
self.rsus[symbol].sort(key=lambda a: a.acq_date)

def add_espp(self, owner: int, symbol: str, count: int, acq_date: date, acq_price: float, currency: str) -> None:
def add_espp(self, symbol: str, count: int, acq_date: date, acq_price: float, currency: str) -> None:
self.espp_stocks[symbol].append(StockGroup(
owner=owner,
count=count,
available=count, # new acquisition, so everything available
acq_price=acq_price,
Expand All @@ -148,10 +145,9 @@ def add_espp(self, owner: int, symbol: str, count: int, acq_date: date, acq_pric
))
self.espp_stocks[symbol].sort(key=lambda a: a.acq_date)

def add_stockoptions(self, owner: int, symbol: str, plan_name: str, count: int, vesting_date: date,
def add_stockoptions(self, symbol: str, plan_name: str, count: int, vesting_date: date,
strike_price: float, currency: str) -> None:
self.stock_options[symbol].append(StockGroup(
owner=owner,
count=count,
available=count, # new acquisition, so everything available
acq_price=strike_price if currency != "EUR" else None, # only set one of the two acquisition prices...
Expand Down Expand Up @@ -190,15 +186,15 @@ def parse_date(some_date):
if plan_name not in self.rsu_plans:
plan_date = parse_date(row["Plan date"])
self.rsu_plan(plan_name, plan_date, symbol, currency)
self.rsu_vesting(owner, symbol, plan_name, acq_count, acq_date, acq_price, currency)
self.rsu_vesting(symbol, plan_name, acq_count, acq_date, acq_price, currency)
elif stock_type == "ESPP":
self.add_espp(owner, symbol, acq_count, acq_date, acq_price, currency)
self.add_espp(symbol, acq_count, acq_date, acq_price, currency)
elif stock_type == "StockOption":
self.add_stockoptions(owner, symbol, plan_name, acq_count, acq_date, acq_price, currency)
self.add_stockoptions(symbol, plan_name, acq_count, acq_date, acq_price, currency)

####### stock selling related load functions #######

def sell_stockoptions(self, symbol: str, nb_stocks: int, sell_date: date, sell_price: float, fees: float,
def sell_stockoptions(self, owner: int, symbol: str, nb_stocks: int, sell_date: date, sell_price: float, fees: float,
currency: str = "EUR"):
if nb_stocks == 0:
return
Expand All @@ -219,7 +215,7 @@ def sell_stockoptions(self, symbol: str, nb_stocks: int, sell_date: date, sell_p
sell_date=sell_date,
sell_price_eur=sell_price_eur,
selling_fees=round(cc.convert(fees, currency, "EUR", date=sell_date), 2),
owner=acq.owner
owner=owner
))
# update the stock options data with new availability
self.stock_options[symbol][i].available = acq.available - sell_from_acq
Expand Down
48 changes: 24 additions & 24 deletions tests/test_stock_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,26 @@
def stock_helper_with_plan():
stock_helper = StockHelper()
stock_helper.rsu_plan("Cake1", date(2016, 6, 28), "CAKE", "USD")
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 240, date(2018, 6, 29), 20)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2018, 7, 30), 18)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2018, 8, 28), 19)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2018, 9, 28), 14)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2018, 10, 29), 15)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2018, 11, 28), 14)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2018, 12, 28), 19)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2019, 1, 28), 23)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 10, date(2019, 2, 28), 24)
stock_helper.rsu_vesting(1, "CAKE", "Cake1", 100, date(2020, 2, 28), 24)
stock_helper.rsu_vesting("CAKE", "Cake1", 240, date(2018, 6, 29), 20)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2018, 7, 30), 18)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2018, 8, 28), 19)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2018, 9, 28), 14)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2018, 10, 29), 15)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2018, 11, 28), 14)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2018, 12, 28), 19)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2019, 1, 28), 23)
stock_helper.rsu_vesting("CAKE", "Cake1", 10, date(2019, 2, 28), 24)
stock_helper.rsu_vesting("CAKE", "Cake1", 100, date(2020, 2, 28), 24)
stock_helper.rsu_plan("Pineapple", date(2016, 6, 29), "PZZA", "USD")
stock_helper.rsu_vesting(1, "PZZA", "Pineapple", 313, date(2020, 12, 28), 20.84)
stock_helper.rsu_vesting(1, "PZZA", "Pineapple", 312, date(2021, 3, 28), 27.44)
stock_helper.rsu_vesting(1, "PZZA", "Pineapple", 313, date(2021, 6, 28), 37.25)
stock_helper.rsu_vesting("PZZA", "Pineapple", 313, date(2020, 12, 28), 20.84)
stock_helper.rsu_vesting("PZZA", "Pineapple", 312, date(2021, 3, 28), 27.44)
stock_helper.rsu_vesting("PZZA", "Pineapple", 313, date(2021, 6, 28), 37.25)
stock_helper.rsu_plan("Pepperoni", date(2017, 7, 28), "PZZA", "USD")
stock_helper.rsu_vesting(1, "PZZA", "Pepperoni", 398, date(2020, 12, 16), 18.75)
stock_helper.rsu_vesting(1, "PZZA", "Pepperoni", 133, date(2021, 1, 26), 19.13)
stock_helper.add_espp(1, "BUD", 200, date(2019, 1, 15), 22, "USD")
stock_helper.add_espp(1, "BUD", 300, date(2019, 7, 15), 19, "USD")
stock_helper.add_stockoptions(1, "PZZA", "SO", 150, date(2018, 1, 15), 5, "USD")
stock_helper.rsu_vesting("PZZA", "Pepperoni", 398, date(2020, 12, 16), 18.75)
stock_helper.rsu_vesting("PZZA", "Pepperoni", 133, date(2021, 1, 26), 19.13)
stock_helper.add_espp("BUD", 200, date(2019, 1, 15), 22, "USD")
stock_helper.add_espp("BUD", 300, date(2019, 7, 15), 19, "USD")
stock_helper.add_stockoptions("PZZA", "SO", 150, date(2018, 1, 15), 5, "USD")
return stock_helper


Expand Down Expand Up @@ -141,8 +141,8 @@ def test_rsu_example(stock_helper_with_plan):

def test_espp_sale(convert_fn):
stock_helper = StockHelper()
stock_helper.add_espp(1, "BUD", 200, date(2019, 1, 15), 22, "USD")
stock_helper.add_espp(1, "BUD", 300, date(2019, 7, 15), 19, "USD")
stock_helper.add_espp("BUD", 200, date(2019, 1, 15), 22, "USD")
stock_helper.add_espp("BUD", 300, date(2019, 7, 15), 19, "USD")
sell_price = 28
final_count = stock_helper.sell_espp("BUD", 300, date(2021, 8, 2), sell_price=sell_price, fees=0, currency="USD")
assert final_count == 300
Expand Down Expand Up @@ -171,7 +171,7 @@ def test_espp_sale(convert_fn):

def test_stockoptions_sale(stock_helper_with_plan, convert_fn):
sell_price = 40
final_count = stock_helper_with_plan.sell_stockoptions("PZZA", 50, date(2021, 8, 2), sell_price=sell_price,
final_count = stock_helper_with_plan.sell_stockoptions(1, "PZZA", 50, date(2021, 8, 2), sell_price=sell_price,
fees=0, currency="USD")
agt = stock_helper_with_plan.compute_acquisition_gain_tax(2021)
cgt = stock_helper_with_plan.compute_capital_gain_tax(2021)
Expand All @@ -192,7 +192,7 @@ def test_reset_all(stock_helper_with_plan):
# CAKE=240 ; BUD=200 ; PZZA=150
stock_helper_with_plan.sell_rsus("CAKE", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_espp("BUD", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_stockoptions("PZZA", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_stockoptions(1, "PZZA", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.reset()
assert stock_helper_with_plan.rsus["CAKE"][0].available == 240
assert stock_helper_with_plan.espp_stocks["BUD"][0].available == 200
Expand All @@ -204,7 +204,7 @@ def test_reset_by_stocktype(stock_helper_with_plan):
# CAKE=240 ; BUD=200 ; PZZA=150
stock_helper_with_plan.sell_rsus("CAKE", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_espp("BUD", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_stockoptions("PZZA", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_stockoptions(1, "PZZA", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
assert stock_helper_with_plan.rsus["CAKE"][0].available == 190
assert stock_helper_with_plan.espp_stocks["BUD"][0].available == 150
assert stock_helper_with_plan.stock_options["PZZA"][0].available == 100
Expand All @@ -226,7 +226,7 @@ def test_reset_by_symbol(stock_helper_with_plan):
# CAKE=240 ; BUD=200 ; PZZA=150
stock_helper_with_plan.sell_rsus("CAKE", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_espp("BUD", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_stockoptions("PZZA", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
stock_helper_with_plan.sell_stockoptions(1, "PZZA", 50, date(2021, 8, 2), sell_price=123, fees=0, currency="USD")
assert stock_helper_with_plan.rsus["CAKE"][0].available == 190
assert stock_helper_with_plan.espp_stocks["BUD"][0].available == 150
assert stock_helper_with_plan.stock_options["PZZA"][0].available == 100
Expand Down

0 comments on commit e484de2

Please sign in to comment.