| from dataclasses import dataclass, field | |
| from datetime import datetime | |
| from typing import Optional | |
| import hashlib | |
| class InsiderTrade: | |
| """Data class to standardize insider trading information""" | |
| symbol: str | |
| company_name: str | |
| insider_name: str | |
| position: str | |
| transaction_date: str | |
| transaction_type: str | |
| shares: int | |
| price: float | |
| value: float | |
| form_type: str | |
| source: str | |
| filing_date: str = "" | |
| ownership_type: str = "" # Direct/Indirect | |
| # IMPROVEMENT: Add hash field directly to dataclass for clarity | |
| hash: str = field(init=False, repr=False) | |
| def __post_init__(self): | |
| """Generate unique hash for deduplication""" | |
| # Create hash based on key identifying fields | |
| hash_string = f"{self.symbol}_{self.insider_name}_{self.transaction_date}_{self.shares}_{self.price}_{self.transaction_type}" | |
| self.hash = hashlib.md5(hash_string.encode()).hexdigest() | |
| def transaction_date_dt(self) -> Optional[datetime]: | |
| """Convert transaction date to datetime object""" | |
| if not self.transaction_date or not isinstance(self.transaction_date, str): | |
| return None | |
| try: | |
| # Handle various date formats | |
| for fmt in ['%Y-%m-%d', '%m/%d/%Y', '%d/%m/%Y', '%Y-%m-%d %H:%M:%S']: | |
| try: | |
| return datetime.strptime(self.transaction_date, fmt) | |
| except ValueError: | |
| continue | |
| return None | |
| # IMPROVEMENT: Catch specific exceptions instead of a generic one. | |
| except (ValueError, TypeError): | |
| return None | |