1use serde::{Deserialize, Serialize};
6
7use super::{
8 BalanceSheetHistory, BalanceSheetHistoryQuarterly, CalendarEvents, CashflowStatementHistory,
9 CashflowStatementHistoryQuarterly, Earnings, EarningsHistory, EarningsTrend, EquityPerformance,
10 FundOwnership, FundPerformance, FundProfile, IncomeStatementHistory,
11 IncomeStatementHistoryQuarterly, IndexTrend, IndustryTrend, InsiderHolders,
12 InsiderTransactions, InstitutionOwnership, MajorHoldersBreakdown, NetSharePurchaseActivity,
13 QuoteSummaryResponse, RecommendationTrend, SecFilings, SectorTrend, TopHoldings,
14 UpgradeDowngradeHistory,
15};
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
52#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
53#[serde(rename_all = "camelCase")]
54#[non_exhaustive]
55pub struct Quote {
56 pub symbol: String,
58
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub logo_url: Option<String>,
62
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub company_logo_url: Option<String>,
66
67 #[serde(skip_serializing_if = "Option::is_none")]
70 pub short_name: Option<String>,
71
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub long_name: Option<String>,
75
76 #[serde(skip_serializing_if = "Option::is_none")]
78 pub exchange: Option<String>,
79
80 #[serde(skip_serializing_if = "Option::is_none")]
82 pub exchange_name: Option<String>,
83
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub quote_type: Option<String>,
87
88 #[serde(skip_serializing_if = "Option::is_none")]
90 pub currency: Option<String>,
91
92 #[serde(skip_serializing_if = "Option::is_none")]
94 pub currency_symbol: Option<String>,
95
96 #[serde(skip_serializing_if = "Option::is_none")]
98 pub underlying_symbol: Option<String>,
99
100 #[serde(skip_serializing_if = "Option::is_none")]
102 pub from_currency: Option<String>,
103
104 #[serde(skip_serializing_if = "Option::is_none")]
106 pub to_currency: Option<String>,
107
108 #[serde(skip_serializing_if = "Option::is_none")]
111 pub regular_market_price: Option<super::FormattedValue<f64>>,
112
113 #[serde(skip_serializing_if = "Option::is_none")]
115 pub regular_market_change: Option<super::FormattedValue<f64>>,
116
117 #[serde(skip_serializing_if = "Option::is_none")]
119 pub regular_market_change_percent: Option<super::FormattedValue<f64>>,
120
121 #[serde(skip_serializing_if = "Option::is_none")]
123 pub regular_market_time: Option<i64>,
124
125 #[serde(skip_serializing_if = "Option::is_none")]
127 pub regular_market_day_high: Option<super::FormattedValue<f64>>,
128
129 #[serde(skip_serializing_if = "Option::is_none")]
131 pub regular_market_day_low: Option<super::FormattedValue<f64>>,
132
133 #[serde(skip_serializing_if = "Option::is_none")]
135 pub regular_market_open: Option<super::FormattedValue<f64>>,
136
137 #[serde(skip_serializing_if = "Option::is_none")]
139 pub regular_market_previous_close: Option<super::FormattedValue<f64>>,
140
141 #[serde(skip_serializing_if = "Option::is_none")]
143 pub regular_market_volume: Option<super::FormattedValue<i64>>,
144
145 #[serde(skip_serializing_if = "Option::is_none")]
147 pub market_state: Option<String>,
148
149 #[serde(skip_serializing_if = "Option::is_none")]
152 pub day_high: Option<super::FormattedValue<f64>>,
153
154 #[serde(skip_serializing_if = "Option::is_none")]
156 pub day_low: Option<super::FormattedValue<f64>>,
157
158 #[serde(skip_serializing_if = "Option::is_none")]
160 pub open: Option<super::FormattedValue<f64>>,
161
162 #[serde(skip_serializing_if = "Option::is_none")]
164 pub previous_close: Option<super::FormattedValue<f64>>,
165
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub volume: Option<super::FormattedValue<i64>>,
169
170 #[serde(skip_serializing_if = "Option::is_none")]
173 pub all_time_high: Option<super::FormattedValue<f64>>,
174
175 #[serde(skip_serializing_if = "Option::is_none")]
177 pub all_time_low: Option<super::FormattedValue<f64>>,
178
179 #[serde(skip_serializing_if = "Option::is_none")]
182 pub pre_market_price: Option<super::FormattedValue<f64>>,
183
184 #[serde(skip_serializing_if = "Option::is_none")]
186 pub pre_market_change: Option<super::FormattedValue<f64>>,
187
188 #[serde(skip_serializing_if = "Option::is_none")]
190 pub pre_market_change_percent: Option<super::FormattedValue<f64>>,
191
192 #[serde(skip_serializing_if = "Option::is_none")]
194 pub pre_market_time: Option<i64>,
195
196 #[serde(skip_serializing_if = "Option::is_none")]
198 pub post_market_price: Option<super::FormattedValue<f64>>,
199
200 #[serde(skip_serializing_if = "Option::is_none")]
202 pub post_market_change: Option<super::FormattedValue<f64>>,
203
204 #[serde(skip_serializing_if = "Option::is_none")]
206 pub post_market_change_percent: Option<super::FormattedValue<f64>>,
207
208 #[serde(skip_serializing_if = "Option::is_none")]
210 pub post_market_time: Option<i64>,
211
212 #[serde(skip_serializing_if = "Option::is_none")]
215 pub average_daily_volume10_day: Option<super::FormattedValue<i64>>,
216
217 #[serde(skip_serializing_if = "Option::is_none")]
219 pub average_daily_volume3_month: Option<super::FormattedValue<i64>>,
220
221 #[serde(skip_serializing_if = "Option::is_none")]
223 pub average_volume: Option<super::FormattedValue<i64>>,
224
225 #[serde(skip_serializing_if = "Option::is_none")]
227 pub average_volume10days: Option<super::FormattedValue<i64>>,
228
229 #[serde(skip_serializing_if = "Option::is_none")]
232 pub market_cap: Option<super::FormattedValue<i64>>,
233
234 #[serde(skip_serializing_if = "Option::is_none")]
236 pub enterprise_value: Option<super::FormattedValue<i64>>,
237
238 #[serde(skip_serializing_if = "Option::is_none")]
240 pub enterprise_to_revenue: Option<super::FormattedValue<f64>>,
241
242 #[serde(skip_serializing_if = "Option::is_none")]
244 pub enterprise_to_ebitda: Option<super::FormattedValue<f64>>,
245
246 #[serde(skip_serializing_if = "Option::is_none")]
248 pub price_to_book: Option<super::FormattedValue<f64>>,
249
250 #[serde(skip_serializing_if = "Option::is_none")]
252 pub price_to_sales_trailing12_months: Option<super::FormattedValue<f64>>,
253
254 #[serde(rename = "forwardPE", skip_serializing_if = "Option::is_none")]
257 pub forward_pe: Option<super::FormattedValue<f64>>,
258
259 #[serde(rename = "trailingPE", skip_serializing_if = "Option::is_none")]
261 pub trailing_pe: Option<super::FormattedValue<f64>>,
262
263 #[serde(skip_serializing_if = "Option::is_none")]
266 pub beta: Option<super::FormattedValue<f64>>,
267
268 #[serde(skip_serializing_if = "Option::is_none")]
271 pub fifty_two_week_high: Option<super::FormattedValue<f64>>,
272
273 #[serde(skip_serializing_if = "Option::is_none")]
275 pub fifty_two_week_low: Option<super::FormattedValue<f64>>,
276
277 #[serde(skip_serializing_if = "Option::is_none")]
279 pub fifty_day_average: Option<super::FormattedValue<f64>>,
280
281 #[serde(skip_serializing_if = "Option::is_none")]
283 pub two_hundred_day_average: Option<super::FormattedValue<f64>>,
284
285 #[serde(rename = "52WeekChange", skip_serializing_if = "Option::is_none")]
287 pub week_52_change: Option<super::FormattedValue<f64>>,
288
289 #[serde(rename = "SandP52WeekChange", skip_serializing_if = "Option::is_none")]
291 pub sand_p_52_week_change: Option<super::FormattedValue<f64>>,
292
293 #[serde(skip_serializing_if = "Option::is_none")]
296 pub dividend_rate: Option<super::FormattedValue<f64>>,
297
298 #[serde(skip_serializing_if = "Option::is_none")]
300 pub dividend_yield: Option<super::FormattedValue<f64>>,
301
302 #[serde(skip_serializing_if = "Option::is_none")]
304 pub trailing_annual_dividend_rate: Option<super::FormattedValue<f64>>,
305
306 #[serde(skip_serializing_if = "Option::is_none")]
308 pub trailing_annual_dividend_yield: Option<super::FormattedValue<f64>>,
309
310 #[serde(skip_serializing_if = "Option::is_none")]
312 pub five_year_avg_dividend_yield: Option<super::FormattedValue<f64>>,
313
314 #[serde(skip_serializing_if = "Option::is_none")]
316 pub ex_dividend_date: Option<super::FormattedValue<i64>>,
317
318 #[serde(skip_serializing_if = "Option::is_none")]
320 pub payout_ratio: Option<super::FormattedValue<f64>>,
321
322 #[serde(skip_serializing_if = "Option::is_none")]
324 pub last_dividend_value: Option<super::FormattedValue<f64>>,
325
326 #[serde(skip_serializing_if = "Option::is_none")]
328 pub last_dividend_date: Option<super::FormattedValue<i64>>,
329
330 #[serde(skip_serializing_if = "Option::is_none")]
333 pub bid: Option<super::FormattedValue<f64>>,
334
335 #[serde(skip_serializing_if = "Option::is_none")]
337 pub bid_size: Option<super::FormattedValue<i64>>,
338
339 #[serde(skip_serializing_if = "Option::is_none")]
341 pub ask: Option<super::FormattedValue<f64>>,
342
343 #[serde(skip_serializing_if = "Option::is_none")]
345 pub ask_size: Option<super::FormattedValue<i64>>,
346
347 #[serde(skip_serializing_if = "Option::is_none")]
350 pub shares_outstanding: Option<super::FormattedValue<i64>>,
351
352 #[serde(skip_serializing_if = "Option::is_none")]
354 pub float_shares: Option<super::FormattedValue<i64>>,
355
356 #[serde(skip_serializing_if = "Option::is_none")]
358 pub implied_shares_outstanding: Option<super::FormattedValue<i64>>,
359
360 #[serde(skip_serializing_if = "Option::is_none")]
362 pub held_percent_insiders: Option<super::FormattedValue<f64>>,
363
364 #[serde(skip_serializing_if = "Option::is_none")]
366 pub held_percent_institutions: Option<super::FormattedValue<f64>>,
367
368 #[serde(skip_serializing_if = "Option::is_none")]
370 pub shares_short: Option<super::FormattedValue<i64>>,
371
372 #[serde(skip_serializing_if = "Option::is_none")]
374 pub shares_short_prior_month: Option<super::FormattedValue<i64>>,
375
376 #[serde(skip_serializing_if = "Option::is_none")]
378 pub short_ratio: Option<super::FormattedValue<f64>>,
379
380 #[serde(skip_serializing_if = "Option::is_none")]
382 pub short_percent_of_float: Option<super::FormattedValue<f64>>,
383
384 #[serde(skip_serializing_if = "Option::is_none")]
386 pub shares_percent_shares_out: Option<super::FormattedValue<f64>>,
387
388 #[serde(skip_serializing_if = "Option::is_none")]
390 pub date_short_interest: Option<super::FormattedValue<i64>>,
391
392 #[serde(skip_serializing_if = "Option::is_none")]
395 pub current_price: Option<super::FormattedValue<f64>>,
396
397 #[serde(skip_serializing_if = "Option::is_none")]
399 pub target_high_price: Option<super::FormattedValue<f64>>,
400
401 #[serde(skip_serializing_if = "Option::is_none")]
403 pub target_low_price: Option<super::FormattedValue<f64>>,
404
405 #[serde(skip_serializing_if = "Option::is_none")]
407 pub target_mean_price: Option<super::FormattedValue<f64>>,
408
409 #[serde(skip_serializing_if = "Option::is_none")]
411 pub target_median_price: Option<super::FormattedValue<f64>>,
412
413 #[serde(skip_serializing_if = "Option::is_none")]
415 pub recommendation_mean: Option<super::FormattedValue<f64>>,
416
417 #[serde(skip_serializing_if = "Option::is_none")]
419 pub recommendation_key: Option<String>,
420
421 #[serde(skip_serializing_if = "Option::is_none")]
423 pub number_of_analyst_opinions: Option<super::FormattedValue<i64>>,
424
425 #[serde(skip_serializing_if = "Option::is_none")]
427 pub total_cash: Option<super::FormattedValue<i64>>,
428
429 #[serde(skip_serializing_if = "Option::is_none")]
431 pub total_cash_per_share: Option<super::FormattedValue<f64>>,
432
433 #[serde(skip_serializing_if = "Option::is_none")]
435 pub ebitda: Option<super::FormattedValue<i64>>,
436
437 #[serde(skip_serializing_if = "Option::is_none")]
439 pub total_debt: Option<super::FormattedValue<i64>>,
440
441 #[serde(skip_serializing_if = "Option::is_none")]
443 pub total_revenue: Option<super::FormattedValue<i64>>,
444
445 #[serde(skip_serializing_if = "Option::is_none")]
447 pub net_income_to_common: Option<super::FormattedValue<i64>>,
448
449 #[serde(skip_serializing_if = "Option::is_none")]
451 pub debt_to_equity: Option<super::FormattedValue<f64>>,
452
453 #[serde(skip_serializing_if = "Option::is_none")]
455 pub revenue_per_share: Option<super::FormattedValue<f64>>,
456
457 #[serde(skip_serializing_if = "Option::is_none")]
459 pub return_on_assets: Option<super::FormattedValue<f64>>,
460
461 #[serde(skip_serializing_if = "Option::is_none")]
463 pub return_on_equity: Option<super::FormattedValue<f64>>,
464
465 #[serde(skip_serializing_if = "Option::is_none")]
467 pub free_cashflow: Option<super::FormattedValue<i64>>,
468
469 #[serde(skip_serializing_if = "Option::is_none")]
471 pub operating_cashflow: Option<super::FormattedValue<i64>>,
472
473 #[serde(skip_serializing_if = "Option::is_none")]
476 pub profit_margins: Option<super::FormattedValue<f64>>,
477
478 #[serde(skip_serializing_if = "Option::is_none")]
480 pub gross_margins: Option<super::FormattedValue<f64>>,
481
482 #[serde(skip_serializing_if = "Option::is_none")]
484 pub ebitda_margins: Option<super::FormattedValue<f64>>,
485
486 #[serde(skip_serializing_if = "Option::is_none")]
488 pub operating_margins: Option<super::FormattedValue<f64>>,
489
490 #[serde(skip_serializing_if = "Option::is_none")]
492 pub gross_profits: Option<super::FormattedValue<i64>>,
493
494 #[serde(skip_serializing_if = "Option::is_none")]
497 pub earnings_growth: Option<super::FormattedValue<f64>>,
498
499 #[serde(skip_serializing_if = "Option::is_none")]
501 pub revenue_growth: Option<super::FormattedValue<f64>>,
502
503 #[serde(skip_serializing_if = "Option::is_none")]
505 pub earnings_quarterly_growth: Option<super::FormattedValue<f64>>,
506
507 #[serde(skip_serializing_if = "Option::is_none")]
510 pub current_ratio: Option<super::FormattedValue<f64>>,
511
512 #[serde(skip_serializing_if = "Option::is_none")]
514 pub quick_ratio: Option<super::FormattedValue<f64>>,
515
516 #[serde(skip_serializing_if = "Option::is_none")]
519 pub trailing_eps: Option<super::FormattedValue<f64>>,
520
521 #[serde(skip_serializing_if = "Option::is_none")]
523 pub forward_eps: Option<super::FormattedValue<f64>>,
524
525 #[serde(skip_serializing_if = "Option::is_none")]
527 pub book_value: Option<super::FormattedValue<f64>>,
528
529 #[serde(skip_serializing_if = "Option::is_none")]
532 pub sector: Option<String>,
533
534 #[serde(skip_serializing_if = "Option::is_none")]
536 pub sector_key: Option<String>,
537
538 #[serde(skip_serializing_if = "Option::is_none")]
540 pub sector_disp: Option<String>,
541
542 #[serde(skip_serializing_if = "Option::is_none")]
544 pub industry: Option<String>,
545
546 #[serde(skip_serializing_if = "Option::is_none")]
548 pub industry_key: Option<String>,
549
550 #[serde(skip_serializing_if = "Option::is_none")]
552 pub industry_disp: Option<String>,
553
554 #[serde(skip_serializing_if = "Option::is_none")]
556 pub long_business_summary: Option<String>,
557
558 #[serde(skip_serializing_if = "Option::is_none")]
560 pub website: Option<String>,
561
562 #[serde(skip_serializing_if = "Option::is_none")]
564 pub ir_website: Option<String>,
565
566 #[serde(skip_serializing_if = "Option::is_none")]
568 pub address1: Option<String>,
569
570 #[serde(skip_serializing_if = "Option::is_none")]
572 pub city: Option<String>,
573
574 #[serde(skip_serializing_if = "Option::is_none")]
576 pub state: Option<String>,
577
578 #[serde(skip_serializing_if = "Option::is_none")]
580 pub zip: Option<String>,
581
582 #[serde(skip_serializing_if = "Option::is_none")]
584 pub country: Option<String>,
585
586 #[serde(skip_serializing_if = "Option::is_none")]
588 pub phone: Option<String>,
589
590 #[serde(skip_serializing_if = "Option::is_none")]
592 pub full_time_employees: Option<i64>,
593
594 #[serde(skip_serializing_if = "Option::is_none")]
596 pub category: Option<String>,
597
598 #[serde(skip_serializing_if = "Option::is_none")]
600 pub fund_family: Option<String>,
601
602 #[serde(skip_serializing_if = "Option::is_none")]
605 pub audit_risk: Option<i32>,
606
607 #[serde(skip_serializing_if = "Option::is_none")]
609 pub board_risk: Option<i32>,
610
611 #[serde(skip_serializing_if = "Option::is_none")]
613 pub compensation_risk: Option<i32>,
614
615 #[serde(skip_serializing_if = "Option::is_none")]
617 pub shareholder_rights_risk: Option<i32>,
618
619 #[serde(skip_serializing_if = "Option::is_none")]
621 pub overall_risk: Option<i32>,
622
623 #[serde(skip_serializing_if = "Option::is_none")]
626 pub time_zone_full_name: Option<String>,
627
628 #[serde(skip_serializing_if = "Option::is_none")]
630 pub time_zone_short_name: Option<String>,
631
632 #[serde(skip_serializing_if = "Option::is_none")]
634 pub gmt_off_set_milliseconds: Option<i64>,
635
636 #[serde(skip_serializing_if = "Option::is_none")]
638 pub first_trade_date_epoch_utc: Option<i64>,
639
640 #[serde(skip_serializing_if = "Option::is_none")]
642 pub message_board_id: Option<String>,
643
644 #[serde(skip_serializing_if = "Option::is_none")]
646 pub exchange_data_delayed_by: Option<i32>,
647
648 #[serde(skip_serializing_if = "Option::is_none")]
651 pub nav_price: Option<super::FormattedValue<f64>>,
652
653 #[serde(skip_serializing_if = "Option::is_none")]
655 pub total_assets: Option<super::FormattedValue<i64>>,
656
657 #[serde(rename = "yield", skip_serializing_if = "Option::is_none")]
659 pub yield_value: Option<super::FormattedValue<f64>>,
660
661 #[serde(skip_serializing_if = "Option::is_none")]
664 pub last_split_factor: Option<String>,
665
666 #[serde(skip_serializing_if = "Option::is_none")]
668 pub last_split_date: Option<super::FormattedValue<i64>>,
669
670 #[serde(skip_serializing_if = "Option::is_none")]
672 pub last_fiscal_year_end: Option<super::FormattedValue<i64>>,
673
674 #[serde(skip_serializing_if = "Option::is_none")]
676 pub next_fiscal_year_end: Option<super::FormattedValue<i64>>,
677
678 #[serde(skip_serializing_if = "Option::is_none")]
680 pub most_recent_quarter: Option<super::FormattedValue<i64>>,
681
682 #[serde(skip_serializing_if = "Option::is_none")]
685 pub price_hint: Option<super::FormattedValue<i64>>,
686
687 #[serde(skip_serializing_if = "Option::is_none")]
689 pub tradeable: Option<bool>,
690
691 #[serde(skip_serializing_if = "Option::is_none")]
693 pub financial_currency: Option<String>,
694
695 #[serde(skip_serializing_if = "Option::is_none")]
698 pub company_officers: Option<Vec<super::CompanyOfficer>>,
699
700 #[serde(skip_serializing_if = "Option::is_none")]
702 pub earnings: Option<Earnings>,
703
704 #[serde(skip_serializing_if = "Option::is_none")]
706 pub calendar_events: Option<CalendarEvents>,
707
708 #[serde(skip_serializing_if = "Option::is_none")]
710 pub recommendation_trend: Option<RecommendationTrend>,
711
712 #[serde(skip_serializing_if = "Option::is_none")]
714 pub upgrade_downgrade_history: Option<UpgradeDowngradeHistory>,
715
716 #[serde(skip_serializing_if = "Option::is_none")]
718 pub earnings_history: Option<EarningsHistory>,
719
720 #[serde(skip_serializing_if = "Option::is_none")]
722 pub earnings_trend: Option<EarningsTrend>,
723
724 #[serde(skip_serializing_if = "Option::is_none")]
726 pub insider_holders: Option<InsiderHolders>,
727
728 #[serde(skip_serializing_if = "Option::is_none")]
730 pub insider_transactions: Option<InsiderTransactions>,
731
732 #[serde(skip_serializing_if = "Option::is_none")]
734 pub institution_ownership: Option<InstitutionOwnership>,
735
736 #[serde(skip_serializing_if = "Option::is_none")]
738 pub fund_ownership: Option<FundOwnership>,
739
740 #[serde(skip_serializing_if = "Option::is_none")]
742 pub major_holders_breakdown: Option<MajorHoldersBreakdown>,
743
744 #[serde(skip_serializing_if = "Option::is_none")]
746 pub net_share_purchase_activity: Option<NetSharePurchaseActivity>,
747
748 #[serde(skip_serializing_if = "Option::is_none")]
750 pub sec_filings: Option<SecFilings>,
751
752 #[serde(skip_serializing_if = "Option::is_none")]
757 pub balance_sheet_history: Option<BalanceSheetHistory>,
758
759 #[serde(skip_serializing_if = "Option::is_none")]
764 pub balance_sheet_history_quarterly: Option<BalanceSheetHistoryQuarterly>,
765
766 #[serde(skip_serializing_if = "Option::is_none")]
771 pub cashflow_statement_history: Option<CashflowStatementHistory>,
772
773 #[serde(skip_serializing_if = "Option::is_none")]
778 pub cashflow_statement_history_quarterly: Option<CashflowStatementHistoryQuarterly>,
779
780 #[serde(skip_serializing_if = "Option::is_none")]
785 pub income_statement_history: Option<IncomeStatementHistory>,
786
787 #[serde(skip_serializing_if = "Option::is_none")]
792 pub income_statement_history_quarterly: Option<IncomeStatementHistoryQuarterly>,
793
794 #[serde(skip_serializing_if = "Option::is_none")]
796 pub equity_performance: Option<EquityPerformance>,
797
798 #[serde(skip_serializing_if = "Option::is_none")]
800 pub index_trend: Option<IndexTrend>,
801
802 #[serde(skip_serializing_if = "Option::is_none")]
804 pub industry_trend: Option<IndustryTrend>,
805
806 #[serde(skip_serializing_if = "Option::is_none")]
808 pub sector_trend: Option<SectorTrend>,
809
810 #[serde(skip_serializing_if = "Option::is_none")]
812 pub fund_profile: Option<FundProfile>,
813
814 #[serde(skip_serializing_if = "Option::is_none")]
816 pub fund_performance: Option<FundPerformance>,
817
818 #[serde(skip_serializing_if = "Option::is_none")]
820 pub top_holdings: Option<TopHoldings>,
821}
822
823impl Quote {
824 pub(crate) fn from_response(
835 response: &QuoteSummaryResponse,
836 logo_url: Option<String>,
837 company_logo_url: Option<String>,
838 ) -> Self {
839 let price = response.price.as_ref();
840 let quote_type = response.quote_type.as_ref();
841 let summary_detail = response.summary_detail.as_ref();
842 let financial_data = response.financial_data.as_ref();
843 let key_stats = response.default_key_statistics.as_ref();
844 let asset_profile = response.asset_profile.as_ref();
845 let summary_profile = response.summary_profile.as_ref();
846
847 Self {
848 symbol: response.symbol.clone(),
849 logo_url,
850 company_logo_url,
851
852 short_name: price
855 .and_then(|p| p.short_name.clone())
856 .or_else(|| quote_type.and_then(|q| q.short_name.clone())),
857
858 long_name: price
859 .and_then(|p| p.long_name.clone())
860 .or_else(|| quote_type.and_then(|q| q.long_name.clone())),
861
862 exchange: price
863 .and_then(|p| p.exchange.clone())
864 .or_else(|| quote_type.and_then(|q| q.exchange.clone())),
865
866 exchange_name: price.and_then(|p| p.exchange_name.clone()),
867
868 quote_type: price
869 .and_then(|p| p.quote_type.clone())
870 .or_else(|| quote_type.and_then(|q| q.quote_type.clone())),
871
872 currency: price.and_then(|p| p.currency.clone()).or_else(|| {
873 summary_detail
874 .and_then(|s| s.currency.clone())
875 .or_else(|| financial_data.and_then(|f| f.financial_currency.clone()))
876 }),
877
878 currency_symbol: price.and_then(|p| p.currency_symbol.clone()),
879
880 underlying_symbol: price
881 .and_then(|p| p.underlying_symbol.clone())
882 .or_else(|| quote_type.and_then(|q| q.underlying_symbol.clone())),
883 from_currency: price
884 .and_then(|p| p.from_currency.clone())
885 .or_else(|| summary_detail.and_then(|s| s.from_currency.clone())),
886 to_currency: price
887 .and_then(|p| p.to_currency.clone())
888 .or_else(|| summary_detail.and_then(|s| s.to_currency.clone())),
889
890 regular_market_price: price.and_then(|p| p.regular_market_price.clone()),
892 regular_market_change: price.and_then(|p| p.regular_market_change.clone()),
893 regular_market_change_percent: price
894 .and_then(|p| p.regular_market_change_percent.clone()),
895 regular_market_time: price.and_then(|p| p.regular_market_time),
896 regular_market_day_high: price.and_then(|p| p.regular_market_day_high.clone()),
897 regular_market_day_low: price.and_then(|p| p.regular_market_day_low.clone()),
898 regular_market_open: price.and_then(|p| p.regular_market_open.clone()),
899 regular_market_previous_close: price
900 .and_then(|p| p.regular_market_previous_close.clone()),
901 regular_market_volume: price.and_then(|p| p.regular_market_volume.clone()),
902 market_state: price.and_then(|p| p.market_state.clone()),
903
904 day_high: summary_detail.and_then(|s| s.day_high.clone()),
906 day_low: summary_detail.and_then(|s| s.day_low.clone()),
907 open: summary_detail.and_then(|s| s.open.clone()),
908 previous_close: summary_detail.and_then(|s| s.previous_close.clone()),
909 volume: summary_detail.and_then(|s| s.volume.clone()),
910
911 all_time_high: summary_detail.and_then(|s| s.all_time_high.clone()),
913 all_time_low: summary_detail.and_then(|s| s.all_time_low.clone()),
914
915 pre_market_price: price.and_then(|p| p.pre_market_price.clone()),
917 pre_market_change: price.and_then(|p| p.pre_market_change.clone()),
918 pre_market_change_percent: price.and_then(|p| p.pre_market_change_percent.clone()),
919 pre_market_time: price.and_then(|p| p.pre_market_time),
920 post_market_price: price.and_then(|p| p.post_market_price.clone()),
921 post_market_change: price.and_then(|p| p.post_market_change.clone()),
922 post_market_change_percent: price.and_then(|p| p.post_market_change_percent.clone()),
923 post_market_time: price.and_then(|p| p.post_market_time),
924
925 average_daily_volume10_day: price
928 .and_then(|p| p.average_daily_volume10_day.clone())
929 .or_else(|| summary_detail.and_then(|s| s.average_daily_volume10_day.clone())),
930 average_daily_volume3_month: price.and_then(|p| p.average_daily_volume3_month.clone()),
931 average_volume: summary_detail.and_then(|s| s.average_volume.clone()),
932 average_volume10days: summary_detail.and_then(|s| s.average_volume10days.clone()),
933
934 market_cap: price.and_then(|p| p.market_cap.clone()),
937 enterprise_value: key_stats.and_then(|k| k.enterprise_value.clone()),
938 enterprise_to_revenue: key_stats.and_then(|k| k.enterprise_to_revenue.clone()),
939 enterprise_to_ebitda: key_stats.and_then(|k| k.enterprise_to_ebitda.clone()),
940 price_to_book: key_stats.and_then(|k| k.price_to_book.clone()),
941 price_to_sales_trailing12_months: summary_detail
942 .and_then(|s| s.price_to_sales_trailing12_months.clone()),
943
944 forward_pe: summary_detail
947 .and_then(|s| s.forward_pe.clone())
948 .or_else(|| key_stats.and_then(|k| k.forward_pe.clone())),
949 trailing_pe: summary_detail.and_then(|s| s.trailing_pe.clone()),
950
951 beta: summary_detail
954 .and_then(|s| s.beta.clone())
955 .or_else(|| key_stats.and_then(|k| k.beta.clone())),
956
957 fifty_two_week_high: summary_detail.and_then(|s| s.fifty_two_week_high.clone()),
959 fifty_two_week_low: summary_detail.and_then(|s| s.fifty_two_week_low.clone()),
960 fifty_day_average: summary_detail.and_then(|s| s.fifty_day_average.clone()),
961 two_hundred_day_average: summary_detail.and_then(|s| s.two_hundred_day_average.clone()),
962 week_52_change: key_stats.and_then(|k| k.week_52_change.clone()),
963 sand_p_52_week_change: key_stats.and_then(|k| k.sand_p_52_week_change.clone()),
964
965 dividend_rate: summary_detail.and_then(|s| s.dividend_rate.clone()),
967 dividend_yield: summary_detail.and_then(|s| s.dividend_yield.clone()),
968 trailing_annual_dividend_rate: summary_detail
969 .and_then(|s| s.trailing_annual_dividend_rate.clone()),
970 trailing_annual_dividend_yield: summary_detail
971 .and_then(|s| s.trailing_annual_dividend_yield.clone()),
972 five_year_avg_dividend_yield: summary_detail
973 .and_then(|s| s.five_year_avg_dividend_yield.clone()),
974 ex_dividend_date: summary_detail.and_then(|s| s.ex_dividend_date.clone()),
975 payout_ratio: summary_detail.and_then(|s| s.payout_ratio.clone()),
976 last_dividend_value: key_stats.and_then(|k| k.last_dividend_value.clone()),
977 last_dividend_date: key_stats.and_then(|k| k.last_dividend_date.clone()),
978
979 bid: summary_detail.and_then(|s| s.bid.clone()),
981 bid_size: summary_detail.and_then(|s| s.bid_size.clone()),
982 ask: summary_detail.and_then(|s| s.ask.clone()),
983 ask_size: summary_detail.and_then(|s| s.ask_size.clone()),
984
985 shares_outstanding: key_stats.and_then(|k| k.shares_outstanding.clone()),
987 float_shares: key_stats.and_then(|k| k.float_shares.clone()),
988 implied_shares_outstanding: key_stats
989 .and_then(|k| k.implied_shares_outstanding.clone()),
990 held_percent_insiders: key_stats.and_then(|k| k.held_percent_insiders.clone()),
991 held_percent_institutions: key_stats.and_then(|k| k.held_percent_institutions.clone()),
992 shares_short: key_stats.and_then(|k| k.shares_short.clone()),
993 shares_short_prior_month: key_stats.and_then(|k| k.shares_short_prior_month.clone()),
994 short_ratio: key_stats.and_then(|k| k.short_ratio.clone()),
995 short_percent_of_float: key_stats.and_then(|k| k.short_percent_of_float.clone()),
996 shares_percent_shares_out: key_stats.and_then(|k| k.shares_percent_shares_out.clone()),
997 date_short_interest: key_stats.and_then(|k| k.date_short_interest.clone()),
998
999 current_price: financial_data.and_then(|f| f.current_price.clone()),
1001 target_high_price: financial_data.and_then(|f| f.target_high_price.clone()),
1002 target_low_price: financial_data.and_then(|f| f.target_low_price.clone()),
1003 target_mean_price: financial_data.and_then(|f| f.target_mean_price.clone()),
1004 target_median_price: financial_data.and_then(|f| f.target_median_price.clone()),
1005 recommendation_mean: financial_data.and_then(|f| f.recommendation_mean.clone()),
1006 recommendation_key: financial_data.and_then(|f| f.recommendation_key.clone()),
1007 number_of_analyst_opinions: financial_data
1008 .and_then(|f| f.number_of_analyst_opinions.clone()),
1009 total_cash: financial_data.and_then(|f| f.total_cash.clone()),
1010 total_cash_per_share: financial_data.and_then(|f| f.total_cash_per_share.clone()),
1011 ebitda: financial_data.and_then(|f| f.ebitda.clone()),
1012 total_debt: financial_data.and_then(|f| f.total_debt.clone()),
1013 total_revenue: financial_data.and_then(|f| f.total_revenue.clone()),
1014 net_income_to_common: key_stats.and_then(|k| k.net_income_to_common.clone()),
1015 debt_to_equity: financial_data.and_then(|f| f.debt_to_equity.clone()),
1016 revenue_per_share: financial_data.and_then(|f| f.revenue_per_share.clone()),
1017 return_on_assets: financial_data.and_then(|f| f.return_on_assets.clone()),
1018 return_on_equity: financial_data.and_then(|f| f.return_on_equity.clone()),
1019 free_cashflow: financial_data.and_then(|f| f.free_cashflow.clone()),
1020 operating_cashflow: financial_data.and_then(|f| f.operating_cashflow.clone()),
1021
1022 profit_margins: financial_data.and_then(|f| f.profit_margins.clone()),
1025 gross_margins: financial_data.and_then(|f| f.gross_margins.clone()),
1026 ebitda_margins: financial_data.and_then(|f| f.ebitda_margins.clone()),
1027 operating_margins: financial_data.and_then(|f| f.operating_margins.clone()),
1028 gross_profits: financial_data.and_then(|f| f.gross_profits.clone()),
1029
1030 earnings_growth: financial_data.and_then(|f| f.earnings_growth.clone()),
1032 revenue_growth: financial_data.and_then(|f| f.revenue_growth.clone()),
1033 earnings_quarterly_growth: key_stats.and_then(|k| k.earnings_quarterly_growth.clone()),
1034
1035 current_ratio: financial_data.and_then(|f| f.current_ratio.clone()),
1037 quick_ratio: financial_data.and_then(|f| f.quick_ratio.clone()),
1038
1039 trailing_eps: key_stats.and_then(|k| k.trailing_eps.clone()),
1041 forward_eps: key_stats.and_then(|k| k.forward_eps.clone()),
1042 book_value: key_stats.and_then(|k| k.book_value.clone()),
1043
1044 sector: asset_profile
1047 .and_then(|a| a.sector.clone())
1048 .or_else(|| summary_profile.and_then(|s| s.sector.clone())),
1049 sector_key: asset_profile.and_then(|a| a.sector_key.clone()),
1050 sector_disp: asset_profile.and_then(|a| a.sector_disp.clone()),
1051 industry: asset_profile
1052 .and_then(|a| a.industry.clone())
1053 .or_else(|| summary_profile.and_then(|s| s.industry.clone())),
1054 industry_key: asset_profile.and_then(|a| a.industry_key.clone()),
1055 industry_disp: asset_profile.and_then(|a| a.industry_disp.clone()),
1056 long_business_summary: asset_profile
1057 .and_then(|a| a.long_business_summary.clone())
1058 .or_else(|| summary_profile.and_then(|s| s.long_business_summary.clone())),
1059 address1: asset_profile
1060 .and_then(|a| a.address1.clone())
1061 .or_else(|| summary_profile.and_then(|s| s.address1.clone())),
1062 city: asset_profile
1063 .and_then(|a| a.city.clone())
1064 .or_else(|| summary_profile.and_then(|s| s.city.clone())),
1065 state: asset_profile
1066 .and_then(|a| a.state.clone())
1067 .or_else(|| summary_profile.and_then(|s| s.state.clone())),
1068 zip: asset_profile
1069 .and_then(|a| a.zip.clone())
1070 .or_else(|| summary_profile.and_then(|s| s.zip.clone())),
1071 country: asset_profile
1072 .and_then(|a| a.country.clone())
1073 .or_else(|| summary_profile.and_then(|s| s.country.clone())),
1074 phone: asset_profile
1075 .and_then(|a| a.phone.clone())
1076 .or_else(|| summary_profile.and_then(|s| s.phone.clone())),
1077 full_time_employees: asset_profile
1078 .and_then(|a| a.full_time_employees)
1079 .or_else(|| summary_profile.and_then(|s| s.full_time_employees)),
1080
1081 website: asset_profile
1082 .and_then(|a| a.website.clone())
1083 .or_else(|| summary_profile.and_then(|s| s.website.clone())),
1084 ir_website: summary_profile.and_then(|s| s.ir_website.clone()),
1085
1086 category: key_stats.and_then(|k| k.category.clone()),
1087 fund_family: key_stats.and_then(|k| k.fund_family.clone()),
1088
1089 audit_risk: asset_profile.and_then(|a| a.audit_risk),
1091 board_risk: asset_profile.and_then(|a| a.board_risk),
1092 compensation_risk: asset_profile.and_then(|a| a.compensation_risk),
1093 shareholder_rights_risk: asset_profile.and_then(|a| a.shareholder_rights_risk),
1094 overall_risk: asset_profile.and_then(|a| a.overall_risk),
1095
1096 time_zone_full_name: quote_type.and_then(|q| q.time_zone_full_name.clone()),
1098 time_zone_short_name: quote_type.and_then(|q| q.time_zone_short_name.clone()),
1099 gmt_off_set_milliseconds: quote_type.and_then(|q| q.gmt_off_set_milliseconds),
1100 first_trade_date_epoch_utc: quote_type.and_then(|q| q.first_trade_date_epoch_utc),
1101 message_board_id: quote_type.and_then(|q| q.message_board_id.clone()),
1102 exchange_data_delayed_by: price.and_then(|p| p.exchange_data_delayed_by),
1103
1104 nav_price: summary_detail.and_then(|s| s.nav_price.clone()),
1106 total_assets: summary_detail.and_then(|s| s.total_assets.clone()),
1107 yield_value: summary_detail.and_then(|s| s.yield_value.clone()),
1108
1109 last_split_factor: key_stats.and_then(|k| k.last_split_factor.clone()),
1111 last_split_date: key_stats.and_then(|k| k.last_split_date.clone()),
1112 last_fiscal_year_end: key_stats.and_then(|k| k.last_fiscal_year_end.clone()),
1113 next_fiscal_year_end: key_stats.and_then(|k| k.next_fiscal_year_end.clone()),
1114 most_recent_quarter: key_stats.and_then(|k| k.most_recent_quarter.clone()),
1115
1116 price_hint: price.and_then(|p| p.price_hint.clone()),
1119 tradeable: summary_detail.and_then(|s| s.tradeable),
1120 financial_currency: financial_data.and_then(|f| f.financial_currency.clone()),
1121
1122 company_officers: asset_profile.map(|a| a.company_officers.clone()),
1124 earnings: response.earnings.clone(),
1125 calendar_events: response.calendar_events.clone(),
1126 recommendation_trend: response.recommendation_trend.clone(),
1127 upgrade_downgrade_history: response.upgrade_downgrade_history.clone(),
1128 earnings_history: response.earnings_history.clone(),
1129 earnings_trend: response.earnings_trend.clone(),
1130 insider_holders: response.insider_holders.clone(),
1131 insider_transactions: response.insider_transactions.clone(),
1132 institution_ownership: response.institution_ownership.clone(),
1133 fund_ownership: response.fund_ownership.clone(),
1134 major_holders_breakdown: response.major_holders_breakdown.clone(),
1135 net_share_purchase_activity: response.net_share_purchase_activity.clone(),
1136 sec_filings: response.sec_filings.clone(),
1137 balance_sheet_history: None,
1140 balance_sheet_history_quarterly: None,
1141 cashflow_statement_history: None,
1142 cashflow_statement_history_quarterly: None,
1143 income_statement_history: None,
1144 income_statement_history_quarterly: None,
1145 equity_performance: response.equity_performance.clone(),
1146 index_trend: response.index_trend.clone(),
1147 industry_trend: response.industry_trend.clone(),
1148 sector_trend: response.sector_trend.clone(),
1149 fund_profile: response.fund_profile.clone(),
1150 fund_performance: response.fund_performance.clone(),
1151 top_holdings: response.top_holdings.clone(),
1152 }
1153 }
1154
1155 pub fn live_price(&self) -> Option<f64> {
1160 if self.market_state.as_deref() == Some("POST") {
1161 self.post_market_price
1162 .as_ref()
1163 .and_then(|p| p.raw)
1164 .or_else(|| self.regular_market_price.as_ref()?.raw)
1165 } else if self.market_state.as_deref() == Some("PRE") {
1166 self.pre_market_price
1167 .as_ref()
1168 .and_then(|p| p.raw)
1169 .or_else(|| self.regular_market_price.as_ref()?.raw)
1170 } else {
1171 self.regular_market_price.as_ref()?.raw
1172 }
1173 }
1174
1175 pub fn day_range(&self) -> Option<(f64, f64)> {
1177 let low = self.regular_market_day_low.as_ref()?.raw?;
1178 let high = self.regular_market_day_high.as_ref()?.raw?;
1179 Some((low, high))
1180 }
1181
1182 pub fn week_52_range(&self) -> Option<(f64, f64)> {
1184 let low = self.fifty_two_week_low.as_ref()?.raw?;
1185 let high = self.fifty_two_week_high.as_ref()?.raw?;
1186 Some((low, high))
1187 }
1188
1189 pub fn is_market_open(&self) -> bool {
1191 self.market_state.as_deref() == Some("REGULAR")
1192 }
1193
1194 pub fn is_pre_market(&self) -> bool {
1196 self.market_state.as_deref() == Some("PRE")
1197 }
1198
1199 pub fn is_post_market(&self) -> bool {
1201 self.market_state.as_deref() == Some("POST")
1202 }
1203}