File size: 1,648 Bytes
55ec4c5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional
import hashlib


@dataclass
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()

    @property
    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