from dataclasses import dataclass, field
from typing import List
import pandas as pd
from .transaction import AccountTransaction
[docs]
@dataclass
class Account:
"""
Represents an account with a list of transactions.
"""
name: str
currency: str
transactions: List[AccountTransaction] = field(default_factory=list)
[docs]
def add_transaction(self, transaction: AccountTransaction):
"""
Adds a transaction to the account.
Args:
transaction (AccountTransaction): The transaction to add.
"""
self.transactions.append(transaction)
[docs]
def add_transaction_from_dict(self, transaction_dict: dict):
"""
Adds a transaction to the account from a dictionary.
Args:
transaction_dict (dict): Dictionary containing transaction details.
"""
amount = transaction_dict["total_base"]
if (
transaction_dict["type"] == "sell"
or transaction_dict["type"] == "withdrawal"
):
amount = -amount
transaction = AccountTransaction(
transaction_date=transaction_dict["date"],
transaction_type=transaction_dict["type"],
amount=amount,
description=transaction_dict.get("description", None),
)
self.add_transaction(transaction)
[docs]
def add_transaction_from_assets_dict(self, transaction_dict: dict):
"""
Adds a transaction to the account from a dictionary.
Args:
transaction_dict (dict): Dictionary containing transaction details.
"""
text = ""
type = ""
amount = transaction_dict["total_base"]
if transaction_dict["type"] == "buy":
type = "sell"
text = f"Buy ${transaction_dict['ticker']} asset"
amount = -amount
elif transaction_dict["type"] == "sell":
type = "buy"
text = f"Sell ${transaction_dict['ticker']} asset"
elif transaction_dict["type"] == "dividend":
type = "income"
text = f"Dividend received for ${transaction_dict['ticker']} asset"
else:
raise ValueError(f"Unknown transaction type: {transaction_dict['type']}")
transaction = AccountTransaction(
transaction_date=transaction_dict["date"],
transaction_type=type,
amount=amount,
description=text,
)
self.add_transaction(transaction)
[docs]
def add_transaction_from_split_dict(self, split_dict: dict, amount: float = 0.0):
"""
Adds a transaction to the account from a stock split dictionary.
Args:
split_dict (dict): Dictionary containing split information with keys:
- date: Split date (str)
- ticker: Ticker symbol of the asset
- split_factor: Split ratio as float (e.g., 2.0 for 2:1 split, 0.1 for 1:10 reverse split)
- amount: Amount of the asset affected by the split (default is 0.0)
"""
transaction = AccountTransaction(
transaction_date=split_dict["date"],
transaction_type="buy",
amount=amount,
description=f"Stock split for {split_dict['ticker']} with factor {split_dict['split_factor']}",
)
self.add_transaction(transaction)
[docs]
@classmethod
def to_dataframe(cls, account: "Account") -> pd.DataFrame:
"""
Converts the account transactions to a pandas DataFrame.
Returns:
pd.DataFrame: DataFrame containing the account transactions.
"""
return AccountTransaction.to_dataframe(account.transactions)
[docs]
def get_amount(self) -> float:
"""
Calculates the total amount of all transactions in the account.
Returns:
float: Total amount of all transactions.
"""
return sum(tx.amount for tx in self.transactions)
[docs]
def sort_transactions(self):
"""
Sorts the account transactions by date.
"""
self.transactions.sort(key=lambda x: x.transaction_date)
def __repr__(self):
return f"Account(name={self.name}, currency={self.currency}, transactions={self.transactions})"