1use serde::{Deserialize, Serialize};
4use std::str::FromStr;
5use strum::{AsRefStr, Display, EnumString};
6
7use chrono::{DateTime, Utc};
8#[cfg(feature = "dataframe")]
9use df_derive::ToDataFrame;
10#[cfg(feature = "dataframe")]
11use paft_core::dataframe::ToDataFrame;
12use paft_core::domain::Money;
13
14#[derive(
19 Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Display, AsRefStr, EnumString,
20)]
21#[strum(ascii_case_insensitive)]
22#[serde(from = "String", into = "String")]
23pub enum TransactionType {
24 #[strum(to_string = "BUY", serialize = "PURCHASE", serialize = "ACQUISITION")]
26 Buy,
27 #[strum(to_string = "SELL", serialize = "SALE", serialize = "DISPOSAL")]
29 Sell,
30 #[strum(to_string = "AWARD", serialize = "GRANT", serialize = "STOCK_AWARD")]
32 Award,
33 #[strum(to_string = "EXERCISE", serialize = "OPTION_EXERCISE")]
35 Exercise,
36 #[strum(to_string = "GIFT")]
38 Gift,
39 #[strum(to_string = "CONVERSION")]
41 Conversion,
42 Other(String),
44}
45
46impl From<String> for TransactionType {
47 fn from(s: String) -> Self {
48 Self::from_str(&s).unwrap_or_else(|_| Self::Other(s.to_uppercase()))
50 }
51}
52
53impl From<TransactionType> for String {
54 fn from(transaction_type: TransactionType) -> Self {
55 match transaction_type {
56 TransactionType::Other(s) => s,
57 _ => transaction_type.to_string(),
58 }
59 }
60}
61
62#[derive(
67 Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Display, AsRefStr, EnumString,
68)]
69#[strum(ascii_case_insensitive)]
70#[serde(from = "String", into = "String")]
71pub enum InsiderPosition {
72 #[strum(to_string = "OFFICER")]
74 Officer,
75 #[strum(to_string = "DIRECTOR", serialize = "BOARD_MEMBER")]
77 Director,
78 #[strum(
80 to_string = "OWNER",
81 serialize = "BENEFICIAL_OWNER",
82 serialize = "10%_OWNER"
83 )]
84 Owner,
85 #[strum(to_string = "CEO", serialize = "CHIEF_EXECUTIVE_OFFICER")]
87 Ceo,
88 #[strum(to_string = "CFO", serialize = "CHIEF_FINANCIAL_OFFICER")]
90 Cfo,
91 #[strum(to_string = "COO", serialize = "CHIEF_OPERATING_OFFICER")]
93 Coo,
94 #[strum(to_string = "CTO", serialize = "CHIEF_TECHNOLOGY_OFFICER")]
96 Cto,
97 #[strum(to_string = "PRESIDENT")]
99 President,
100 #[strum(to_string = "VP", serialize = "VICE_PRESIDENT")]
102 VicePresident,
103 #[strum(to_string = "SECRETARY")]
105 Secretary,
106 #[strum(to_string = "TREASURER")]
108 Treasurer,
109 Other(String),
111}
112
113impl From<String> for InsiderPosition {
114 fn from(s: String) -> Self {
115 Self::from_str(&s).unwrap_or_else(|_| Self::Other(s.to_uppercase()))
117 }
118}
119
120impl From<InsiderPosition> for String {
121 fn from(position: InsiderPosition) -> Self {
122 match position {
123 InsiderPosition::Other(s) => s,
124 _ => position.to_string(),
125 }
126 }
127}
128
129#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
130#[cfg_attr(feature = "dataframe", derive(ToDataFrame))]
131pub struct MajorHolder {
133 pub category: String,
135 pub value: f64,
137}
138
139#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
141#[cfg_attr(feature = "dataframe", derive(ToDataFrame))]
142pub struct InstitutionalHolder {
143 pub holder: String,
145 pub shares: Option<u64>,
147 #[serde(with = "chrono::serde::ts_seconds")]
149 pub date_reported: DateTime<Utc>,
150 pub pct_held: Option<f64>,
152 pub value: Option<Money>,
154}
155
156#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
158#[cfg_attr(feature = "dataframe", derive(ToDataFrame))]
159pub struct InsiderTransaction {
160 pub insider: String,
162 #[cfg_attr(feature = "dataframe", df_derive(as_string))]
164 pub position: InsiderPosition,
165 #[cfg_attr(feature = "dataframe", df_derive(as_string))]
167 pub transaction_type: TransactionType,
168 pub shares: Option<u64>,
170 pub value: Option<Money>,
172 #[serde(with = "chrono::serde::ts_seconds")]
174 pub transaction_date: DateTime<Utc>,
175 pub url: String,
177}
178
179#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
181#[cfg_attr(feature = "dataframe", derive(ToDataFrame))]
182pub struct InsiderRosterHolder {
183 pub name: String,
185 #[cfg_attr(feature = "dataframe", df_derive(as_string))]
187 pub position: InsiderPosition,
188 #[cfg_attr(feature = "dataframe", df_derive(as_string))]
190 pub most_recent_transaction: TransactionType,
191 #[serde(with = "chrono::serde::ts_seconds")]
193 pub latest_transaction_date: DateTime<Utc>,
194 pub shares_owned_directly: Option<u64>,
196 #[serde(with = "chrono::serde::ts_seconds")]
198 pub position_direct_date: DateTime<Utc>,
199}
200
201#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
203#[cfg_attr(feature = "dataframe", derive(ToDataFrame))]
204pub struct NetSharePurchaseActivity {
205 pub period: String,
207 pub buy_shares: Option<u64>,
209 pub buy_count: Option<u64>,
211 pub sell_shares: Option<u64>,
213 pub sell_count: Option<u64>,
215 pub net_shares: Option<i64>,
217 pub net_count: Option<i64>,
219 pub total_insider_shares: Option<u64>,
221 pub net_percent_insider_shares: Option<f64>,
223}