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
1204 pub(crate) fn from_batch_response(json: &serde_json::Value) -> Result<Self, String> {
1209 let symbol = json
1210 .get("symbol")
1211 .and_then(|v| v.as_str())
1212 .ok_or("Missing symbol")?
1213 .to_string();
1214
1215 let get_f64 = |key: &str| -> Option<super::FormattedValue<f64>> {
1218 json.get(key).and_then(|v| {
1219 if let Some(raw) = v.as_f64() {
1220 Some(super::FormattedValue {
1222 raw: Some(raw),
1223 fmt: None,
1224 long_fmt: None,
1225 })
1226 } else if v.is_object() {
1227 Some(super::FormattedValue {
1229 raw: v.get("raw").and_then(|r| r.as_f64()),
1230 fmt: v.get("fmt").and_then(|f| f.as_str()).map(|s| s.to_string()),
1231 long_fmt: v
1232 .get("longFmt")
1233 .and_then(|f| f.as_str())
1234 .map(|s| s.to_string()),
1235 })
1236 } else {
1237 None
1238 }
1239 })
1240 };
1241
1242 let get_i64 = |key: &str| -> Option<super::FormattedValue<i64>> {
1245 json.get(key).and_then(|v| {
1246 if let Some(raw) = v.as_i64() {
1247 Some(super::FormattedValue {
1249 raw: Some(raw),
1250 fmt: None,
1251 long_fmt: None,
1252 })
1253 } else if v.is_object() {
1254 Some(super::FormattedValue {
1256 raw: v.get("raw").and_then(|r| r.as_i64()),
1257 fmt: v.get("fmt").and_then(|f| f.as_str()).map(|s| s.to_string()),
1258 long_fmt: v
1259 .get("longFmt")
1260 .and_then(|f| f.as_str())
1261 .map(|s| s.to_string()),
1262 })
1263 } else {
1264 None
1265 }
1266 })
1267 };
1268
1269 let get_str = |key: &str| -> Option<String> {
1271 json.get(key)
1272 .and_then(|v| v.as_str())
1273 .map(|s| s.to_string())
1274 };
1275
1276 Ok(Self {
1277 symbol,
1278 logo_url: get_str("logoUrl"),
1279 company_logo_url: get_str("companyLogoUrl"),
1280
1281 short_name: get_str("shortName"),
1283 long_name: get_str("longName"),
1284 exchange: get_str("exchange"),
1285 exchange_name: get_str("fullExchangeName"),
1286 quote_type: get_str("quoteType"),
1287 currency: get_str("currency"),
1288 currency_symbol: get_str("currencySymbol"),
1289 underlying_symbol: get_str("underlyingSymbol"),
1290 from_currency: get_str("fromCurrency"),
1291 to_currency: get_str("toCurrency"),
1292
1293 regular_market_price: get_f64("regularMarketPrice"),
1295 regular_market_change: get_f64("regularMarketChange"),
1296 regular_market_change_percent: get_f64("regularMarketChangePercent"),
1297 regular_market_time: json.get("regularMarketTime").and_then(|v| v.as_i64()),
1298 regular_market_day_high: get_f64("regularMarketDayHigh"),
1299 regular_market_day_low: get_f64("regularMarketDayLow"),
1300 regular_market_open: get_f64("regularMarketOpen"),
1301 regular_market_previous_close: get_f64("regularMarketPreviousClose"),
1302 regular_market_volume: get_i64("regularMarketVolume"),
1303 market_state: get_str("marketState"),
1304
1305 day_high: get_f64("dayHigh"),
1307 day_low: get_f64("dayLow"),
1308 open: get_f64("open"),
1309 previous_close: get_f64("previousClose"),
1310 volume: get_i64("volume"),
1311
1312 all_time_high: None,
1314 all_time_low: None,
1315
1316 pre_market_price: get_f64("preMarketPrice"),
1318 pre_market_change: get_f64("preMarketChange"),
1319 pre_market_change_percent: get_f64("preMarketChangePercent"),
1320 pre_market_time: json.get("preMarketTime").and_then(|v| v.as_i64()),
1321 post_market_price: get_f64("postMarketPrice"),
1322 post_market_change: get_f64("postMarketChange"),
1323 post_market_change_percent: get_f64("postMarketChangePercent"),
1324 post_market_time: json.get("postMarketTime").and_then(|v| v.as_i64()),
1325
1326 average_daily_volume10_day: get_i64("averageDailyVolume10Day"),
1328 average_daily_volume3_month: get_i64("averageDailyVolume3Month"),
1329 average_volume: get_i64("averageVolume"),
1330 average_volume10days: get_i64("averageVolume10days"),
1331
1332 market_cap: get_i64("marketCap"),
1334 enterprise_value: None,
1335 enterprise_to_revenue: None,
1336 enterprise_to_ebitda: None,
1337 price_to_book: get_f64("priceToBook"),
1338 price_to_sales_trailing12_months: None,
1339
1340 forward_pe: get_f64("forwardPE"),
1342 trailing_pe: get_f64("trailingPE"),
1343
1344 beta: None,
1346
1347 fifty_two_week_high: get_f64("fiftyTwoWeekHigh"),
1349 fifty_two_week_low: get_f64("fiftyTwoWeekLow"),
1350 fifty_day_average: get_f64("fiftyDayAverage"),
1351 two_hundred_day_average: get_f64("twoHundredDayAverage"),
1352 week_52_change: get_f64("52WeekChange"),
1353 sand_p_52_week_change: None,
1354
1355 dividend_rate: get_f64("dividendRate"),
1357 dividend_yield: get_f64("dividendYield"),
1358 trailing_annual_dividend_rate: get_f64("trailingAnnualDividendRate"),
1359 trailing_annual_dividend_yield: get_f64("trailingAnnualDividendYield"),
1360 five_year_avg_dividend_yield: None,
1361 ex_dividend_date: None,
1362 payout_ratio: None,
1363 last_dividend_value: None,
1364 last_dividend_date: None,
1365
1366 bid: get_f64("bid"),
1368 bid_size: get_i64("bidSize"),
1369 ask: get_f64("ask"),
1370 ask_size: get_i64("askSize"),
1371
1372 shares_outstanding: get_i64("sharesOutstanding"),
1374 float_shares: None,
1375 implied_shares_outstanding: None,
1376 held_percent_insiders: None,
1377 held_percent_institutions: None,
1378 shares_short: None,
1379 shares_short_prior_month: None,
1380 short_ratio: None,
1381 short_percent_of_float: None,
1382 shares_percent_shares_out: None,
1383 date_short_interest: None,
1384
1385 current_price: None,
1387 target_high_price: None,
1388 target_low_price: None,
1389 target_mean_price: None,
1390 target_median_price: None,
1391 recommendation_mean: None,
1392 recommendation_key: None,
1393 number_of_analyst_opinions: None,
1394 total_cash: None,
1395 total_cash_per_share: None,
1396 ebitda: None,
1397 total_debt: None,
1398 total_revenue: None,
1399 net_income_to_common: None,
1400 debt_to_equity: None,
1401 revenue_per_share: None,
1402 return_on_assets: None,
1403 return_on_equity: None,
1404 free_cashflow: None,
1405 operating_cashflow: None,
1406
1407 profit_margins: None,
1409 gross_margins: None,
1410 ebitda_margins: None,
1411 operating_margins: None,
1412 gross_profits: None,
1413
1414 earnings_growth: None,
1416 revenue_growth: None,
1417 earnings_quarterly_growth: None,
1418
1419 current_ratio: None,
1421 quick_ratio: None,
1422
1423 trailing_eps: get_f64("trailingEps"),
1425 forward_eps: get_f64("forwardEps"),
1426 book_value: get_f64("bookValue"),
1427
1428 sector: get_str("sector"),
1430 sector_key: get_str("sectorKey"),
1431 sector_disp: get_str("sectorDisp"),
1432 industry: get_str("industry"),
1433 industry_key: get_str("industryKey"),
1434 industry_disp: get_str("industryDisp"),
1435 long_business_summary: None,
1436 website: None,
1437 ir_website: None,
1438 address1: None,
1439 city: None,
1440 state: None,
1441 zip: None,
1442 country: None,
1443 phone: None,
1444 full_time_employees: None,
1445 category: None,
1446 fund_family: None,
1447
1448 audit_risk: None,
1450 board_risk: None,
1451 compensation_risk: None,
1452 shareholder_rights_risk: None,
1453 overall_risk: None,
1454
1455 time_zone_full_name: get_str("exchangeTimezoneName"),
1457 time_zone_short_name: get_str("exchangeTimezoneShortName"),
1458 gmt_off_set_milliseconds: json.get("gmtOffSetMilliseconds").and_then(|v| v.as_i64()),
1459 first_trade_date_epoch_utc: json
1460 .get("firstTradeDateMilliseconds")
1461 .and_then(|v| v.as_i64()),
1462 message_board_id: get_str("messageBoardId"),
1463 exchange_data_delayed_by: json
1464 .get("exchangeDataDelayedBy")
1465 .and_then(|v| v.as_i64())
1466 .map(|v| v as i32),
1467
1468 nav_price: get_f64("navPrice"),
1470 total_assets: get_i64("totalAssets"),
1471 yield_value: get_f64("yield"),
1472
1473 last_split_factor: None,
1475 last_split_date: None,
1476 last_fiscal_year_end: None,
1477 next_fiscal_year_end: None,
1478 most_recent_quarter: None,
1479
1480 price_hint: get_i64("priceHint"),
1482 tradeable: json.get("tradeable").and_then(|v| v.as_bool()),
1483 financial_currency: get_str("financialCurrency"),
1484
1485 company_officers: None,
1487 earnings: None,
1488 calendar_events: None,
1489 recommendation_trend: None,
1490 upgrade_downgrade_history: None,
1491 earnings_history: None,
1492 earnings_trend: None,
1493 insider_holders: None,
1494 insider_transactions: None,
1495 institution_ownership: None,
1496 fund_ownership: None,
1497 major_holders_breakdown: None,
1498 net_share_purchase_activity: None,
1499 sec_filings: None,
1500 balance_sheet_history: None,
1501 balance_sheet_history_quarterly: None,
1502 cashflow_statement_history: None,
1503 cashflow_statement_history_quarterly: None,
1504 income_statement_history: None,
1505 income_statement_history_quarterly: None,
1506 equity_performance: None,
1507 index_trend: None,
1508 industry_trend: None,
1509 sector_trend: None,
1510 fund_profile: None,
1511 fund_performance: None,
1512 top_holdings: None,
1513 })
1514 }
1515}