1use serde::{Deserialize, Serialize};
6
7use super::{
8 AssetProfile, BalanceSheetHistory, BalanceSheetHistoryQuarterly, CalendarEvents,
9 CashflowStatementHistory, CashflowStatementHistoryQuarterly, DefaultKeyStatistics, Earnings,
10 EarningsHistory, EarningsTrend, EquityPerformance, FinancialData, FundOwnership,
11 FundPerformance, FundProfile, IncomeStatementHistory, IncomeStatementHistoryQuarterly,
12 IndexTrend, IndustryTrend, InsiderHolders, InsiderTransactions, InstitutionOwnership,
13 MajorHoldersBreakdown, NetSharePurchaseActivity, Price, QuoteSummaryResponse, QuoteTypeData,
14 RecommendationTrend, SecFilings, SectorTrend, SummaryDetail, SummaryProfile, TopHoldings,
15 UpgradeDowngradeHistory,
16};
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
53#[cfg_attr(feature = "dataframe", derive(crate::ToDataFrame))]
54#[serde(rename_all = "camelCase")]
55#[non_exhaustive]
56pub struct Quote {
57 pub symbol: String,
59
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub logo_url: Option<String>,
63
64 #[serde(skip_serializing_if = "Option::is_none")]
66 pub company_logo_url: Option<String>,
67
68 #[serde(skip_serializing_if = "Option::is_none")]
71 pub short_name: Option<String>,
72
73 #[serde(skip_serializing_if = "Option::is_none")]
75 pub long_name: Option<String>,
76
77 #[serde(skip_serializing_if = "Option::is_none")]
79 pub exchange: Option<String>,
80
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub exchange_name: Option<String>,
84
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub quote_type: Option<String>,
88
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub currency: Option<String>,
92
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub currency_symbol: Option<String>,
96
97 #[serde(skip_serializing_if = "Option::is_none")]
99 pub underlying_symbol: Option<String>,
100
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub from_currency: Option<String>,
104
105 #[serde(skip_serializing_if = "Option::is_none")]
107 pub to_currency: Option<String>,
108
109 #[serde(skip_serializing_if = "Option::is_none")]
112 pub regular_market_price: Option<super::FormattedValue<f64>>,
113
114 #[serde(skip_serializing_if = "Option::is_none")]
116 pub regular_market_change: Option<super::FormattedValue<f64>>,
117
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub regular_market_change_percent: Option<super::FormattedValue<f64>>,
121
122 #[serde(skip_serializing_if = "Option::is_none")]
124 pub regular_market_time: Option<i64>,
125
126 #[serde(skip_serializing_if = "Option::is_none")]
128 pub regular_market_day_high: Option<super::FormattedValue<f64>>,
129
130 #[serde(skip_serializing_if = "Option::is_none")]
132 pub regular_market_day_low: Option<super::FormattedValue<f64>>,
133
134 #[serde(skip_serializing_if = "Option::is_none")]
136 pub regular_market_open: Option<super::FormattedValue<f64>>,
137
138 #[serde(skip_serializing_if = "Option::is_none")]
140 pub regular_market_previous_close: Option<super::FormattedValue<f64>>,
141
142 #[serde(skip_serializing_if = "Option::is_none")]
144 pub regular_market_volume: Option<super::FormattedValue<i64>>,
145
146 #[serde(skip_serializing_if = "Option::is_none")]
148 pub market_state: Option<String>,
149
150 #[serde(skip_serializing_if = "Option::is_none")]
153 pub day_high: Option<super::FormattedValue<f64>>,
154
155 #[serde(skip_serializing_if = "Option::is_none")]
157 pub day_low: Option<super::FormattedValue<f64>>,
158
159 #[serde(skip_serializing_if = "Option::is_none")]
161 pub open: Option<super::FormattedValue<f64>>,
162
163 #[serde(skip_serializing_if = "Option::is_none")]
165 pub previous_close: Option<super::FormattedValue<f64>>,
166
167 #[serde(skip_serializing_if = "Option::is_none")]
169 pub volume: Option<super::FormattedValue<i64>>,
170
171 #[serde(skip_serializing_if = "Option::is_none")]
174 pub all_time_high: Option<super::FormattedValue<f64>>,
175
176 #[serde(skip_serializing_if = "Option::is_none")]
178 pub all_time_low: Option<super::FormattedValue<f64>>,
179
180 #[serde(skip_serializing_if = "Option::is_none")]
183 pub pre_market_price: Option<super::FormattedValue<f64>>,
184
185 #[serde(skip_serializing_if = "Option::is_none")]
187 pub pre_market_change: Option<super::FormattedValue<f64>>,
188
189 #[serde(skip_serializing_if = "Option::is_none")]
191 pub pre_market_change_percent: Option<super::FormattedValue<f64>>,
192
193 #[serde(skip_serializing_if = "Option::is_none")]
195 pub pre_market_time: Option<i64>,
196
197 #[serde(skip_serializing_if = "Option::is_none")]
199 pub post_market_price: Option<super::FormattedValue<f64>>,
200
201 #[serde(skip_serializing_if = "Option::is_none")]
203 pub post_market_change: Option<super::FormattedValue<f64>>,
204
205 #[serde(skip_serializing_if = "Option::is_none")]
207 pub post_market_change_percent: Option<super::FormattedValue<f64>>,
208
209 #[serde(skip_serializing_if = "Option::is_none")]
211 pub post_market_time: Option<i64>,
212
213 #[serde(skip_serializing_if = "Option::is_none")]
216 pub average_daily_volume10_day: Option<super::FormattedValue<i64>>,
217
218 #[serde(skip_serializing_if = "Option::is_none")]
220 pub average_daily_volume3_month: Option<super::FormattedValue<i64>>,
221
222 #[serde(skip_serializing_if = "Option::is_none")]
224 pub average_volume: Option<super::FormattedValue<i64>>,
225
226 #[serde(skip_serializing_if = "Option::is_none")]
228 pub average_volume10days: Option<super::FormattedValue<i64>>,
229
230 #[serde(skip_serializing_if = "Option::is_none")]
233 pub market_cap: Option<super::FormattedValue<i64>>,
234
235 #[serde(skip_serializing_if = "Option::is_none")]
237 pub enterprise_value: Option<super::FormattedValue<i64>>,
238
239 #[serde(skip_serializing_if = "Option::is_none")]
241 pub enterprise_to_revenue: Option<super::FormattedValue<f64>>,
242
243 #[serde(skip_serializing_if = "Option::is_none")]
245 pub enterprise_to_ebitda: Option<super::FormattedValue<f64>>,
246
247 #[serde(skip_serializing_if = "Option::is_none")]
249 pub price_to_book: Option<super::FormattedValue<f64>>,
250
251 #[serde(skip_serializing_if = "Option::is_none")]
253 pub price_to_sales_trailing12_months: Option<super::FormattedValue<f64>>,
254
255 #[serde(rename = "forwardPE", skip_serializing_if = "Option::is_none")]
258 pub forward_pe: Option<super::FormattedValue<f64>>,
259
260 #[serde(rename = "trailingPE", skip_serializing_if = "Option::is_none")]
262 pub trailing_pe: Option<super::FormattedValue<f64>>,
263
264 #[serde(skip_serializing_if = "Option::is_none")]
267 pub beta: Option<super::FormattedValue<f64>>,
268
269 #[serde(skip_serializing_if = "Option::is_none")]
272 pub fifty_two_week_high: Option<super::FormattedValue<f64>>,
273
274 #[serde(skip_serializing_if = "Option::is_none")]
276 pub fifty_two_week_low: Option<super::FormattedValue<f64>>,
277
278 #[serde(skip_serializing_if = "Option::is_none")]
280 pub fifty_day_average: Option<super::FormattedValue<f64>>,
281
282 #[serde(skip_serializing_if = "Option::is_none")]
284 pub two_hundred_day_average: Option<super::FormattedValue<f64>>,
285
286 #[serde(rename = "52WeekChange", skip_serializing_if = "Option::is_none")]
288 pub week_52_change: Option<super::FormattedValue<f64>>,
289
290 #[serde(rename = "SandP52WeekChange", skip_serializing_if = "Option::is_none")]
292 pub sand_p_52_week_change: Option<super::FormattedValue<f64>>,
293
294 #[serde(skip_serializing_if = "Option::is_none")]
297 pub dividend_rate: Option<super::FormattedValue<f64>>,
298
299 #[serde(skip_serializing_if = "Option::is_none")]
301 pub dividend_yield: Option<super::FormattedValue<f64>>,
302
303 #[serde(skip_serializing_if = "Option::is_none")]
305 pub trailing_annual_dividend_rate: Option<super::FormattedValue<f64>>,
306
307 #[serde(skip_serializing_if = "Option::is_none")]
309 pub trailing_annual_dividend_yield: Option<super::FormattedValue<f64>>,
310
311 #[serde(skip_serializing_if = "Option::is_none")]
313 pub five_year_avg_dividend_yield: Option<super::FormattedValue<f64>>,
314
315 #[serde(skip_serializing_if = "Option::is_none")]
317 pub ex_dividend_date: Option<super::FormattedValue<i64>>,
318
319 #[serde(skip_serializing_if = "Option::is_none")]
321 pub payout_ratio: Option<super::FormattedValue<f64>>,
322
323 #[serde(skip_serializing_if = "Option::is_none")]
325 pub last_dividend_value: Option<super::FormattedValue<f64>>,
326
327 #[serde(skip_serializing_if = "Option::is_none")]
329 pub last_dividend_date: Option<super::FormattedValue<i64>>,
330
331 #[serde(skip_serializing_if = "Option::is_none")]
334 pub bid: Option<super::FormattedValue<f64>>,
335
336 #[serde(skip_serializing_if = "Option::is_none")]
338 pub bid_size: Option<super::FormattedValue<i64>>,
339
340 #[serde(skip_serializing_if = "Option::is_none")]
342 pub ask: Option<super::FormattedValue<f64>>,
343
344 #[serde(skip_serializing_if = "Option::is_none")]
346 pub ask_size: Option<super::FormattedValue<i64>>,
347
348 #[serde(skip_serializing_if = "Option::is_none")]
351 pub shares_outstanding: Option<super::FormattedValue<i64>>,
352
353 #[serde(skip_serializing_if = "Option::is_none")]
355 pub float_shares: Option<super::FormattedValue<i64>>,
356
357 #[serde(skip_serializing_if = "Option::is_none")]
359 pub implied_shares_outstanding: Option<super::FormattedValue<i64>>,
360
361 #[serde(skip_serializing_if = "Option::is_none")]
363 pub held_percent_insiders: Option<super::FormattedValue<f64>>,
364
365 #[serde(skip_serializing_if = "Option::is_none")]
367 pub held_percent_institutions: Option<super::FormattedValue<f64>>,
368
369 #[serde(skip_serializing_if = "Option::is_none")]
371 pub shares_short: Option<super::FormattedValue<i64>>,
372
373 #[serde(skip_serializing_if = "Option::is_none")]
375 pub shares_short_prior_month: Option<super::FormattedValue<i64>>,
376
377 #[serde(skip_serializing_if = "Option::is_none")]
379 pub short_ratio: Option<super::FormattedValue<f64>>,
380
381 #[serde(skip_serializing_if = "Option::is_none")]
383 pub short_percent_of_float: Option<super::FormattedValue<f64>>,
384
385 #[serde(skip_serializing_if = "Option::is_none")]
387 pub shares_percent_shares_out: Option<super::FormattedValue<f64>>,
388
389 #[serde(skip_serializing_if = "Option::is_none")]
391 pub date_short_interest: Option<super::FormattedValue<i64>>,
392
393 #[serde(skip_serializing_if = "Option::is_none")]
396 pub current_price: Option<super::FormattedValue<f64>>,
397
398 #[serde(skip_serializing_if = "Option::is_none")]
400 pub target_high_price: Option<super::FormattedValue<f64>>,
401
402 #[serde(skip_serializing_if = "Option::is_none")]
404 pub target_low_price: Option<super::FormattedValue<f64>>,
405
406 #[serde(skip_serializing_if = "Option::is_none")]
408 pub target_mean_price: Option<super::FormattedValue<f64>>,
409
410 #[serde(skip_serializing_if = "Option::is_none")]
412 pub target_median_price: Option<super::FormattedValue<f64>>,
413
414 #[serde(skip_serializing_if = "Option::is_none")]
416 pub recommendation_mean: Option<super::FormattedValue<f64>>,
417
418 #[serde(skip_serializing_if = "Option::is_none")]
420 pub recommendation_key: Option<String>,
421
422 #[serde(skip_serializing_if = "Option::is_none")]
424 pub number_of_analyst_opinions: Option<super::FormattedValue<i64>>,
425
426 #[serde(skip_serializing_if = "Option::is_none")]
428 pub total_cash: Option<super::FormattedValue<i64>>,
429
430 #[serde(skip_serializing_if = "Option::is_none")]
432 pub total_cash_per_share: Option<super::FormattedValue<f64>>,
433
434 #[serde(skip_serializing_if = "Option::is_none")]
436 pub ebitda: Option<super::FormattedValue<i64>>,
437
438 #[serde(skip_serializing_if = "Option::is_none")]
440 pub total_debt: Option<super::FormattedValue<i64>>,
441
442 #[serde(skip_serializing_if = "Option::is_none")]
444 pub total_revenue: Option<super::FormattedValue<i64>>,
445
446 #[serde(skip_serializing_if = "Option::is_none")]
448 pub net_income_to_common: Option<super::FormattedValue<i64>>,
449
450 #[serde(skip_serializing_if = "Option::is_none")]
452 pub debt_to_equity: Option<super::FormattedValue<f64>>,
453
454 #[serde(skip_serializing_if = "Option::is_none")]
456 pub revenue_per_share: Option<super::FormattedValue<f64>>,
457
458 #[serde(skip_serializing_if = "Option::is_none")]
460 pub return_on_assets: Option<super::FormattedValue<f64>>,
461
462 #[serde(skip_serializing_if = "Option::is_none")]
464 pub return_on_equity: Option<super::FormattedValue<f64>>,
465
466 #[serde(skip_serializing_if = "Option::is_none")]
468 pub free_cashflow: Option<super::FormattedValue<i64>>,
469
470 #[serde(skip_serializing_if = "Option::is_none")]
472 pub operating_cashflow: Option<super::FormattedValue<i64>>,
473
474 #[serde(skip_serializing_if = "Option::is_none")]
477 pub profit_margins: Option<super::FormattedValue<f64>>,
478
479 #[serde(skip_serializing_if = "Option::is_none")]
481 pub gross_margins: Option<super::FormattedValue<f64>>,
482
483 #[serde(skip_serializing_if = "Option::is_none")]
485 pub ebitda_margins: Option<super::FormattedValue<f64>>,
486
487 #[serde(skip_serializing_if = "Option::is_none")]
489 pub operating_margins: Option<super::FormattedValue<f64>>,
490
491 #[serde(skip_serializing_if = "Option::is_none")]
493 pub gross_profits: Option<super::FormattedValue<i64>>,
494
495 #[serde(skip_serializing_if = "Option::is_none")]
498 pub earnings_growth: Option<super::FormattedValue<f64>>,
499
500 #[serde(skip_serializing_if = "Option::is_none")]
502 pub revenue_growth: Option<super::FormattedValue<f64>>,
503
504 #[serde(skip_serializing_if = "Option::is_none")]
506 pub earnings_quarterly_growth: Option<super::FormattedValue<f64>>,
507
508 #[serde(skip_serializing_if = "Option::is_none")]
511 pub current_ratio: Option<super::FormattedValue<f64>>,
512
513 #[serde(skip_serializing_if = "Option::is_none")]
515 pub quick_ratio: Option<super::FormattedValue<f64>>,
516
517 #[serde(skip_serializing_if = "Option::is_none")]
520 pub trailing_eps: Option<super::FormattedValue<f64>>,
521
522 #[serde(skip_serializing_if = "Option::is_none")]
524 pub forward_eps: Option<super::FormattedValue<f64>>,
525
526 #[serde(skip_serializing_if = "Option::is_none")]
528 pub book_value: Option<super::FormattedValue<f64>>,
529
530 #[serde(skip_serializing_if = "Option::is_none")]
533 pub sector: Option<String>,
534
535 #[serde(skip_serializing_if = "Option::is_none")]
537 pub sector_key: Option<String>,
538
539 #[serde(skip_serializing_if = "Option::is_none")]
541 pub sector_disp: Option<String>,
542
543 #[serde(skip_serializing_if = "Option::is_none")]
545 pub industry: Option<String>,
546
547 #[serde(skip_serializing_if = "Option::is_none")]
549 pub industry_key: Option<String>,
550
551 #[serde(skip_serializing_if = "Option::is_none")]
553 pub industry_disp: Option<String>,
554
555 #[serde(skip_serializing_if = "Option::is_none")]
557 pub long_business_summary: Option<String>,
558
559 #[serde(skip_serializing_if = "Option::is_none")]
561 pub website: Option<String>,
562
563 #[serde(skip_serializing_if = "Option::is_none")]
565 pub ir_website: Option<String>,
566
567 #[serde(skip_serializing_if = "Option::is_none")]
569 pub address1: Option<String>,
570
571 #[serde(skip_serializing_if = "Option::is_none")]
573 pub city: Option<String>,
574
575 #[serde(skip_serializing_if = "Option::is_none")]
577 pub state: Option<String>,
578
579 #[serde(skip_serializing_if = "Option::is_none")]
581 pub zip: Option<String>,
582
583 #[serde(skip_serializing_if = "Option::is_none")]
585 pub country: Option<String>,
586
587 #[serde(skip_serializing_if = "Option::is_none")]
589 pub phone: Option<String>,
590
591 #[serde(skip_serializing_if = "Option::is_none")]
593 pub full_time_employees: Option<i64>,
594
595 #[serde(skip_serializing_if = "Option::is_none")]
597 pub category: Option<String>,
598
599 #[serde(skip_serializing_if = "Option::is_none")]
601 pub fund_family: Option<String>,
602
603 #[serde(skip_serializing_if = "Option::is_none")]
606 pub audit_risk: Option<i32>,
607
608 #[serde(skip_serializing_if = "Option::is_none")]
610 pub board_risk: Option<i32>,
611
612 #[serde(skip_serializing_if = "Option::is_none")]
614 pub compensation_risk: Option<i32>,
615
616 #[serde(skip_serializing_if = "Option::is_none")]
618 pub shareholder_rights_risk: Option<i32>,
619
620 #[serde(skip_serializing_if = "Option::is_none")]
622 pub overall_risk: Option<i32>,
623
624 #[serde(skip_serializing_if = "Option::is_none")]
627 pub time_zone_full_name: Option<String>,
628
629 #[serde(skip_serializing_if = "Option::is_none")]
631 pub time_zone_short_name: Option<String>,
632
633 #[serde(skip_serializing_if = "Option::is_none")]
635 pub gmt_off_set_milliseconds: Option<i64>,
636
637 #[serde(skip_serializing_if = "Option::is_none")]
639 pub first_trade_date_epoch_utc: Option<i64>,
640
641 #[serde(skip_serializing_if = "Option::is_none")]
643 pub message_board_id: Option<String>,
644
645 #[serde(skip_serializing_if = "Option::is_none")]
647 pub exchange_data_delayed_by: Option<i32>,
648
649 #[serde(skip_serializing_if = "Option::is_none")]
652 pub nav_price: Option<super::FormattedValue<f64>>,
653
654 #[serde(skip_serializing_if = "Option::is_none")]
656 pub total_assets: Option<super::FormattedValue<i64>>,
657
658 #[serde(rename = "yield", skip_serializing_if = "Option::is_none")]
660 pub yield_value: Option<super::FormattedValue<f64>>,
661
662 #[serde(skip_serializing_if = "Option::is_none")]
665 pub last_split_factor: Option<String>,
666
667 #[serde(skip_serializing_if = "Option::is_none")]
669 pub last_split_date: Option<super::FormattedValue<i64>>,
670
671 #[serde(skip_serializing_if = "Option::is_none")]
673 pub last_fiscal_year_end: Option<super::FormattedValue<i64>>,
674
675 #[serde(skip_serializing_if = "Option::is_none")]
677 pub next_fiscal_year_end: Option<super::FormattedValue<i64>>,
678
679 #[serde(skip_serializing_if = "Option::is_none")]
681 pub most_recent_quarter: Option<super::FormattedValue<i64>>,
682
683 #[serde(skip_serializing_if = "Option::is_none")]
686 pub price_hint: Option<super::FormattedValue<i64>>,
687
688 #[serde(skip_serializing_if = "Option::is_none")]
690 pub tradeable: Option<bool>,
691
692 #[serde(skip_serializing_if = "Option::is_none")]
694 pub financial_currency: Option<String>,
695
696 #[serde(skip_serializing_if = "Option::is_none")]
699 pub company_officers: Option<Vec<super::CompanyOfficer>>,
700
701 #[serde(skip_serializing_if = "Option::is_none")]
703 pub earnings: Option<Earnings>,
704
705 #[serde(skip_serializing_if = "Option::is_none")]
707 pub calendar_events: Option<CalendarEvents>,
708
709 #[serde(skip_serializing_if = "Option::is_none")]
711 pub recommendation_trend: Option<RecommendationTrend>,
712
713 #[serde(skip_serializing_if = "Option::is_none")]
715 pub upgrade_downgrade_history: Option<UpgradeDowngradeHistory>,
716
717 #[serde(skip_serializing_if = "Option::is_none")]
719 pub earnings_history: Option<EarningsHistory>,
720
721 #[serde(skip_serializing_if = "Option::is_none")]
723 pub earnings_trend: Option<EarningsTrend>,
724
725 #[serde(skip_serializing_if = "Option::is_none")]
727 pub insider_holders: Option<InsiderHolders>,
728
729 #[serde(skip_serializing_if = "Option::is_none")]
731 pub insider_transactions: Option<InsiderTransactions>,
732
733 #[serde(skip_serializing_if = "Option::is_none")]
735 pub institution_ownership: Option<InstitutionOwnership>,
736
737 #[serde(skip_serializing_if = "Option::is_none")]
739 pub fund_ownership: Option<FundOwnership>,
740
741 #[serde(skip_serializing_if = "Option::is_none")]
743 pub major_holders_breakdown: Option<MajorHoldersBreakdown>,
744
745 #[serde(skip_serializing_if = "Option::is_none")]
747 pub net_share_purchase_activity: Option<NetSharePurchaseActivity>,
748
749 #[serde(skip_serializing_if = "Option::is_none")]
751 pub sec_filings: Option<SecFilings>,
752
753 #[serde(skip_serializing_if = "Option::is_none")]
755 pub balance_sheet_history: Option<BalanceSheetHistory>,
756
757 #[serde(skip_serializing_if = "Option::is_none")]
759 pub balance_sheet_history_quarterly: Option<BalanceSheetHistoryQuarterly>,
760
761 #[serde(skip_serializing_if = "Option::is_none")]
763 pub cashflow_statement_history: Option<CashflowStatementHistory>,
764
765 #[serde(skip_serializing_if = "Option::is_none")]
767 pub cashflow_statement_history_quarterly: Option<CashflowStatementHistoryQuarterly>,
768
769 #[serde(skip_serializing_if = "Option::is_none")]
771 pub income_statement_history: Option<IncomeStatementHistory>,
772
773 #[serde(skip_serializing_if = "Option::is_none")]
775 pub income_statement_history_quarterly: Option<IncomeStatementHistoryQuarterly>,
776
777 #[serde(skip_serializing_if = "Option::is_none")]
779 pub equity_performance: Option<EquityPerformance>,
780
781 #[serde(skip_serializing_if = "Option::is_none")]
783 pub index_trend: Option<IndexTrend>,
784
785 #[serde(skip_serializing_if = "Option::is_none")]
787 pub industry_trend: Option<IndustryTrend>,
788
789 #[serde(skip_serializing_if = "Option::is_none")]
791 pub sector_trend: Option<SectorTrend>,
792
793 #[serde(skip_serializing_if = "Option::is_none")]
795 pub fund_profile: Option<FundProfile>,
796
797 #[serde(skip_serializing_if = "Option::is_none")]
799 pub fund_performance: Option<FundPerformance>,
800
801 #[serde(skip_serializing_if = "Option::is_none")]
803 pub top_holdings: Option<TopHoldings>,
804}
805
806impl Quote {
807 pub(crate) fn from_response(
818 response: &QuoteSummaryResponse,
819 logo_url: Option<String>,
820 company_logo_url: Option<String>,
821 ) -> Self {
822 let price: Option<Price> = response.get_typed("price").ok();
824 let quote_type: Option<QuoteTypeData> = response.get_typed("quoteType").ok();
825 let summary_detail: Option<SummaryDetail> = response.get_typed("summaryDetail").ok();
826 let financial_data: Option<FinancialData> = response.get_typed("financialData").ok();
827 let key_stats: Option<DefaultKeyStatistics> =
828 response.get_typed("defaultKeyStatistics").ok();
829 let asset_profile: Option<AssetProfile> = response.get_typed("assetProfile").ok();
830 let summary_profile: Option<SummaryProfile> = response.get_typed("summaryProfile").ok();
831
832 Self {
833 symbol: response.symbol.clone(),
834 logo_url,
835 company_logo_url,
836
837 short_name: price
840 .as_ref()
841 .and_then(|p| p.short_name.clone())
842 .or_else(|| quote_type.as_ref().and_then(|q| q.short_name.clone())),
843
844 long_name: price
845 .as_ref()
846 .and_then(|p| p.long_name.clone())
847 .or_else(|| quote_type.as_ref().and_then(|q| q.long_name.clone())),
848
849 exchange: price
850 .as_ref()
851 .and_then(|p| p.exchange.clone())
852 .or_else(|| quote_type.as_ref().and_then(|q| q.exchange.clone())),
853
854 exchange_name: price.as_ref().and_then(|p| p.exchange_name.clone()),
855
856 quote_type: price
857 .as_ref()
858 .and_then(|p| p.quote_type.clone())
859 .or_else(|| quote_type.as_ref().and_then(|q| q.quote_type.clone())),
860
861 currency: price.as_ref().and_then(|p| p.currency.clone()).or_else(|| {
862 summary_detail
863 .as_ref()
864 .and_then(|s| s.currency.clone())
865 .or_else(|| {
866 financial_data
867 .as_ref()
868 .and_then(|f| f.financial_currency.clone())
869 })
870 }),
871
872 currency_symbol: price.as_ref().and_then(|p| p.currency_symbol.clone()),
873
874 underlying_symbol: price
875 .as_ref()
876 .and_then(|p| p.underlying_symbol.clone())
877 .or_else(|| {
878 quote_type
879 .as_ref()
880 .and_then(|q| q.underlying_symbol.clone())
881 }),
882 from_currency: price
883 .as_ref()
884 .and_then(|p| p.from_currency.clone())
885 .or_else(|| {
886 summary_detail
887 .as_ref()
888 .and_then(|s| s.from_currency.clone())
889 }),
890 to_currency: price
891 .as_ref()
892 .and_then(|p| p.to_currency.clone())
893 .or_else(|| summary_detail.as_ref().and_then(|s| s.to_currency.clone())),
894
895 regular_market_price: price.as_ref().and_then(|p| p.regular_market_price.clone()),
897 regular_market_change: price.as_ref().and_then(|p| p.regular_market_change.clone()),
898 regular_market_change_percent: price
899 .as_ref()
900 .and_then(|p| p.regular_market_change_percent.clone()),
901 regular_market_time: price.as_ref().and_then(|p| p.regular_market_time),
902 regular_market_day_high: price
903 .as_ref()
904 .and_then(|p| p.regular_market_day_high.clone()),
905 regular_market_day_low: price
906 .as_ref()
907 .and_then(|p| p.regular_market_day_low.clone()),
908 regular_market_open: price.as_ref().and_then(|p| p.regular_market_open.clone()),
909 regular_market_previous_close: price
910 .as_ref()
911 .and_then(|p| p.regular_market_previous_close.clone()),
912 regular_market_volume: price.as_ref().and_then(|p| p.regular_market_volume.clone()),
913 market_state: price.as_ref().and_then(|p| p.market_state.clone()),
914
915 day_high: summary_detail.as_ref().and_then(|s| s.day_high.clone()),
917 day_low: summary_detail.as_ref().and_then(|s| s.day_low.clone()),
918 open: summary_detail.as_ref().and_then(|s| s.open.clone()),
919 previous_close: summary_detail
920 .as_ref()
921 .and_then(|s| s.previous_close.clone()),
922 volume: summary_detail.as_ref().and_then(|s| s.volume.clone()),
923
924 all_time_high: summary_detail
926 .as_ref()
927 .and_then(|s| s.all_time_high.clone()),
928 all_time_low: summary_detail.as_ref().and_then(|s| s.all_time_low.clone()),
929
930 pre_market_price: price.as_ref().and_then(|p| p.pre_market_price.clone()),
932 pre_market_change: price.as_ref().and_then(|p| p.pre_market_change.clone()),
933 pre_market_change_percent: price
934 .as_ref()
935 .and_then(|p| p.pre_market_change_percent.clone()),
936 pre_market_time: price.as_ref().and_then(|p| p.pre_market_time),
937 post_market_price: price.as_ref().and_then(|p| p.post_market_price.clone()),
938 post_market_change: price.as_ref().and_then(|p| p.post_market_change.clone()),
939 post_market_change_percent: price
940 .as_ref()
941 .and_then(|p| p.post_market_change_percent.clone()),
942 post_market_time: price.as_ref().and_then(|p| p.post_market_time),
943
944 average_daily_volume10_day: price
947 .as_ref()
948 .and_then(|p| p.average_daily_volume10_day.clone())
949 .or_else(|| {
950 summary_detail
951 .as_ref()
952 .and_then(|s| s.average_daily_volume10_day.clone())
953 }),
954 average_daily_volume3_month: price
955 .as_ref()
956 .and_then(|p| p.average_daily_volume3_month.clone()),
957 average_volume: summary_detail
958 .as_ref()
959 .and_then(|s| s.average_volume.clone()),
960 average_volume10days: summary_detail
961 .as_ref()
962 .and_then(|s| s.average_volume10days.clone()),
963
964 market_cap: price.as_ref().and_then(|p| p.market_cap.clone()),
967 enterprise_value: key_stats.as_ref().and_then(|k| k.enterprise_value.clone()),
968 enterprise_to_revenue: key_stats
969 .as_ref()
970 .and_then(|k| k.enterprise_to_revenue.clone()),
971 enterprise_to_ebitda: key_stats
972 .as_ref()
973 .and_then(|k| k.enterprise_to_ebitda.clone()),
974 price_to_book: key_stats.as_ref().and_then(|k| k.price_to_book.clone()),
975 price_to_sales_trailing12_months: summary_detail
976 .as_ref()
977 .and_then(|s| s.price_to_sales_trailing12_months.clone()),
978
979 forward_pe: summary_detail
982 .as_ref()
983 .and_then(|s| s.forward_pe.clone())
984 .or_else(|| key_stats.as_ref().and_then(|k| k.forward_pe.clone())),
985 trailing_pe: summary_detail.as_ref().and_then(|s| s.trailing_pe.clone()),
986
987 beta: summary_detail
990 .as_ref()
991 .and_then(|s| s.beta.clone())
992 .or_else(|| key_stats.as_ref().and_then(|k| k.beta.clone())),
993
994 fifty_two_week_high: summary_detail
996 .as_ref()
997 .and_then(|s| s.fifty_two_week_high.clone()),
998 fifty_two_week_low: summary_detail
999 .as_ref()
1000 .and_then(|s| s.fifty_two_week_low.clone()),
1001 fifty_day_average: summary_detail
1002 .as_ref()
1003 .and_then(|s| s.fifty_day_average.clone()),
1004 two_hundred_day_average: summary_detail
1005 .as_ref()
1006 .and_then(|s| s.two_hundred_day_average.clone()),
1007 week_52_change: key_stats.as_ref().and_then(|k| k.week_52_change.clone()),
1008 sand_p_52_week_change: key_stats
1009 .as_ref()
1010 .and_then(|k| k.sand_p_52_week_change.clone()),
1011
1012 dividend_rate: summary_detail
1014 .as_ref()
1015 .and_then(|s| s.dividend_rate.clone()),
1016 dividend_yield: summary_detail
1017 .as_ref()
1018 .and_then(|s| s.dividend_yield.clone()),
1019 trailing_annual_dividend_rate: summary_detail
1020 .as_ref()
1021 .and_then(|s| s.trailing_annual_dividend_rate.clone()),
1022 trailing_annual_dividend_yield: summary_detail
1023 .as_ref()
1024 .and_then(|s| s.trailing_annual_dividend_yield.clone()),
1025 five_year_avg_dividend_yield: summary_detail
1026 .as_ref()
1027 .and_then(|s| s.five_year_avg_dividend_yield.clone()),
1028 ex_dividend_date: summary_detail
1029 .as_ref()
1030 .and_then(|s| s.ex_dividend_date.clone()),
1031 payout_ratio: summary_detail.as_ref().and_then(|s| s.payout_ratio.clone()),
1032 last_dividend_value: key_stats
1033 .as_ref()
1034 .and_then(|k| k.last_dividend_value.clone()),
1035 last_dividend_date: key_stats
1036 .as_ref()
1037 .and_then(|k| k.last_dividend_date.clone()),
1038
1039 bid: summary_detail.as_ref().and_then(|s| s.bid.clone()),
1041 bid_size: summary_detail.as_ref().and_then(|s| s.bid_size.clone()),
1042 ask: summary_detail.as_ref().and_then(|s| s.ask.clone()),
1043 ask_size: summary_detail.as_ref().and_then(|s| s.ask_size.clone()),
1044
1045 shares_outstanding: key_stats
1047 .as_ref()
1048 .and_then(|k| k.shares_outstanding.clone()),
1049 float_shares: key_stats.as_ref().and_then(|k| k.float_shares.clone()),
1050 implied_shares_outstanding: key_stats
1051 .as_ref()
1052 .and_then(|k| k.implied_shares_outstanding.clone()),
1053 held_percent_insiders: key_stats
1054 .as_ref()
1055 .and_then(|k| k.held_percent_insiders.clone()),
1056 held_percent_institutions: key_stats
1057 .as_ref()
1058 .and_then(|k| k.held_percent_institutions.clone()),
1059 shares_short: key_stats.as_ref().and_then(|k| k.shares_short.clone()),
1060 shares_short_prior_month: key_stats
1061 .as_ref()
1062 .and_then(|k| k.shares_short_prior_month.clone()),
1063 short_ratio: key_stats.as_ref().and_then(|k| k.short_ratio.clone()),
1064 short_percent_of_float: key_stats
1065 .as_ref()
1066 .and_then(|k| k.short_percent_of_float.clone()),
1067 shares_percent_shares_out: key_stats
1068 .as_ref()
1069 .and_then(|k| k.shares_percent_shares_out.clone()),
1070 date_short_interest: key_stats
1071 .as_ref()
1072 .and_then(|k| k.date_short_interest.clone()),
1073
1074 current_price: financial_data
1076 .as_ref()
1077 .and_then(|f| f.current_price.clone()),
1078 target_high_price: financial_data
1079 .as_ref()
1080 .and_then(|f| f.target_high_price.clone()),
1081 target_low_price: financial_data
1082 .as_ref()
1083 .and_then(|f| f.target_low_price.clone()),
1084 target_mean_price: financial_data
1085 .as_ref()
1086 .and_then(|f| f.target_mean_price.clone()),
1087 target_median_price: financial_data
1088 .as_ref()
1089 .and_then(|f| f.target_median_price.clone()),
1090 recommendation_mean: financial_data
1091 .as_ref()
1092 .and_then(|f| f.recommendation_mean.clone()),
1093 recommendation_key: financial_data
1094 .as_ref()
1095 .and_then(|f| f.recommendation_key.clone()),
1096 number_of_analyst_opinions: financial_data
1097 .as_ref()
1098 .and_then(|f| f.number_of_analyst_opinions.clone()),
1099 total_cash: financial_data.as_ref().and_then(|f| f.total_cash.clone()),
1100 total_cash_per_share: financial_data
1101 .as_ref()
1102 .and_then(|f| f.total_cash_per_share.clone()),
1103 ebitda: financial_data.as_ref().and_then(|f| f.ebitda.clone()),
1104 total_debt: financial_data.as_ref().and_then(|f| f.total_debt.clone()),
1105 total_revenue: financial_data
1106 .as_ref()
1107 .and_then(|f| f.total_revenue.clone()),
1108 net_income_to_common: key_stats
1109 .as_ref()
1110 .and_then(|k| k.net_income_to_common.clone()),
1111 debt_to_equity: financial_data
1112 .as_ref()
1113 .and_then(|f| f.debt_to_equity.clone()),
1114 revenue_per_share: financial_data
1115 .as_ref()
1116 .and_then(|f| f.revenue_per_share.clone()),
1117 return_on_assets: financial_data
1118 .as_ref()
1119 .and_then(|f| f.return_on_assets.clone()),
1120 return_on_equity: financial_data
1121 .as_ref()
1122 .and_then(|f| f.return_on_equity.clone()),
1123 free_cashflow: financial_data
1124 .as_ref()
1125 .and_then(|f| f.free_cashflow.clone()),
1126 operating_cashflow: financial_data
1127 .as_ref()
1128 .and_then(|f| f.operating_cashflow.clone()),
1129
1130 profit_margins: financial_data
1133 .as_ref()
1134 .and_then(|f| f.profit_margins.clone()),
1135 gross_margins: financial_data
1136 .as_ref()
1137 .and_then(|f| f.gross_margins.clone()),
1138 ebitda_margins: financial_data
1139 .as_ref()
1140 .and_then(|f| f.ebitda_margins.clone()),
1141 operating_margins: financial_data
1142 .as_ref()
1143 .and_then(|f| f.operating_margins.clone()),
1144 gross_profits: financial_data
1145 .as_ref()
1146 .and_then(|f| f.gross_profits.clone()),
1147
1148 earnings_growth: financial_data
1150 .as_ref()
1151 .and_then(|f| f.earnings_growth.clone()),
1152 revenue_growth: financial_data
1153 .as_ref()
1154 .and_then(|f| f.revenue_growth.clone()),
1155 earnings_quarterly_growth: key_stats
1156 .as_ref()
1157 .and_then(|k| k.earnings_quarterly_growth.clone()),
1158
1159 current_ratio: financial_data
1161 .as_ref()
1162 .and_then(|f| f.current_ratio.clone()),
1163 quick_ratio: financial_data.as_ref().and_then(|f| f.quick_ratio.clone()),
1164
1165 trailing_eps: key_stats.as_ref().and_then(|k| k.trailing_eps.clone()),
1167 forward_eps: key_stats.as_ref().and_then(|k| k.forward_eps.clone()),
1168 book_value: key_stats.as_ref().and_then(|k| k.book_value.clone()),
1169
1170 sector: asset_profile
1173 .as_ref()
1174 .and_then(|a| a.sector.clone())
1175 .or_else(|| summary_profile.as_ref().and_then(|s| s.sector.clone())),
1176 sector_key: asset_profile.as_ref().and_then(|a| a.sector_key.clone()),
1177 sector_disp: asset_profile.as_ref().and_then(|a| a.sector_disp.clone()),
1178 industry: asset_profile
1179 .as_ref()
1180 .and_then(|a| a.industry.clone())
1181 .or_else(|| summary_profile.as_ref().and_then(|s| s.industry.clone())),
1182 industry_key: asset_profile.as_ref().and_then(|a| a.industry_key.clone()),
1183 industry_disp: asset_profile.as_ref().and_then(|a| a.industry_disp.clone()),
1184 long_business_summary: asset_profile
1185 .as_ref()
1186 .and_then(|a| a.long_business_summary.clone())
1187 .or_else(|| {
1188 summary_profile
1189 .as_ref()
1190 .and_then(|s| s.long_business_summary.clone())
1191 }),
1192 address1: asset_profile
1193 .as_ref()
1194 .and_then(|a| a.address1.clone())
1195 .or_else(|| summary_profile.as_ref().and_then(|s| s.address1.clone())),
1196 city: asset_profile
1197 .as_ref()
1198 .and_then(|a| a.city.clone())
1199 .or_else(|| summary_profile.as_ref().and_then(|s| s.city.clone())),
1200 state: asset_profile
1201 .as_ref()
1202 .and_then(|a| a.state.clone())
1203 .or_else(|| summary_profile.as_ref().and_then(|s| s.state.clone())),
1204 zip: asset_profile
1205 .as_ref()
1206 .and_then(|a| a.zip.clone())
1207 .or_else(|| summary_profile.as_ref().and_then(|s| s.zip.clone())),
1208 country: asset_profile
1209 .as_ref()
1210 .and_then(|a| a.country.clone())
1211 .or_else(|| summary_profile.as_ref().and_then(|s| s.country.clone())),
1212 phone: asset_profile
1213 .as_ref()
1214 .and_then(|a| a.phone.clone())
1215 .or_else(|| summary_profile.as_ref().and_then(|s| s.phone.clone())),
1216 full_time_employees: asset_profile
1217 .as_ref()
1218 .and_then(|a| a.full_time_employees)
1219 .or_else(|| summary_profile.as_ref().and_then(|s| s.full_time_employees)),
1220
1221 website: asset_profile
1222 .as_ref()
1223 .and_then(|a| a.website.clone())
1224 .or_else(|| summary_profile.as_ref().and_then(|s| s.website.clone())),
1225 ir_website: summary_profile.as_ref().and_then(|s| s.ir_website.clone()),
1226
1227 category: key_stats.as_ref().and_then(|k| k.category.clone()),
1228 fund_family: key_stats.as_ref().and_then(|k| k.fund_family.clone()),
1229
1230 audit_risk: asset_profile.as_ref().and_then(|a| a.audit_risk),
1232 board_risk: asset_profile.as_ref().and_then(|a| a.board_risk),
1233 compensation_risk: asset_profile.as_ref().and_then(|a| a.compensation_risk),
1234 shareholder_rights_risk: asset_profile
1235 .as_ref()
1236 .and_then(|a| a.shareholder_rights_risk),
1237 overall_risk: asset_profile.as_ref().and_then(|a| a.overall_risk),
1238
1239 time_zone_full_name: quote_type
1241 .as_ref()
1242 .and_then(|q| q.time_zone_full_name.clone()),
1243 time_zone_short_name: quote_type
1244 .as_ref()
1245 .and_then(|q| q.time_zone_short_name.clone()),
1246 gmt_off_set_milliseconds: quote_type.as_ref().and_then(|q| q.gmt_off_set_milliseconds),
1247 first_trade_date_epoch_utc: quote_type
1248 .as_ref()
1249 .and_then(|q| q.first_trade_date_epoch_utc),
1250 message_board_id: quote_type.as_ref().and_then(|q| q.message_board_id.clone()),
1251 exchange_data_delayed_by: price.as_ref().and_then(|p| p.exchange_data_delayed_by),
1252
1253 nav_price: summary_detail.as_ref().and_then(|s| s.nav_price.clone()),
1255 total_assets: summary_detail.as_ref().and_then(|s| s.total_assets.clone()),
1256 yield_value: summary_detail.as_ref().and_then(|s| s.yield_value.clone()),
1257
1258 last_split_factor: key_stats.as_ref().and_then(|k| k.last_split_factor.clone()),
1260 last_split_date: key_stats.as_ref().and_then(|k| k.last_split_date.clone()),
1261 last_fiscal_year_end: key_stats
1262 .as_ref()
1263 .and_then(|k| k.last_fiscal_year_end.clone()),
1264 next_fiscal_year_end: key_stats
1265 .as_ref()
1266 .and_then(|k| k.next_fiscal_year_end.clone()),
1267 most_recent_quarter: key_stats
1268 .as_ref()
1269 .and_then(|k| k.most_recent_quarter.clone()),
1270
1271 price_hint: price.as_ref().and_then(|p| p.price_hint.clone()),
1274 tradeable: summary_detail.as_ref().and_then(|s| s.tradeable),
1275 financial_currency: financial_data
1276 .as_ref()
1277 .and_then(|f| f.financial_currency.clone()),
1278
1279 company_officers: asset_profile.as_ref().map(|a| a.company_officers.clone()),
1281 earnings: response.get_typed("earnings").ok(),
1282 calendar_events: response.get_typed("calendarEvents").ok(),
1283 recommendation_trend: response.get_typed("recommendationTrend").ok(),
1284 upgrade_downgrade_history: response.get_typed("upgradeDowngradeHistory").ok(),
1285 earnings_history: response.get_typed("earningsHistory").ok(),
1286 earnings_trend: response.get_typed("earningsTrend").ok(),
1287 insider_holders: response.get_typed("insiderHolders").ok(),
1288 insider_transactions: response.get_typed("insiderTransactions").ok(),
1289 institution_ownership: response.get_typed("institutionOwnership").ok(),
1290 fund_ownership: response.get_typed("fundOwnership").ok(),
1291 major_holders_breakdown: response.get_typed("majorHoldersBreakdown").ok(),
1292 net_share_purchase_activity: response.get_typed("netSharePurchaseActivity").ok(),
1293 sec_filings: response.get_typed("secFilings").ok(),
1294 balance_sheet_history: response.get_typed("balanceSheetHistory").ok(),
1295 balance_sheet_history_quarterly: response
1296 .get_typed("balanceSheetHistoryQuarterly")
1297 .ok(),
1298 cashflow_statement_history: response.get_typed("cashflowStatementHistory").ok(),
1299 cashflow_statement_history_quarterly: response
1300 .get_typed("cashflowStatementHistoryQuarterly")
1301 .ok(),
1302 income_statement_history: response.get_typed("incomeStatementHistory").ok(),
1303 income_statement_history_quarterly: response
1304 .get_typed("incomeStatementHistoryQuarterly")
1305 .ok(),
1306 equity_performance: response.get_typed("equityPerformance").ok(),
1307 index_trend: response.get_typed("indexTrend").ok(),
1308 industry_trend: response.get_typed("industryTrend").ok(),
1309 sector_trend: response.get_typed("sectorTrend").ok(),
1310 fund_profile: response.get_typed("fundProfile").ok(),
1311 fund_performance: response.get_typed("fundPerformance").ok(),
1312 top_holdings: response.get_typed("topHoldings").ok(),
1313 }
1314 }
1315
1316 pub fn live_price(&self) -> Option<f64> {
1321 if self.market_state.as_deref() == Some("POST") {
1322 self.post_market_price
1323 .as_ref()
1324 .and_then(|p| p.raw)
1325 .or_else(|| self.regular_market_price.as_ref()?.raw)
1326 } else if self.market_state.as_deref() == Some("PRE") {
1327 self.pre_market_price
1328 .as_ref()
1329 .and_then(|p| p.raw)
1330 .or_else(|| self.regular_market_price.as_ref()?.raw)
1331 } else {
1332 self.regular_market_price.as_ref()?.raw
1333 }
1334 }
1335
1336 pub fn day_range(&self) -> Option<(f64, f64)> {
1338 let low = self.regular_market_day_low.as_ref()?.raw?;
1339 let high = self.regular_market_day_high.as_ref()?.raw?;
1340 Some((low, high))
1341 }
1342
1343 pub fn week_52_range(&self) -> Option<(f64, f64)> {
1345 let low = self.fifty_two_week_low.as_ref()?.raw?;
1346 let high = self.fifty_two_week_high.as_ref()?.raw?;
1347 Some((low, high))
1348 }
1349
1350 pub fn is_market_open(&self) -> bool {
1352 self.market_state.as_deref() == Some("REGULAR")
1353 }
1354
1355 pub fn is_pre_market(&self) -> bool {
1357 self.market_state.as_deref() == Some("PRE")
1358 }
1359
1360 pub fn is_post_market(&self) -> bool {
1362 self.market_state.as_deref() == Some("POST")
1363 }
1364
1365 pub(crate) fn from_batch_response(json: &serde_json::Value) -> Result<Self, String> {
1370 let symbol = json
1371 .get("symbol")
1372 .and_then(|v| v.as_str())
1373 .ok_or("Missing symbol")?
1374 .to_string();
1375
1376 let get_f64 = |key: &str| -> Option<super::FormattedValue<f64>> {
1379 json.get(key).and_then(|v| {
1380 if let Some(raw) = v.as_f64() {
1381 Some(super::FormattedValue {
1383 raw: Some(raw),
1384 fmt: None,
1385 long_fmt: None,
1386 })
1387 } else if v.is_object() {
1388 Some(super::FormattedValue {
1390 raw: v.get("raw").and_then(|r| r.as_f64()),
1391 fmt: v.get("fmt").and_then(|f| f.as_str()).map(|s| s.to_string()),
1392 long_fmt: v
1393 .get("longFmt")
1394 .and_then(|f| f.as_str())
1395 .map(|s| s.to_string()),
1396 })
1397 } else {
1398 None
1399 }
1400 })
1401 };
1402
1403 let get_i64 = |key: &str| -> Option<super::FormattedValue<i64>> {
1406 json.get(key).and_then(|v| {
1407 if let Some(raw) = v.as_i64() {
1408 Some(super::FormattedValue {
1410 raw: Some(raw),
1411 fmt: None,
1412 long_fmt: None,
1413 })
1414 } else if v.is_object() {
1415 Some(super::FormattedValue {
1417 raw: v.get("raw").and_then(|r| r.as_i64()),
1418 fmt: v.get("fmt").and_then(|f| f.as_str()).map(|s| s.to_string()),
1419 long_fmt: v
1420 .get("longFmt")
1421 .and_then(|f| f.as_str())
1422 .map(|s| s.to_string()),
1423 })
1424 } else {
1425 None
1426 }
1427 })
1428 };
1429
1430 let get_str = |key: &str| -> Option<String> {
1432 json.get(key)
1433 .and_then(|v| v.as_str())
1434 .map(|s| s.to_string())
1435 };
1436
1437 Ok(Self {
1438 symbol,
1439 logo_url: get_str("logoUrl"),
1440 company_logo_url: get_str("companyLogoUrl"),
1441
1442 short_name: get_str("shortName"),
1444 long_name: get_str("longName"),
1445 exchange: get_str("exchange"),
1446 exchange_name: get_str("fullExchangeName"),
1447 quote_type: get_str("quoteType"),
1448 currency: get_str("currency"),
1449 currency_symbol: get_str("currencySymbol"),
1450 underlying_symbol: get_str("underlyingSymbol"),
1451 from_currency: get_str("fromCurrency"),
1452 to_currency: get_str("toCurrency"),
1453
1454 regular_market_price: get_f64("regularMarketPrice"),
1456 regular_market_change: get_f64("regularMarketChange"),
1457 regular_market_change_percent: get_f64("regularMarketChangePercent"),
1458 regular_market_time: json.get("regularMarketTime").and_then(|v| v.as_i64()),
1459 regular_market_day_high: get_f64("regularMarketDayHigh"),
1460 regular_market_day_low: get_f64("regularMarketDayLow"),
1461 regular_market_open: get_f64("regularMarketOpen"),
1462 regular_market_previous_close: get_f64("regularMarketPreviousClose"),
1463 regular_market_volume: get_i64("regularMarketVolume"),
1464 market_state: get_str("marketState"),
1465
1466 day_high: get_f64("dayHigh"),
1468 day_low: get_f64("dayLow"),
1469 open: get_f64("open"),
1470 previous_close: get_f64("previousClose"),
1471 volume: get_i64("volume"),
1472
1473 all_time_high: None,
1475 all_time_low: None,
1476
1477 pre_market_price: get_f64("preMarketPrice"),
1479 pre_market_change: get_f64("preMarketChange"),
1480 pre_market_change_percent: get_f64("preMarketChangePercent"),
1481 pre_market_time: json.get("preMarketTime").and_then(|v| v.as_i64()),
1482 post_market_price: get_f64("postMarketPrice"),
1483 post_market_change: get_f64("postMarketChange"),
1484 post_market_change_percent: get_f64("postMarketChangePercent"),
1485 post_market_time: json.get("postMarketTime").and_then(|v| v.as_i64()),
1486
1487 average_daily_volume10_day: get_i64("averageDailyVolume10Day"),
1489 average_daily_volume3_month: get_i64("averageDailyVolume3Month"),
1490 average_volume: get_i64("averageVolume"),
1491 average_volume10days: get_i64("averageVolume10days"),
1492
1493 market_cap: get_i64("marketCap"),
1495 enterprise_value: None,
1496 enterprise_to_revenue: None,
1497 enterprise_to_ebitda: None,
1498 price_to_book: get_f64("priceToBook"),
1499 price_to_sales_trailing12_months: None,
1500
1501 forward_pe: get_f64("forwardPE"),
1503 trailing_pe: get_f64("trailingPE"),
1504
1505 beta: None,
1507
1508 fifty_two_week_high: get_f64("fiftyTwoWeekHigh"),
1510 fifty_two_week_low: get_f64("fiftyTwoWeekLow"),
1511 fifty_day_average: get_f64("fiftyDayAverage"),
1512 two_hundred_day_average: get_f64("twoHundredDayAverage"),
1513 week_52_change: get_f64("52WeekChange"),
1514 sand_p_52_week_change: None,
1515
1516 dividend_rate: get_f64("dividendRate"),
1518 dividend_yield: get_f64("dividendYield"),
1519 trailing_annual_dividend_rate: get_f64("trailingAnnualDividendRate"),
1520 trailing_annual_dividend_yield: get_f64("trailingAnnualDividendYield"),
1521 five_year_avg_dividend_yield: None,
1522 ex_dividend_date: None,
1523 payout_ratio: None,
1524 last_dividend_value: None,
1525 last_dividend_date: None,
1526
1527 bid: get_f64("bid"),
1529 bid_size: get_i64("bidSize"),
1530 ask: get_f64("ask"),
1531 ask_size: get_i64("askSize"),
1532
1533 shares_outstanding: get_i64("sharesOutstanding"),
1535 float_shares: None,
1536 implied_shares_outstanding: None,
1537 held_percent_insiders: None,
1538 held_percent_institutions: None,
1539 shares_short: None,
1540 shares_short_prior_month: None,
1541 short_ratio: None,
1542 short_percent_of_float: None,
1543 shares_percent_shares_out: None,
1544 date_short_interest: None,
1545
1546 current_price: None,
1548 target_high_price: None,
1549 target_low_price: None,
1550 target_mean_price: None,
1551 target_median_price: None,
1552 recommendation_mean: None,
1553 recommendation_key: None,
1554 number_of_analyst_opinions: None,
1555 total_cash: None,
1556 total_cash_per_share: None,
1557 ebitda: None,
1558 total_debt: None,
1559 total_revenue: None,
1560 net_income_to_common: None,
1561 debt_to_equity: None,
1562 revenue_per_share: None,
1563 return_on_assets: None,
1564 return_on_equity: None,
1565 free_cashflow: None,
1566 operating_cashflow: None,
1567
1568 profit_margins: None,
1570 gross_margins: None,
1571 ebitda_margins: None,
1572 operating_margins: None,
1573 gross_profits: None,
1574
1575 earnings_growth: None,
1577 revenue_growth: None,
1578 earnings_quarterly_growth: None,
1579
1580 current_ratio: None,
1582 quick_ratio: None,
1583
1584 trailing_eps: get_f64("trailingEps"),
1586 forward_eps: get_f64("forwardEps"),
1587 book_value: get_f64("bookValue"),
1588
1589 sector: get_str("sector"),
1591 sector_key: get_str("sectorKey"),
1592 sector_disp: get_str("sectorDisp"),
1593 industry: get_str("industry"),
1594 industry_key: get_str("industryKey"),
1595 industry_disp: get_str("industryDisp"),
1596 long_business_summary: None,
1597 website: None,
1598 ir_website: None,
1599 address1: None,
1600 city: None,
1601 state: None,
1602 zip: None,
1603 country: None,
1604 phone: None,
1605 full_time_employees: None,
1606 category: None,
1607 fund_family: None,
1608
1609 audit_risk: None,
1611 board_risk: None,
1612 compensation_risk: None,
1613 shareholder_rights_risk: None,
1614 overall_risk: None,
1615
1616 time_zone_full_name: get_str("exchangeTimezoneName"),
1618 time_zone_short_name: get_str("exchangeTimezoneShortName"),
1619 gmt_off_set_milliseconds: json.get("gmtOffSetMilliseconds").and_then(|v| v.as_i64()),
1620 first_trade_date_epoch_utc: json
1621 .get("firstTradeDateMilliseconds")
1622 .and_then(|v| v.as_i64()),
1623 message_board_id: get_str("messageBoardId"),
1624 exchange_data_delayed_by: json
1625 .get("exchangeDataDelayedBy")
1626 .and_then(|v| v.as_i64())
1627 .map(|v| v as i32),
1628
1629 nav_price: get_f64("navPrice"),
1631 total_assets: get_i64("totalAssets"),
1632 yield_value: get_f64("yield"),
1633
1634 last_split_factor: None,
1636 last_split_date: None,
1637 last_fiscal_year_end: None,
1638 next_fiscal_year_end: None,
1639 most_recent_quarter: None,
1640
1641 price_hint: get_i64("priceHint"),
1643 tradeable: json.get("tradeable").and_then(|v| v.as_bool()),
1644 financial_currency: get_str("financialCurrency"),
1645
1646 company_officers: None,
1648 earnings: None,
1649 calendar_events: None,
1650 recommendation_trend: None,
1651 upgrade_downgrade_history: None,
1652 earnings_history: None,
1653 earnings_trend: None,
1654 insider_holders: None,
1655 insider_transactions: None,
1656 institution_ownership: None,
1657 fund_ownership: None,
1658 major_holders_breakdown: None,
1659 net_share_purchase_activity: None,
1660 sec_filings: None,
1661 balance_sheet_history: None,
1662 balance_sheet_history_quarterly: None,
1663 cashflow_statement_history: None,
1664 cashflow_statement_history_quarterly: None,
1665 income_statement_history: None,
1666 income_statement_history_quarterly: None,
1667 equity_performance: None,
1668 index_trend: None,
1669 industry_trend: None,
1670 sector_trend: None,
1671 fund_profile: None,
1672 fund_performance: None,
1673 top_holdings: None,
1674 })
1675 }
1676}