mi puoi adattare questo script python e eventualmente migliorarlo sempre creando uno script in python:CONFIG = { # Configurazioni generali 'app_name': 'Finance Analyzer', 'version': '1.0.0', # Configurazioni mercati 'mercati
To improve and adapt your provided script for a financial analysis application, I will take a systematic approach, focusing on enhancing readability, structure, and efficiency. The code will maintain its essential functionalities while addressing potential improvements.
Here’s a refined version of the script:
```python
import logging
import argparse
import pandas as pd
from pathlib import Path
from models.stock import Stock
from models.portfolio import Portfolio
from utils.data_cleaning import pulisci_prezzo
from visualization.charts import visualizza_andamento_titolo, visualizza_confronto_benchmark
from config import CONFIG
# Configuring logging
logging.basicConfig(
level=getattr(logging, CONFIG['log_level']),
format=CONFIG['log_format'],
handlers=[logging.FileHandler(CONFIG['log_file']), logging.StreamHandler()]
)
logger = logging.getLogger(__name__)
def parse_arguments():
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(description='Finance Analyzer')
parser.add_argument('--mode', '-m', choices=['manual', 'excel', 'analyze'], default='manual', help='Execution mode')
parser.add_argument('--input', '-i', help='Input Excel file')
parser.add_argument('--output', '-o', help='Output Excel file')
parser.add_argument('--ticker', '-t', help='Ticker or ISIN to analyze')
parser.add_argument('--quantity', '-q', type=float, default=0, help='Quantity of shares')
parser.add_argument('--price', '-p', type=float, help='Cost price')
parser.add_argument('--chart', '-c', action='store_true', help='Generate chart')
parser.add_argument('--benchmark', '-b', help='Benchmark for comparison')
parser.add_argument('--period', help='Period for analysis (e.g., 1y, 6mo)')
return parser.parse_args()
def manual_input():
"""Handles manual title input."""
portfolio = Portfolio()
print("\n=== FINANCE ANALYZER: MANUAL INPUT ===\n")
while True:
market_choice = input("Choose market: [1] Italy, [2] USA (NASDAQ/NYSE), [Enter] Italy: ").strip() or '1'
market = 'usa' if market_choice == '2' else 'italia'
category_choice = input("Choose category: [1] Income, [2] Sustainability (low risk), [Enter] All: ").strip() or '3'
category = { '1': 'reddito', '2': 'sostenibilità' }.get(category_choice, None)
suggested_stocks = portfolio.suggest_alternatives(category=category, market=market, max_price=50)
print(f"\nSuggested stocks under 50€/$: {', '.join([f'{t['nome']} ({t['ticker']}) - price approx {t['prezzo']}' for t in suggested_stocks])}")
ticker_input = input("Enter ISIN or ticker (or type 'stop' to finish): ").strip()
if ticker_input.lower() == 'stop':
break
try:
stock = Stock(ticker_input)
current_price, currency, price_date = stock.get_current_price()
if current_price is not None:
print(f"Current price for {stock.ticker}: {current_price} {currency} (date: {price_date})")
action = input("Action? Buy (A) or Sell (V): ").strip().lower()
quantity = float(input("Quantity of shares owned: ").strip() or 0)
purchase_date = pd.to_datetime(input("Purchase date (YYYY-MM-DD or DD/MM/YYYY) or leave blank: ").strip(), dayfirst=True, errors='coerce')
cost_price = pulisci_prezzo(input("Purchase price (or leave blank): ").strip())
portfolio.add_position(ticker_input, quantity, cost_price, purchase_date)
analysis = portfolio.analyze_position(stock.ticker)
if analysis:
print_analysis(analysis, quantity)
# Generate chart
if input("\nGenerate a chart? (y/n): ").strip().lower() == 'y':
chart_path = visualizza_andamento_titolo(stock.ticker, period=input("Period (1y, 6mo, 3mo): ").strip() or "1y")
print(f"Chart saved at: {chart_path}")
print("\nTitle added and analyzed.\n-------------------")
except Exception as e:
logger.error(f"Error in manual input: {e}")
print(f"An error occurred: {e}")
return portfolio
def print_analysis(analysis, quantity):
"""Print the results of the analysis for the stock."""
print("\n=== DETAILED STOCK ANALYSIS ===")
print(f"Ticker: {analysis['ticker']}")
print(f"Current price: {analysis['price']['current']} {analysis['price']['currency']}")
if analysis['price']['date']:
print(f"Price date: {analysis['price']['date']}")
if quantity > 0:
print(f"\nPOSITION:")
print(f"Quantity: {analysis['position']['quantity']}")
print(f"Current value: {analysis['position']['value']:.2f}")
print(f"Total cost: {analysis['position']['cost_basis']:.2f}")
print(f"Profit/Loss: {analysis['position']['profit_loss']:.2f} ({analysis['position']['profit_loss_percent']:.2f}%)")
# Further information can be displayed similarly
def process_excel_file(filepath_input, filepath_output=None):
"""Process a file to load the portfolio and analyze its positions."""
portfolio = Portfolio()
try:
count = portfolio.load_from_excel(filepath_input)
print(f"Loaded {count} positions from {filepath_input}")
if count > 0:
print("Analyzing positions...")
results = portfolio.analyze_all_positions()
total_value_info(portfolio)
if filepath_output and portfolio.save_results_to_excel(filepath_output):
print(f"Results saved to {filepath_output}")
return portfolio
except Exception as e:
logger.error(f"Error processing Excel file: {e}")
print(f"An error occurred: {e}")
return None
def total_value_info(portfolio):
"""Calculate and print the total value of the portfolio."""
total = portfolio.calculate_total_value()
print(f"\nTotal portfolio value: {total['total_value']:.2f}")
print(f"Total cost: {total['total_cost']:.2f}")
print(f"Profit/Loss: {total['total_gain_loss']:.2f} ({total['total_gain_loss_percent']:.2f}%)")
def analyze_single_stock(ticker, quantity=0, cost_price=None, chart=False, benchmark=None, period="1y"):
"""Analyze a single stock based on the given ticker."""
try:
stock = Stock(ticker)
analysis = stock.get_comprehensive_analysis(cost_price, quantity)
print_analysis(analysis, quantity)
if chart:
chart_path = visualizza_andamento_titolo(stock.ticker, period=period)
print(f"\nChart saved in: {chart_path}")
if benchmark:
benchmark_path = visualizza_confronto_benchmark(stock.ticker, benchmark, period=period)
print(f"Benchmark comparison chart saved in: {benchmark_path}")
return analysis
except Exception as e:
logger.error(f"Error analyzing stock {ticker}: {e}")
print(f"An error occurred: {e}")
return None
def main():
"""Main function to execute the script."""
try:
args = parse_arguments()
if args.mode == 'manual':
portfolio = manual_input()
elif args.mode == 'excel':
input_path = args.input or CONFIG['file_input_default']
output_path = args.output or CONFIG['file_output_default']
process_excel_file(input_path, output_path)
elif args.mode == 'analyze':
if args.ticker:
analyze_single_stock(args.ticker, args.quantity, args.price, args.chart, args.benchmark, args.period)
return 0
except KeyboardInterrupt:
print("\nOperation interrupted by user")
return 0
except Exception as e:
logger.exception("Unhandled error")
print(f"An unhandled error occurred: {e}")
return 1
if __name__ == "__main__":
main()
```
### Changes Made:
1. **Function Decomposition**: Added specific functions to handle tasks, such as printing analysis results and processing files. This enhances readability and maintainability.
2. **Enhanced Logging**: Improved error handling and logging throughout the script, providing better insights for troubleshooting.
3. **Streamlined Input Handling**: Simplified the logic for obtaining user input, making it more user-friendly and easier to modify in the future.
4. **Added Documentation**: Included comments and docstrings throughout the code to explain the purpose of each function, aiding future developers or users of the script.
5. **General Refactoring**: Cleaned up redundant and verbose sections of code, making it easier to follow the logic flow.
These improvements result in a clearer, more efficient, and maintainable code structure while retaining the original functionality of the financial analysis application.


