1use std::collections::BTreeMap;
2
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5
6pub type UnknownCorporateAction = BTreeMap<String, serde_json::Value>;
7
8#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
9pub struct CorporateActions {
10 #[serde(default)]
11 pub forward_splits: Vec<ForwardSplit>,
12 #[serde(default)]
13 pub reverse_splits: Vec<ReverseSplit>,
14 #[serde(default)]
15 pub unit_splits: Vec<UnitSplit>,
16 #[serde(default)]
17 pub stock_dividends: Vec<StockDividend>,
18 #[serde(default)]
19 pub cash_dividends: Vec<CashDividend>,
20 #[serde(default)]
21 pub spin_offs: Vec<SpinOff>,
22 #[serde(default)]
23 pub cash_mergers: Vec<CashMerger>,
24 #[serde(default)]
25 pub stock_mergers: Vec<StockMerger>,
26 #[serde(default)]
27 pub stock_and_cash_mergers: Vec<StockAndCashMerger>,
28 #[serde(default)]
29 pub redemptions: Vec<Redemption>,
30 #[serde(default)]
31 pub name_changes: Vec<NameChange>,
32 #[serde(default)]
33 pub worthless_removals: Vec<WorthlessRemoval>,
34 #[serde(default)]
35 pub rights_distributions: Vec<RightsDistribution>,
36 #[serde(default)]
37 pub contract_adjustments: Vec<UnknownCorporateAction>,
38 #[serde(default)]
39 pub partial_calls: Vec<UnknownCorporateAction>,
40 #[serde(flatten)]
41 pub other: BTreeMap<String, Vec<UnknownCorporateAction>>,
42}
43
44impl CorporateActions {
45 pub(crate) fn merge(&mut self, mut next: Self) {
46 self.forward_splits.append(&mut next.forward_splits);
47 self.reverse_splits.append(&mut next.reverse_splits);
48 self.unit_splits.append(&mut next.unit_splits);
49 self.stock_dividends.append(&mut next.stock_dividends);
50 self.cash_dividends.append(&mut next.cash_dividends);
51 self.spin_offs.append(&mut next.spin_offs);
52 self.cash_mergers.append(&mut next.cash_mergers);
53 self.stock_mergers.append(&mut next.stock_mergers);
54 self.stock_and_cash_mergers
55 .append(&mut next.stock_and_cash_mergers);
56 self.redemptions.append(&mut next.redemptions);
57 self.name_changes.append(&mut next.name_changes);
58 self.worthless_removals.append(&mut next.worthless_removals);
59 self.rights_distributions
60 .append(&mut next.rights_distributions);
61 self.contract_adjustments
62 .append(&mut next.contract_adjustments);
63 self.partial_calls.append(&mut next.partial_calls);
64
65 for (key, mut values) in next.other {
66 self.other.entry(key).or_default().append(&mut values);
67 }
68 }
69}
70
71#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
72pub struct ForwardSplit {
73 pub id: String,
74 pub symbol: String,
75 pub cusip: String,
76 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
77 pub new_rate: Decimal,
78 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
79 pub old_rate: Decimal,
80 pub process_date: String,
81 pub ex_date: String,
82 pub record_date: Option<String>,
83 pub payable_date: Option<String>,
84 pub due_bill_redemption_date: Option<String>,
85}
86
87#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
88pub struct ReverseSplit {
89 pub id: String,
90 pub symbol: String,
91 pub old_cusip: String,
92 pub new_cusip: String,
93 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
94 pub new_rate: Decimal,
95 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
96 pub old_rate: Decimal,
97 pub process_date: String,
98 pub ex_date: String,
99 pub record_date: Option<String>,
100 pub payable_date: Option<String>,
101}
102
103#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
104pub struct UnitSplit {
105 pub id: String,
106 pub old_symbol: String,
107 pub old_cusip: String,
108 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
109 pub old_rate: Decimal,
110 pub new_symbol: String,
111 pub new_cusip: String,
112 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
113 pub new_rate: Decimal,
114 pub alternate_symbol: String,
115 pub alternate_cusip: String,
116 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
117 pub alternate_rate: Decimal,
118 pub process_date: String,
119 pub effective_date: String,
120 pub payable_date: Option<String>,
121}
122
123#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
124pub struct StockDividend {
125 pub id: String,
126 pub symbol: String,
127 pub cusip: String,
128 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
129 pub rate: Decimal,
130 pub process_date: String,
131 pub ex_date: String,
132 pub record_date: Option<String>,
133 pub payable_date: Option<String>,
134}
135
136#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
137pub struct CashDividend {
138 pub id: String,
139 pub symbol: String,
140 pub cusip: String,
141 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
142 pub rate: Decimal,
143 pub special: bool,
144 pub foreign: bool,
145 pub process_date: String,
146 pub ex_date: String,
147 pub record_date: Option<String>,
148 pub payable_date: Option<String>,
149 pub due_bill_on_date: Option<String>,
150 pub due_bill_off_date: Option<String>,
151}
152
153#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
154pub struct SpinOff {
155 pub id: String,
156 pub source_symbol: String,
157 pub source_cusip: String,
158 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
159 pub source_rate: Decimal,
160 pub new_symbol: String,
161 pub new_cusip: String,
162 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
163 pub new_rate: Decimal,
164 pub process_date: String,
165 pub ex_date: String,
166 pub record_date: Option<String>,
167 pub payable_date: Option<String>,
168 pub due_bill_redemption_date: Option<String>,
169}
170
171#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
172pub struct CashMerger {
173 pub id: String,
174 pub acquirer_symbol: Option<String>,
175 pub acquirer_cusip: Option<String>,
176 pub acquiree_symbol: String,
177 pub acquiree_cusip: String,
178 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
179 pub rate: Decimal,
180 pub process_date: String,
181 pub effective_date: String,
182 pub payable_date: Option<String>,
183}
184
185#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
186pub struct StockMerger {
187 pub id: String,
188 pub acquirer_symbol: String,
189 pub acquirer_cusip: String,
190 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
191 pub acquirer_rate: Decimal,
192 pub acquiree_symbol: String,
193 pub acquiree_cusip: String,
194 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
195 pub acquiree_rate: Decimal,
196 pub process_date: String,
197 pub effective_date: String,
198 pub payable_date: Option<String>,
199}
200
201#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
202pub struct StockAndCashMerger {
203 pub id: String,
204 pub acquirer_symbol: String,
205 pub acquirer_cusip: String,
206 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
207 pub acquirer_rate: Decimal,
208 pub acquiree_symbol: String,
209 pub acquiree_cusip: String,
210 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
211 pub acquiree_rate: Decimal,
212 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
213 pub cash_rate: Decimal,
214 pub process_date: String,
215 pub effective_date: String,
216 pub payable_date: Option<String>,
217}
218
219#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
220pub struct Redemption {
221 pub id: String,
222 pub symbol: String,
223 pub cusip: String,
224 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
225 pub rate: Decimal,
226 pub process_date: String,
227 pub payable_date: Option<String>,
228}
229
230#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
231pub struct NameChange {
232 pub id: String,
233 pub old_symbol: String,
234 pub old_cusip: String,
235 pub new_symbol: String,
236 pub new_cusip: String,
237 pub process_date: String,
238}
239
240#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
241pub struct WorthlessRemoval {
242 pub id: String,
243 pub symbol: String,
244 pub cusip: String,
245 pub process_date: String,
246}
247
248#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
249pub struct RightsDistribution {
250 pub id: String,
251 pub source_symbol: String,
252 pub source_cusip: String,
253 pub new_symbol: String,
254 pub new_cusip: String,
255 #[serde(deserialize_with = "alpaca_core::decimal::deserialize_decimal_from_string_or_number")]
256 pub rate: Decimal,
257 pub process_date: String,
258 pub ex_date: String,
259 pub record_date: Option<String>,
260 pub payable_date: String,
261 pub expiration_date: Option<String>,
262}