Last active
November 30, 2025 17:34
-
-
Save kamranahmedse/475b0b4dbbbdb8953656c4eba3ca525e to your computer and use it in GitHub Desktop.
Basic implementation of investment portfolio system
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
| from abc import ABC, abstractmethod | |
| import csv | |
| import numpy as np | |
| class Investment(ABC): | |
| def __init__(self): | |
| self._name = "" | |
| self._invested_amount = 0.0 | |
| self._return_rate = 0.0 | |
| self._risk_level = "" | |
| self._type = "Investment" | |
| @abstractmethod | |
| def calculate_return(self, years): | |
| pass | |
| @abstractmethod | |
| def display_details(self): | |
| pass | |
| def get_name(self): | |
| return self._name | |
| def get_amount(self): | |
| return self._invested_amount | |
| def get_return_rate(self): | |
| return self._return_rate | |
| def get_risk(self): | |
| return self._risk_level | |
| def get_type(self): | |
| return self._type | |
| def set_name(self, name): | |
| self._name = name | |
| def set_amount(self, amount): | |
| if amount < 0: | |
| raise ValueError("Amount cannot be negative") | |
| self._invested_amount = amount | |
| def set_return_rate(self, rate): | |
| self._return_rate = rate | |
| def set_risk(self, risk): | |
| if risk not in ["Low", "Medium", "High"]: | |
| raise ValueError("Risk must be Low, Medium, or High") | |
| self._risk_level = risk | |
| def __str__(self): | |
| return f"{self._name}: Rs. {self._invested_amount} ({self._return_rate}% return, {self._risk_level} risk)" | |
| class SavingsAccount(Investment): | |
| def __init__(self): | |
| super().__init__() | |
| self._bank_name = "" | |
| def calculate_return(self, years): | |
| profit = self._invested_amount * (self._return_rate/100) * years | |
| return profit | |
| def display_details(self): | |
| print(f"\n--- Bank Savings Account ---") | |
| print(f"Account Name: {self._name}") | |
| print(f"Bank: {self._bank_name}") | |
| print(f"Amount Deposited: Rs. {self._invested_amount:.2f}") | |
| print(f"Annual Interest: {self._return_rate}%") | |
| print(f"Risk Level: {self._risk_level}") | |
| def get_bank_name(self): | |
| return self._bank_name | |
| def set_bank_name(self, bank): | |
| self._bank_name = bank | |
| class FixedDeposit(Investment): | |
| def __init__(self): | |
| super().__init__() | |
| self._term_years = 0 | |
| def calculate_return(self, years): | |
| if self._term_years > 0: | |
| actual_years = min(years, self._term_years) | |
| else: | |
| actual_years = years | |
| profit = self._invested_amount * (self._return_rate/100) * actual_years | |
| return profit | |
| def display_details(self): | |
| print(f"\n--- Fixed Deposit ---") | |
| print(f"FD Name: {self._name}") | |
| print(f"Term: {self._term_years} years") | |
| print(f"Amount Deposited: Rs. {self._invested_amount:.2f}") | |
| print(f"Annual Interest: {self._return_rate}%") | |
| print(f"Risk Level: {self._risk_level}") | |
| def get_term_years(self): | |
| return self._term_years | |
| def set_term_years(self, years): | |
| if years < 0: | |
| raise ValueError("Term years cannot be negative") | |
| self._term_years = years | |
| class Gold(Investment): | |
| def __init__(self): | |
| super().__init__() | |
| self._weight_grams = 0.0 | |
| def calculate_return(self, years): | |
| profit = self._invested_amount * (self._return_rate/100) * years | |
| return profit | |
| def display_details(self): | |
| print(f"\n--- Gold Investment ---") | |
| print(f"Description: {self._name}") | |
| print(f"Weight: {self._weight_grams} grams") | |
| print(f"Purchase Amount: Rs. {self._invested_amount:.2f}") | |
| print(f"Annual Price Increase: {self._return_rate}%") | |
| print(f"Risk Level: {self._risk_level}") | |
| def get_weight_grams(self): | |
| return self._weight_grams | |
| def set_weight_grams(self, weight): | |
| if weight < 0: | |
| raise ValueError("Weight cannot be negative") | |
| self._weight_grams = weight | |
| class BankData: | |
| SAVINGS_RATES = { | |
| "HBL": 12.0, | |
| "UBL": 11.0, | |
| "MCB": 10.0, | |
| "Allied Bank": 11.5, | |
| "Meezan Bank": 12.5 | |
| } | |
| FIXED_DEPOSIT_RATES = { | |
| "HBL": 13.0, | |
| "UBL": 12.5, | |
| "MCB": 12.0, | |
| "Allied Bank": 13.5, | |
| "Meezan Bank": 14.0 | |
| } | |
| GOLD_RATE_PER_GRAM = 18500.0 | |
| @staticmethod | |
| def get_savings_rate(bank): | |
| return BankData.SAVINGS_RATES.get(bank, 0) | |
| @staticmethod | |
| def get_fd_rate(bank): | |
| return BankData.FIXED_DEPOSIT_RATES.get(bank, 0) | |
| class MarketData: | |
| STOCKS = { | |
| "Apple": 185.50, | |
| "Google": 142.30, | |
| "Tesla": 248.75, | |
| "Microsoft": 378.90, | |
| "Amazon": 156.20, | |
| "Meta": 485.60, | |
| "Netflix": 612.40 | |
| } | |
| MUTUAL_FUNDS = { | |
| "Vanguard S&P 500": 428.50, | |
| "Fidelity Growth": 156.80, | |
| "T. Rowe Price": 89.30, | |
| "BlackRock Equity": 234.60, | |
| "JP Morgan Balanced": 125.40 | |
| } | |
| CRYPTOCURRENCIES = { | |
| "Bitcoin": 45000.00, | |
| "Ethereum": 2400.00, | |
| "Cardano": 0.65, | |
| "Solana": 110.00, | |
| "Polkadot": 7.50, | |
| "Ripple": 0.55 | |
| } | |
| @staticmethod | |
| def get_stock_price(name): | |
| return MarketData.STOCKS.get(name, 0) | |
| @staticmethod | |
| def get_mutual_fund_price(name): | |
| return MarketData.MUTUAL_FUNDS.get(name, 0) | |
| @staticmethod | |
| def get_crypto_price(name): | |
| return MarketData.CRYPTOCURRENCIES.get(name, 0) | |
| class Stock(Investment): | |
| def __init__(self): | |
| super().__init__() | |
| self._quantity = 0 | |
| self._purchase_price = 0.0 | |
| self._current_price = 0.0 | |
| self._type = "Stock" | |
| def calculate_return(self, years): | |
| current_value = self._quantity * self._current_price | |
| profit = current_value - self._invested_amount | |
| return profit | |
| def display_details(self): | |
| current_value = self._quantity * self._current_price | |
| profit = current_value - self._invested_amount | |
| if self._invested_amount > 0: | |
| return_pct = (profit / self._invested_amount * 100) | |
| else: | |
| return_pct = 0 | |
| print(f"\n--- Stock Investment ---") | |
| print(f"Company: {self._name}") | |
| print(f"Quantity: {self._quantity} shares") | |
| print(f"Purchase Price: Rs. {self._purchase_price:.2f} per share") | |
| print(f"Current Price: Rs. {self._current_price:.2f} per share") | |
| print(f"Amount Invested: Rs. {self._invested_amount:.2f}") | |
| print(f"Current Value: Rs. {current_value:.2f}") | |
| print(f"Profit/Loss: Rs. {profit:.2f}") | |
| print(f"Return: {return_pct:.2f}%") | |
| print(f"Risk Level: {self._risk_level}") | |
| def get_quantity(self): | |
| return self._quantity | |
| def set_quantity(self, quantity): | |
| self._quantity = quantity | |
| def get_purchase_price(self): | |
| return self._purchase_price | |
| def set_purchase_price(self, price): | |
| self._purchase_price = price | |
| def get_current_price(self): | |
| return self._current_price | |
| def set_current_price(self, price): | |
| self._current_price = price | |
| def update_current_price(self): | |
| self._current_price = MarketData.get_stock_price(self._name) | |
| def get_current_value(self): | |
| return self._quantity * self._current_price | |
| class MutualFund(Investment): | |
| def __init__(self): | |
| super().__init__() | |
| self._units = 0 | |
| self._purchase_price = 0.0 | |
| self._current_price = 0.0 | |
| self._type = "MutualFund" | |
| def calculate_return(self, years): | |
| current_value = self._units * self._current_price | |
| profit = current_value - self._invested_amount | |
| return profit | |
| def display_details(self): | |
| current_value = self._units * self._current_price | |
| profit = current_value - self._invested_amount | |
| if self._invested_amount > 0: | |
| return_pct = (profit / self._invested_amount * 100) | |
| else: | |
| return_pct = 0 | |
| print(f"\n--- Mutual Fund Investment ---") | |
| print(f"Fund Name: {self._name}") | |
| print(f"Units: {self._units}") | |
| print(f"Purchase Price: Rs. {self._purchase_price:.2f} per unit") | |
| print(f"Current Price: Rs. {self._current_price:.2f} per unit") | |
| print(f"Amount Invested: Rs. {self._invested_amount:.2f}") | |
| print(f"Current Value: Rs. {current_value:.2f}") | |
| print(f"Profit/Loss: Rs. {profit:.2f}") | |
| print(f"Return: {return_pct:.2f}%") | |
| print(f"Risk Level: {self._risk_level}") | |
| def get_units(self): | |
| return self._units | |
| def set_units(self, units): | |
| self._units = units | |
| def get_purchase_price(self): | |
| return self._purchase_price | |
| def set_purchase_price(self, price): | |
| self._purchase_price = price | |
| def get_current_price(self): | |
| return self._current_price | |
| def set_current_price(self, price): | |
| self._current_price = price | |
| def update_current_price(self): | |
| self._current_price = MarketData.get_mutual_fund_price(self._name) | |
| def get_current_value(self): | |
| return self._units * self._current_price | |
| class Cryptocurrency(Investment): | |
| def __init__(self): | |
| super().__init__() | |
| self._quantity = 0.0 | |
| self._purchase_price = 0.0 | |
| self._current_price = 0.0 | |
| self._type = "Cryptocurrency" | |
| def calculate_return(self, years): | |
| current_value = self._quantity * self._current_price | |
| profit = current_value - self._invested_amount | |
| return profit | |
| def display_details(self): | |
| current_value = self._quantity * self._current_price | |
| profit = current_value - self._invested_amount | |
| if self._invested_amount > 0: | |
| return_pct = profit / self._invested_amount * 100 | |
| else: | |
| return_pct = 0 | |
| print(f"\n--- Cryptocurrency Investment ---") | |
| print(f"Crypto: {self._name}") | |
| print(f"Quantity: {self._quantity:.6f} coins") | |
| print(f"Purchase Price: Rs. {self._purchase_price:.2f} per coin") | |
| print(f"Current Price: Rs. {self._current_price:.2f} per coin") | |
| print(f"Amount Invested: Rs. {self._invested_amount:.2f}") | |
| print(f"Current Value: Rs. {current_value:.2f}") | |
| print(f"Profit/Loss: Rs. {profit:.2f}") | |
| print(f"Return: {return_pct:.2f}%") | |
| print(f"Risk Level: {self._risk_level}") | |
| def get_quantity(self): | |
| return self._quantity | |
| def set_quantity(self, quantity): | |
| self._quantity = quantity | |
| def get_purchase_price(self): | |
| return self._purchase_price | |
| def set_purchase_price(self, price): | |
| self._purchase_price = price | |
| def get_current_price(self): | |
| return self._current_price | |
| def set_current_price(self, price): | |
| self._current_price = price | |
| def update_current_price(self): | |
| self._current_price = MarketData.get_crypto_price(self._name) | |
| def get_current_value(self): | |
| return self._quantity * self._current_price | |
| class User: | |
| def __init__(self): | |
| self._user_id = "" | |
| self._full_name = "" | |
| self._email = "" | |
| self._password = "" | |
| self._balance = 0.0 | |
| def register(self): | |
| print(f"\n✓ User {self._full_name} registered successfully!") | |
| print(f"User ID: {self._user_id}") | |
| print(f"Email: {self._email}") | |
| def login(self, user_id, password): | |
| if self._user_id == user_id and self._password == password: | |
| print(f"\n✓ Welcome back, {self._full_name}!") | |
| return True | |
| else: | |
| print("\n✗ Invalid credentials") | |
| return False | |
| def get_user_id(self): | |
| return self._user_id | |
| def get_name(self): | |
| return self._full_name | |
| def get_email(self): | |
| return self._email | |
| def set_user_id(self, user_id): | |
| if not user_id or len(user_id) == 0: | |
| raise ValueError("User ID cannot be empty") | |
| self._user_id = user_id | |
| def set_name(self, name): | |
| if not name or len(name) == 0: | |
| raise ValueError("Name cannot be empty") | |
| self._full_name = name | |
| def set_email(self, email): | |
| if "@" not in email: | |
| raise ValueError("Invalid email format") | |
| self._email = email | |
| def set_password(self, password): | |
| if not password or len(password) == 0: | |
| raise ValueError("Password cannot be empty") | |
| self._password = password | |
| def update_profile(self): | |
| print(f"\n=== Profile Updated ===") | |
| print(f"Name: {self._full_name}") | |
| print(f"Email: {self._email}") | |
| def deposit_money(self, amount): | |
| if amount <= 0: | |
| raise ValueError("Deposit amount must be positive") | |
| self._balance += amount | |
| print(f"\n✓ Rs. {amount:.2f} deposited successfully!") | |
| print(f"Current Balance: Rs. {self._balance:.2f}") | |
| def get_balance(self): | |
| return self._balance | |
| def deduct_balance(self, amount): | |
| if amount > self._balance: | |
| raise ValueError("Insufficient balance") | |
| self._balance -= amount | |
| class Portfolio: | |
| def __init__(self): | |
| self._owner = None | |
| self._investments = [] | |
| self._total_value = 0.0 | |
| def add_investment(self, investment): | |
| self._investments.append(investment) | |
| print(f"✓ Added {investment.get_name()} to portfolio") | |
| def remove_investment(self, name): | |
| for inv in self._investments: | |
| if inv.get_name() == name: | |
| self._investments.remove(inv) | |
| print(f"✓ Removed {name} from portfolio") | |
| return | |
| print(f"✗ Investment {name} not found") | |
| def view_all(self): | |
| if not self._investments: | |
| print("\nNo investments in portfolio") | |
| return | |
| print(f"\n{'='*60}") | |
| if self._owner: | |
| owner_name = self._owner.get_name() | |
| else: | |
| owner_name = 'Unknown' | |
| print(f"Portfolio of {owner_name}") | |
| print(f"{'='*60}") | |
| i = 1 | |
| for inv in self._investments: | |
| inv_type = inv.get_type() | |
| if inv_type == "Stock" or inv_type == "MutualFund" or inv_type == "Cryptocurrency": | |
| inv.update_current_price() | |
| current_value = inv.get_current_value() | |
| profit = current_value - inv.get_amount() | |
| if inv.get_amount() > 0: | |
| return_pct = profit / inv.get_amount() * 100 | |
| else: | |
| return_pct = 0 | |
| inv.set_return_rate(return_pct) | |
| print(f"\n{i}. {inv}") | |
| inv.display_details() | |
| i = i + 1 | |
| def calculate_total(self): | |
| total = 0 | |
| for inv in self._investments: | |
| inv_type = inv.get_type() | |
| if inv_type == "Stock" or inv_type == "MutualFund" or inv_type == "Cryptocurrency": | |
| inv.update_current_price() | |
| total = total + inv.get_current_value() | |
| else: | |
| total = total + inv.get_amount() | |
| self._total_value = total | |
| return total | |
| def get_investments(self): | |
| return self._investments | |
| def get_owner(self): | |
| return self._owner | |
| def set_owner(self, user): | |
| self._owner = user | |
| def calculate_statistics(self): | |
| if not self._investments: | |
| print("\nNo investments to analyze") | |
| return | |
| print("\n=== Portfolio Statistics (Using NumPy) ===") | |
| for inv in self._investments: | |
| inv_type = inv.get_type() | |
| if inv_type == "Stock" or inv_type == "MutualFund" or inv_type == "Cryptocurrency": | |
| inv.update_current_price() | |
| current_value = inv.get_current_value() | |
| profit = current_value - inv.get_amount() | |
| if inv.get_amount() > 0: | |
| return_pct = profit / inv.get_amount() * 100 | |
| else: | |
| return_pct = 0 | |
| inv.set_return_rate(return_pct) | |
| returns = np.array([inv.get_return_rate() for inv in self._investments]) | |
| amounts = np.array([inv.get_amount() for inv in self._investments]) | |
| avg_return = np.mean(returns) | |
| total_invested = np.sum(amounts) | |
| risk_std = np.std(returns) | |
| max_return = np.max(returns) | |
| min_return = np.min(returns) | |
| print(f"Total Investments: {len(self._investments)}") | |
| print(f"Total Amount Invested: Rs. {total_invested:.2f}") | |
| print(f"Average Return Rate: {avg_return:.2f}%") | |
| print(f"Return Std Deviation (Risk): {risk_std:.2f}%") | |
| print(f"Highest Return: {max_return:.2f}%") | |
| print(f"Lowest Return: {min_return:.2f}%") | |
| def calculate_average_return(self): | |
| if not self._investments: | |
| return 0 | |
| returns = [inv.get_return_rate() for inv in self._investments] | |
| return sum(returns) / len(returns) | |
| def calculate_risk(self): | |
| if not self._investments: | |
| return "No Risk" | |
| risk_counts = {"Low": 0, "Medium": 0, "High": 0} | |
| for inv in self._investments: | |
| risk = inv.get_risk() | |
| if risk in risk_counts: | |
| risk_counts[risk] += 1 | |
| if risk_counts["High"] > len(self._investments) / 2: | |
| return "High" | |
| elif risk_counts["Low"] > len(self._investments) / 2: | |
| return "Low" | |
| else: | |
| return "Medium" | |
| def find_highest_return(self): | |
| if not self._investments: | |
| return None | |
| return max(self._investments, key=lambda inv: inv.get_return_rate()) | |
| def find_lowest_risk(self): | |
| if not self._investments: | |
| return None | |
| risk_priority = {"Low": 1, "Medium": 2, "High": 3} | |
| return min(self._investments, key=lambda inv: risk_priority.get(inv.get_risk(), 4)) | |
| def find_best_recursive(self, index=0, best=None): | |
| if index == len(self._investments): | |
| return best | |
| current = self._investments[index] | |
| if best is None or current.get_return_rate() > best.get_return_rate(): | |
| best = current | |
| return self.find_best_recursive(index + 1, best) | |
| def sum_returns_recursive(self, index=0, total=0): | |
| if index == len(self._investments): | |
| return total | |
| total += self._investments[index].get_return_rate() | |
| return self.sum_returns_recursive(index + 1, total) | |
| def count_by_risk_recursive(self, risk_level, index=0, count=0): | |
| if index == len(self._investments): | |
| return count | |
| if self._investments[index].get_risk() == risk_level: | |
| count += 1 | |
| return self.count_by_risk_recursive(risk_level, index + 1, count) | |
| class FileHandler: | |
| def save_portfolio_csv(self, portfolio, filename): | |
| try: | |
| with open(filename, 'w', newline='') as f: | |
| writer = csv.writer(f) | |
| writer.writerow(['Name', 'Type', 'Amount', 'Return Rate', 'Risk']) | |
| for inv in portfolio.get_investments(): | |
| writer.writerow([ | |
| inv.get_name(), | |
| type(inv).__name__, | |
| inv.get_amount(), | |
| inv.get_return_rate(), | |
| inv.get_risk() | |
| ]) | |
| print(f"✓ Portfolio saved to {filename}") | |
| except Exception as e: | |
| print(f"✗ Error saving: {e}") | |
| def print_portfolio_csv(self, filename): | |
| try: | |
| with open(filename, 'r') as f: | |
| reader = csv.reader(f) | |
| print(f"\n=== Contents of {filename} ===") | |
| for row in reader: | |
| print(" | ".join(row)) | |
| print(f"✓ File read successfully") | |
| except FileNotFoundError: | |
| print(f"✗ File {filename} not found") | |
| except Exception as e: | |
| print(f"✗ Error reading file: {e}") | |
| class ReportGenerator: | |
| def print_summary(self, portfolio): | |
| print("\n" + "="*50) | |
| print("PORTFOLIO SUMMARY") | |
| print("="*50) | |
| owner = portfolio.get_owner() | |
| if owner: | |
| print(f"Owner: {owner.get_name()}") | |
| total = portfolio.calculate_total() | |
| print(f"Total Value: Rs. {total:.2f}") | |
| print(f"Number of Investments: {len(portfolio.get_investments())}") | |
| def print_best_investment(self, portfolio): | |
| print("\n=== Best Investment ===") | |
| best = portfolio.find_best_recursive() | |
| if best: | |
| print(f"Name: {best.get_name()}") | |
| print(f"Return Rate: {best.get_return_rate()}%") | |
| print(f"Amount: Rs. {best.get_amount():.2f}") | |
| else: | |
| print("No investments found") | |
| class Validator: | |
| @staticmethod | |
| def validate_email(email): | |
| if "@" in email and "." in email: | |
| return True | |
| return False | |
| @staticmethod | |
| def validate_amount(amount): | |
| try: | |
| amount_float = float(amount) | |
| return amount_float >= 0 | |
| except: | |
| return False | |
| @staticmethod | |
| def validate_risk(risk): | |
| return risk in ["Low", "Medium", "High"] | |
| def display_menu(user=None): | |
| print("\n" + "="*50) | |
| print("INVESTMENT PORTFOLIO SYSTEM - MENU") | |
| print("="*50) | |
| if user: | |
| print(f"Account Balance: Rs. {user.get_balance():.2f}") | |
| print("="*50) | |
| print("1. Create User Account") | |
| print("2. Deposit Money") | |
| print("3. Add Savings Account") | |
| print("4. Add Fixed Deposit") | |
| print("5. Add Gold Investment") | |
| print("6. Buy/Sell Stocks") | |
| print("7. Buy/Sell Mutual Funds") | |
| print("8. Buy/Sell Cryptocurrency") | |
| print("9. View Portfolio") | |
| print("10. Calculate Portfolio Statistics") | |
| print("11. Find Best Investment (Recursion)") | |
| print("12. Save Portfolio to CSV") | |
| print("13. View CSV File") | |
| print("14. Generate Report") | |
| print("0. Exit") | |
| print("="*50) | |
| def main(): | |
| print("="*50) | |
| print("WELCOME TO PORTFOLIO MANAGEMENT SYSTEM") | |
| print("="*50) | |
| print("Track and manage your investments including bank") | |
| print("accounts, fixed deposits, gold, and businesses.") | |
| user = None | |
| portfolio = None | |
| while True: | |
| display_menu(user) | |
| try: | |
| choice = input("\nEnter your choice (0-14): ").strip() | |
| if choice == "1": | |
| print("\n=== CREATE USER ===") | |
| user_id = input("Enter User ID: ") | |
| name = input("Enter Name: ") | |
| email = input("Enter Email: ") | |
| password = input("Enter Password: ") | |
| if not Validator.validate_email(email): | |
| print("✗ Invalid email format!") | |
| continue | |
| user = User() | |
| user.set_user_id(user_id) | |
| user.set_name(name) | |
| user.set_email(email) | |
| user.set_password(password) | |
| user.register() | |
| portfolio = Portfolio() | |
| portfolio.set_owner(user) | |
| print(f"✓ Portfolio created for {name}") | |
| elif choice == "2": | |
| if user is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| print("\n=== DEPOSIT MONEY ===") | |
| amount = float(input("Enter amount to deposit: Rs. ")) | |
| user.deposit_money(amount) | |
| elif choice == "3": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| print("\n=== ADD SAVINGS ACCOUNT ===") | |
| print(f"Available Balance: Rs. {user.get_balance():.2f}") | |
| print("\nAvailable Banks:") | |
| i = 1 | |
| for bank in BankData.SAVINGS_RATES: | |
| rate = BankData.SAVINGS_RATES[bank] | |
| print(f"{i}. {bank}: {rate}% annual return") | |
| i = i + 1 | |
| bank_num = int(input("\nSelect bank number: ")) | |
| banks = list(BankData.SAVINGS_RATES.keys()) | |
| if 1 <= bank_num <= len(banks): | |
| bank = banks[bank_num - 1] | |
| return_rate = BankData.SAVINGS_RATES[bank] | |
| amount = float(input("Enter deposit amount: Rs. ")) | |
| if not Validator.validate_amount(amount): | |
| print("✗ Invalid amount!") | |
| continue | |
| if amount > user.get_balance(): | |
| print(f"✗ Insufficient balance! You have Rs. {user.get_balance():.2f}") | |
| continue | |
| annual_return = amount * (return_rate / 100) | |
| final_amount = amount + annual_return | |
| savings = SavingsAccount() | |
| savings.set_name(f"{bank} Savings Account") | |
| savings.set_bank_name(bank) | |
| savings.set_amount(amount) | |
| savings.set_return_rate(return_rate) | |
| savings.set_risk("Low") | |
| portfolio.add_investment(savings) | |
| user.deduct_balance(amount) | |
| print(f"\n✓ Savings Account Created!") | |
| print(f"Bank: {bank}") | |
| print(f"Deposit Amount: Rs. {amount:.2f}") | |
| print(f"Annual Return Rate: {return_rate}%") | |
| print(f"Annual Return: Rs. {annual_return:.2f}") | |
| print(f"Final Amount (after 1 year): Rs. {final_amount:.2f}") | |
| print(f"Remaining Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| elif choice == "4": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| print("\n=== ADD FIXED DEPOSIT ===") | |
| print(f"Available Balance: Rs. {user.get_balance():.2f}") | |
| print("\nAvailable Banks:") | |
| i = 1 | |
| for bank in BankData.FIXED_DEPOSIT_RATES: | |
| rate = BankData.FIXED_DEPOSIT_RATES[bank] | |
| print(f"{i}. {bank}: {rate}% annual return") | |
| i = i + 1 | |
| bank_num = int(input("\nSelect bank number: ")) | |
| banks = list(BankData.FIXED_DEPOSIT_RATES.keys()) | |
| if 1 <= bank_num <= len(banks): | |
| bank = banks[bank_num - 1] | |
| return_rate = BankData.FIXED_DEPOSIT_RATES[bank] | |
| term = int(input("Enter term in years: ")) | |
| amount = float(input("Enter deposit amount: Rs. ")) | |
| if not Validator.validate_amount(amount): | |
| print("✗ Invalid amount!") | |
| continue | |
| if amount > user.get_balance(): | |
| print(f"✗ Insufficient balance! You have Rs. {user.get_balance():.2f}") | |
| continue | |
| annual_return = amount * (return_rate / 100) | |
| total_return = annual_return * term | |
| final_amount = amount + total_return | |
| fd = FixedDeposit() | |
| fd.set_name(f"{bank} Fixed Deposit") | |
| fd.set_term_years(term) | |
| fd.set_amount(amount) | |
| fd.set_return_rate(return_rate) | |
| fd.set_risk("Low") | |
| portfolio.add_investment(fd) | |
| user.deduct_balance(amount) | |
| print(f"\n✓ Fixed Deposit Created!") | |
| print(f"Bank: {bank}") | |
| print(f"Deposit Amount: Rs. {amount:.2f}") | |
| print(f"Term: {term} years") | |
| print(f"Annual Return Rate: {return_rate}%") | |
| print(f"Annual Return: Rs. {annual_return:.2f}") | |
| print(f"Total Return (after {term} years): Rs. {total_return:.2f}") | |
| print(f"Final Amount: Rs. {final_amount:.2f}") | |
| print(f"Remaining Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| elif choice == "5": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| print("\n=== ADD GOLD INVESTMENT ===") | |
| print(f"Available Balance: Rs. {user.get_balance():.2f}") | |
| print(f"\n💰 Current Gold Rate: Rs. {BankData.GOLD_RATE_PER_GRAM:.2f} per gram") | |
| name = input("\nEnter description (e.g., Gold Bangles, Gold Coins): ") | |
| weight = float(input("Enter weight in grams: ")) | |
| amount = weight * BankData.GOLD_RATE_PER_GRAM | |
| print(f"\nCalculated Amount: {weight} grams × Rs. {BankData.GOLD_RATE_PER_GRAM:.2f} = Rs. {amount:.2f}") | |
| if not Validator.validate_amount(amount): | |
| print("✗ Invalid amount!") | |
| continue | |
| if amount > user.get_balance(): | |
| print(f"✗ Insufficient balance! You need Rs. {amount:.2f}") | |
| continue | |
| expected_increase = 8.0 | |
| annual_return = amount * (expected_increase / 100) | |
| final_amount = amount + annual_return | |
| gold = Gold() | |
| gold.set_name(name) | |
| gold.set_weight_grams(weight) | |
| gold.set_amount(amount) | |
| gold.set_return_rate(expected_increase) | |
| gold.set_risk("Medium") | |
| portfolio.add_investment(gold) | |
| user.deduct_balance(amount) | |
| print(f"\n✓ Gold Investment Created!") | |
| print(f"Description: {name}") | |
| print(f"Weight: {weight} grams") | |
| print(f"Purchase Rate: Rs. {BankData.GOLD_RATE_PER_GRAM:.2f} per gram") | |
| print(f"Total Amount: Rs. {amount:.2f}") | |
| print(f"Expected Annual Increase: {expected_increase}%") | |
| print(f"Expected Annual Return: Rs. {annual_return:.2f}") | |
| print(f"Expected Value (after 1 year): Rs. {final_amount:.2f}") | |
| print(f"Remaining Balance: Rs. {user.get_balance():.2f}") | |
| elif choice == "6": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| print("\n=== STOCKS MARKET ===") | |
| print(f"Available Balance: Rs. {user.get_balance():.2f}") | |
| print("\nAvailable Stocks:") | |
| i = 1 | |
| for company in MarketData.STOCKS: | |
| price = MarketData.STOCKS[company] | |
| print(f"{i}. {company}: Rs. {price:.2f} per share") | |
| i = i + 1 | |
| action = input("\nEnter 'B' to Buy or 'S' to Sell: ").strip().upper() | |
| if action == 'B': | |
| company_num = int(input("Select company number: ")) | |
| companies = list(MarketData.STOCKS.keys()) | |
| if 1 <= company_num <= len(companies): | |
| company = companies[company_num - 1] | |
| price = MarketData.STOCKS[company] | |
| quantity = int(input(f"Enter quantity to buy: ")) | |
| total_cost = price * quantity | |
| if total_cost > user.get_balance(): | |
| print(f"✗ Insufficient balance! You need Rs. {total_cost:.2f}") | |
| continue | |
| stock = Stock() | |
| stock.set_name(company) | |
| stock.set_quantity(quantity) | |
| stock.set_purchase_price(price) | |
| stock.set_current_price(price) | |
| stock.set_amount(total_cost) | |
| stock.set_risk("High") | |
| profit = 0 | |
| return_pct = 0 | |
| stock.set_return_rate(return_pct) | |
| portfolio.add_investment(stock) | |
| user.deduct_balance(total_cost) | |
| print(f"\n✓ Purchased {quantity} shares of {company}") | |
| print(f"Total Cost: Rs. {total_cost:.2f}") | |
| print(f"Remaining Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| elif action == 'S': | |
| stocks_list = [] | |
| for inv in portfolio.get_investments(): | |
| if inv.get_type() == "Stock": | |
| stocks_list.append(inv) | |
| if not stocks_list: | |
| print("\n✗ No stocks to sell!") | |
| continue | |
| print("\nYour Stocks:") | |
| i = 1 | |
| for stock in stocks_list: | |
| stock.update_current_price() | |
| current_value = stock.get_current_value() | |
| profit = current_value - stock.get_amount() | |
| print(f"{i}. {stock.get_name()}: {stock.get_quantity()} shares, Current Value: Rs. {current_value:.2f}, P/L: Rs. {profit:.2f}") | |
| i = i + 1 | |
| stock_num = int(input("\nSelect stock number to sell: ")) | |
| if 1 <= stock_num <= len(stocks_list): | |
| stock = stocks_list[stock_num - 1] | |
| quantity = int(input(f"Enter quantity to sell (max {stock.get_quantity()}): ")) | |
| if quantity > stock.get_quantity(): | |
| print("✗ Not enough shares!") | |
| continue | |
| stock.update_current_price() | |
| sale_value = quantity * stock.get_current_price() | |
| purchase_value = quantity * stock.get_purchase_price() | |
| profit = sale_value - purchase_value | |
| if purchase_value > 0: | |
| return_pct = profit / purchase_value * 100 | |
| else: | |
| return_pct = 0 | |
| if quantity == stock.get_quantity(): | |
| portfolio.remove_investment(stock.get_name()) | |
| else: | |
| stock.set_quantity(stock.get_quantity() - quantity) | |
| new_amount = stock.get_quantity() * stock.get_purchase_price() | |
| stock.set_amount(new_amount) | |
| user._balance += sale_value | |
| print(f"\n✓ Sold {quantity} shares of {stock.get_name()}") | |
| print(f"Sale Value: Rs. {sale_value:.2f}") | |
| print(f"Profit/Loss: Rs. {profit:.2f}") | |
| print(f"Return: {return_pct:.2f}%") | |
| print(f"Current Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| else: | |
| print("✗ Invalid action!") | |
| elif choice == "7": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| print("\n=== MUTUAL FUNDS MARKET ===") | |
| print(f"Available Balance: Rs. {user.get_balance():.2f}") | |
| print("\nAvailable Mutual Funds:") | |
| i = 1 | |
| for fund in MarketData.MUTUAL_FUNDS: | |
| price = MarketData.MUTUAL_FUNDS[fund] | |
| print(f"{i}. {fund}: Rs. {price:.2f} per unit") | |
| i = i + 1 | |
| action = input("\nEnter 'B' to Buy or 'S' to Sell: ").strip().upper() | |
| if action == 'B': | |
| fund_num = int(input("Select fund number: ")) | |
| funds = list(MarketData.MUTUAL_FUNDS.keys()) | |
| if 1 <= fund_num <= len(funds): | |
| fund = funds[fund_num - 1] | |
| price = MarketData.MUTUAL_FUNDS[fund] | |
| units = int(input(f"Enter units to buy: ")) | |
| total_cost = price * units | |
| if total_cost > user.get_balance(): | |
| print(f"✗ Insufficient balance! You need Rs. {total_cost:.2f}") | |
| continue | |
| mf = MutualFund() | |
| mf.set_name(fund) | |
| mf.set_units(units) | |
| mf.set_purchase_price(price) | |
| mf.set_current_price(price) | |
| mf.set_amount(total_cost) | |
| mf.set_risk("Medium") | |
| return_pct = 0 | |
| mf.set_return_rate(return_pct) | |
| portfolio.add_investment(mf) | |
| user.deduct_balance(total_cost) | |
| print(f"\n✓ Purchased {units} units of {fund}") | |
| print(f"Total Cost: Rs. {total_cost:.2f}") | |
| print(f"Remaining Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| elif action == 'S': | |
| mf_list = [] | |
| for inv in portfolio.get_investments(): | |
| if inv.get_type() == "MutualFund": | |
| mf_list.append(inv) | |
| if not mf_list: | |
| print("\n✗ No mutual funds to sell!") | |
| continue | |
| print("\nYour Mutual Funds:") | |
| i = 1 | |
| for mf in mf_list: | |
| mf.update_current_price() | |
| current_value = mf.get_current_value() | |
| profit = current_value - mf.get_amount() | |
| print(f"{i}. {mf.get_name()}: {mf.get_units()} units, Current Value: Rs. {current_value:.2f}, P/L: Rs. {profit:.2f}") | |
| i = i + 1 | |
| mf_num = int(input("\nSelect fund number to sell: ")) | |
| if 1 <= mf_num <= len(mf_list): | |
| mf = mf_list[mf_num - 1] | |
| units = int(input(f"Enter units to sell (max {mf.get_units()}): ")) | |
| if units > mf.get_units(): | |
| print("✗ Not enough units!") | |
| continue | |
| mf.update_current_price() | |
| sale_value = units * mf.get_current_price() | |
| purchase_value = units * mf.get_purchase_price() | |
| profit = sale_value - purchase_value | |
| if purchase_value > 0: | |
| return_pct = profit / purchase_value * 100 | |
| else: | |
| return_pct = 0 | |
| if units == mf.get_units(): | |
| portfolio.remove_investment(mf.get_name()) | |
| else: | |
| mf.set_units(mf.get_units() - units) | |
| new_amount = mf.get_units() * mf.get_purchase_price() | |
| mf.set_amount(new_amount) | |
| user._balance += sale_value | |
| print(f"\n✓ Sold {units} units of {mf.get_name()}") | |
| print(f"Sale Value: Rs. {sale_value:.2f}") | |
| print(f"Profit/Loss: Rs. {profit:.2f}") | |
| print(f"Return: {return_pct:.2f}%") | |
| print(f"Current Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| else: | |
| print("✗ Invalid action!") | |
| elif choice == "8": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| print("\n=== CRYPTOCURRENCY MARKET ===") | |
| print(f"Available Balance: Rs. {user.get_balance():.2f}") | |
| print("\nAvailable Cryptocurrencies:") | |
| i = 1 | |
| for crypto in MarketData.CRYPTOCURRENCIES: | |
| price = MarketData.CRYPTOCURRENCIES[crypto] | |
| print(f"{i}. {crypto}: Rs. {price:.2f} per coin") | |
| i = i + 1 | |
| action = input("\nEnter 'B' to Buy or 'S' to Sell: ").strip().upper() | |
| if action == 'B': | |
| crypto_num = int(input("Select cryptocurrency number: ")) | |
| cryptos = list(MarketData.CRYPTOCURRENCIES.keys()) | |
| if 1 <= crypto_num <= len(cryptos): | |
| crypto = cryptos[crypto_num - 1] | |
| price = MarketData.CRYPTOCURRENCIES[crypto] | |
| quantity = float(input(f"Enter quantity to buy: ")) | |
| total_cost = price * quantity | |
| if total_cost > user.get_balance(): | |
| print(f"✗ Insufficient balance! You need Rs. {total_cost:.2f}") | |
| continue | |
| cc = Cryptocurrency() | |
| cc.set_name(crypto) | |
| cc.set_quantity(quantity) | |
| cc.set_purchase_price(price) | |
| cc.set_current_price(price) | |
| cc.set_amount(total_cost) | |
| cc.set_risk("High") | |
| return_pct = 0 | |
| cc.set_return_rate(return_pct) | |
| portfolio.add_investment(cc) | |
| user.deduct_balance(total_cost) | |
| print(f"\n✓ Purchased {quantity} coins of {crypto}") | |
| print(f"Total Cost: Rs. {total_cost:.2f}") | |
| print(f"Remaining Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| elif action == 'S': | |
| crypto_list = [] | |
| for inv in portfolio.get_investments(): | |
| if inv.get_type() == "Cryptocurrency": | |
| crypto_list.append(inv) | |
| if not crypto_list: | |
| print("\n✗ No cryptocurrencies to sell!") | |
| continue | |
| print("\nYour Cryptocurrencies:") | |
| i = 1 | |
| for cc in crypto_list: | |
| cc.update_current_price() | |
| current_value = cc.get_current_value() | |
| profit = current_value - cc.get_amount() | |
| print(f"{i}. {cc.get_name()}: {cc.get_quantity():.6f} coins, Current Value: Rs. {current_value:.2f}, P/L: Rs. {profit:.2f}") | |
| i = i + 1 | |
| crypto_num = int(input("\nSelect cryptocurrency number to sell: ")) | |
| if 1 <= crypto_num <= len(crypto_list): | |
| cc = crypto_list[crypto_num - 1] | |
| quantity = float(input(f"Enter quantity to sell (max {cc.get_quantity():.6f}): ")) | |
| if quantity > cc.get_quantity(): | |
| print("✗ Not enough coins!") | |
| continue | |
| cc.update_current_price() | |
| sale_value = quantity * cc.get_current_price() | |
| purchase_value = quantity * cc.get_purchase_price() | |
| profit = sale_value - purchase_value | |
| if purchase_value > 0: | |
| return_pct = profit / purchase_value * 100 | |
| else: | |
| return_pct = 0 | |
| if abs(quantity - cc.get_quantity()) < 0.000001: | |
| portfolio.remove_investment(cc.get_name()) | |
| else: | |
| cc.set_quantity(cc.get_quantity() - quantity) | |
| new_amount = cc.get_quantity() * cc.get_purchase_price() | |
| cc.set_amount(new_amount) | |
| user._balance += sale_value | |
| print(f"\n✓ Sold {quantity} coins of {cc.get_name()}") | |
| print(f"Sale Value: Rs. {sale_value:.2f}") | |
| print(f"Profit/Loss: Rs. {profit:.2f}") | |
| print(f"Return: {return_pct:.2f}%") | |
| print(f"Current Balance: Rs. {user.get_balance():.2f}") | |
| else: | |
| print("✗ Invalid selection!") | |
| else: | |
| print("✗ Invalid action!") | |
| elif choice == "9": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| portfolio.view_all() | |
| print(f"\nTotal Portfolio Value: Rs. {portfolio.calculate_total():.2f}") | |
| elif choice == "10": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| portfolio.calculate_statistics() | |
| elif choice == "11": | |
| if portfolio is None or len(portfolio.get_investments()) == 0: | |
| print("\n✗ No investments in portfolio!") | |
| continue | |
| print("\n=== FIND BEST INVESTMENT (Recursion) ===") | |
| best = portfolio.find_best_recursive() | |
| print(f"Best Investment: {best.get_name()}") | |
| print(f"Return Rate: {best.get_return_rate()}%") | |
| print(f"Amount: Rs. {best.get_amount():.2f}") | |
| low = portfolio.count_by_risk_recursive("Low") | |
| med = portfolio.count_by_risk_recursive("Medium") | |
| high = portfolio.count_by_risk_recursive("High") | |
| print(f"\nRisk Distribution (using recursion):") | |
| print(f"Low: {low}, Medium: {med}, High: {high}") | |
| elif choice == "12": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| filename = input("Enter filename (e.g., portfolio.csv): ") | |
| if not filename.endswith('.csv'): | |
| filename += '.csv' | |
| file_handler = FileHandler() | |
| file_handler.save_portfolio_csv(portfolio, filename) | |
| elif choice == "13": | |
| filename = input("Enter CSV filename to view: ") | |
| if not filename.endswith('.csv'): | |
| filename += '.csv' | |
| file_handler = FileHandler() | |
| file_handler.print_portfolio_csv(filename) | |
| elif choice == "14": | |
| if portfolio is None: | |
| print("\n✗ Please create a user first (Option 1)") | |
| continue | |
| report = ReportGenerator() | |
| report.print_summary(portfolio) | |
| report.print_best_investment(portfolio) | |
| elif choice == "0": | |
| print("\n" + "="*50) | |
| print("Thank you for using Portfolio Management System!") | |
| print("="*50) | |
| break | |
| else: | |
| print("\n✗ Invalid choice! Please enter 0-14") | |
| except ValueError as e: | |
| print(f"\n✗ Invalid input: {e}") | |
| except Exception as e: | |
| print(f"\n✗ Error: {e}") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment