Last active
May 27, 2024 10:29
-
-
Save laserpez/39ccfbb15ac63898a721ecae4f307e51 to your computer and use it in GitHub Desktop.
Average stock price calculator with LIFO strategy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3.10 | |
import csv | |
import argparse | |
from collections import defaultdict | |
BUY = "Buy" | |
SELL = "Sell" | |
class Transaction: | |
def __init__(self, shares, price): | |
self.shares = shares | |
self.price = price | |
def calculate_lifo_average(transactions): | |
portfolios = defaultdict(list) | |
def average_price(stock): | |
purchases = portfolios[stock] | |
total_cost = sum(purchase.shares * purchase.price for purchase in purchases) | |
total_shares = sum(purchase.shares for purchase in purchases) | |
average_price = total_cost / total_shares if total_shares > 0 else 0 | |
return average_price | |
for transaction in reversed(transactions): | |
stock = transaction['stock'] | |
if transaction['type'] == BUY: | |
portfolios[stock].append(Transaction(transaction['shares'], transaction['price'])) | |
elif transaction['type'] == SELL: | |
print(f"{transaction['date']}: [{stock}] Average stock price before Sell: {average_price(stock):.4f} EUR") | |
shares_to_sell = transaction['shares'] | |
while shares_to_sell > 0 and portfolios[stock]: | |
top = portfolios[stock][-1] | |
if top.shares <= shares_to_sell: | |
shares_to_sell -= top.shares | |
portfolios[stock].pop() | |
else: | |
top.shares -= shares_to_sell | |
shares_to_sell = 0 | |
print(f"{transaction['date']}: [{stock}] Average stock price after Sell: {average_price(stock):.4f} EUR") | |
def read_transactions_from_csv(file_path): | |
transactions = [] | |
with open(file_path, mode='r') as file: | |
reader = csv.DictReader(file) | |
for row in reader: | |
transaction = { | |
'date': row[reader.fieldnames[0]], | |
'stock': row['Symbol'], | |
'type': row['Type'], | |
'shares': float(row['Quantity']), | |
'price': float(row['Price']) | |
} | |
transactions.append(transaction) | |
return transactions | |
def main(): | |
parser = argparse.ArgumentParser(description='Calculate stocks average buying price.') | |
parser.add_argument('file_path', type=str, help='The CSV transactions file path') | |
args = parser.parse_args() | |
# read transactions from CSV file | |
transactions = read_transactions_from_csv(args.file_path) | |
# calculate and print average stock price before and after each Sell operation | |
calculate_lifo_average(transactions) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment