1use std::collections::HashMap;
2
3use num_enum::{FromPrimitive, IntoPrimitive};
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6use strum_macros::{Display, EnumString};
7use time::OffsetDateTime;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct FinancialReports {
18 pub list: serde_json::Value,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct DividendList {
29 pub list: Vec<DividendItem>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct DividendItem {
36 pub symbol: String,
38 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
40 pub id: String,
41 pub desc: String,
43 pub record_date: String,
45 pub ex_date: String,
47 pub payment_date: String,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct InstitutionRating {
57 pub latest: InstitutionRatingLatest,
59 pub summary: InstitutionRatingSummary,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct InstitutionRatingLatest {
66 pub evaluate: RatingEvaluate,
68 pub target: RatingTarget,
70 pub industry_id: i64,
72 pub industry_name: String,
74 pub industry_rank: i32,
76 pub industry_total: i32,
78 pub industry_mean: i32,
80 pub industry_median: i32,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct RatingEvaluate {
87 pub buy: i32,
89 pub over: i32,
91 pub hold: i32,
93 pub under: i32,
95 pub sell: i32,
97 pub no_opinion: i32,
99 pub total: i32,
101 pub start_date: String,
103 pub end_date: String,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct RatingTarget {
110 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
112 pub highest_price: Option<Decimal>,
113 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
115 pub lowest_price: Option<Decimal>,
116 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
118 pub prev_close: Option<Decimal>,
119 pub start_date: String,
121 pub end_date: String,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize)]
127pub struct InstitutionRatingSummary {
128 pub ccy_symbol: String,
130 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
132 pub change: Option<Decimal>,
133 pub evaluate: RatingSummaryEvaluate,
135 pub recommend: InstitutionRecommend,
137 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
139 pub target: Option<Decimal>,
140 pub updated_at: String,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct RatingSummaryEvaluate {
147 pub buy: i32,
149 pub date: String,
151 pub hold: i32,
153 pub sell: i32,
155 pub strong_buy: i32,
157 pub under: i32,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct InstitutionRatingDetail {
166 pub ccy_symbol: String,
168 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
170 pub evaluate: InstitutionRatingDetailEvaluate,
171 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
173 pub target: InstitutionRatingDetailTarget,
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize, Default)]
178pub struct InstitutionRatingDetailEvaluate {
179 pub list: Vec<InstitutionRatingDetailEvaluateItem>,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize)]
185pub struct InstitutionRatingDetailEvaluateItem {
186 pub buy: i32,
188 pub date: String,
190 pub hold: i32,
192 pub sell: i32,
194 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
196 pub strong_buy: i32,
197 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
199 pub no_opinion: i32,
200 pub under: i32,
202}
203
204#[derive(Debug, Clone, Serialize, Deserialize, Default)]
206pub struct InstitutionRatingDetailTarget {
207 pub data_percent: Option<Decimal>,
209 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
211 pub prediction_accuracy: Option<Decimal>,
212 pub updated_at: String,
214 pub list: Vec<InstitutionRatingDetailTargetItem>,
216}
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct InstitutionRatingDetailTargetItem {
221 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
223 pub avg_target: Option<Decimal>,
224 pub date: String,
226 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
228 pub max_target: Option<Decimal>,
229 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
231 pub min_target: Option<Decimal>,
232 pub meet: bool,
234 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
236 pub price: Option<Decimal>,
237 pub timestamp: String,
239}
240
241#[derive(Debug, Clone, Serialize, Deserialize)]
245pub struct ForecastEps {
246 pub items: Vec<ForecastEpsItem>,
248}
249
250#[derive(Debug, Clone, Serialize, Deserialize)]
252pub struct ForecastEpsItem {
253 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
255 pub forecast_eps_median: Option<Decimal>,
256 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
258 pub forecast_eps_mean: Option<Decimal>,
259 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
261 pub forecast_eps_lowest: Option<Decimal>,
262 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
264 pub forecast_eps_highest: Option<Decimal>,
265 pub institution_total: i32,
267 pub institution_up: i32,
269 pub institution_down: i32,
271 #[serde(deserialize_with = "crate::serde_utils::deserialize_timestamp")]
273 pub forecast_start_date: OffsetDateTime,
274 #[serde(deserialize_with = "crate::serde_utils::deserialize_timestamp")]
276 pub forecast_end_date: OffsetDateTime,
277}
278
279#[derive(Debug, Clone, Serialize, Deserialize)]
283pub struct FinancialConsensus {
284 pub list: Vec<ConsensusReport>,
286 pub current_index: i32,
288 pub currency: String,
290 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
292 pub opt_periods: Vec<String>,
293 pub current_period: String,
295}
296
297#[derive(Debug, Clone, Serialize, Deserialize)]
299pub struct ConsensusReport {
300 pub fiscal_year: i32,
302 pub fiscal_period: String,
304 pub period_text: String,
306 pub details: Vec<ConsensusDetail>,
308}
309
310#[derive(Debug, Clone, Serialize, Deserialize)]
312pub struct ConsensusDetail {
313 pub key: String,
315 pub name: String,
317 pub description: String,
319 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
321 pub actual: Option<Decimal>,
322 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
324 pub estimate: Option<Decimal>,
325 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
327 pub comp_value: Option<Decimal>,
328 pub comp_desc: String,
330 pub comp: String,
332 pub is_released: bool,
334}
335
336#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct ValuationData {
341 pub metrics: ValuationMetricsData,
343}
344
345#[derive(Debug, Clone, Serialize, Deserialize)]
347pub struct ValuationMetricsData {
348 pub pe: Option<ValuationMetricData>,
350 pub pb: Option<ValuationMetricData>,
352 pub ps: Option<ValuationMetricData>,
354 pub dvd_yld: Option<ValuationMetricData>,
356}
357
358#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct ValuationMetricData {
361 pub desc: String,
363 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
365 pub high: Option<Decimal>,
366 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
368 pub low: Option<Decimal>,
369 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
371 pub median: Option<Decimal>,
372 pub list: Vec<ValuationPoint>,
374}
375
376#[derive(Debug, Clone, Serialize, Deserialize)]
378pub struct ValuationPoint {
379 #[serde(deserialize_with = "crate::serde_utils::deserialize_timestamp")]
381 pub timestamp: OffsetDateTime,
382 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
384 pub value: Option<Decimal>,
385}
386
387#[derive(Debug, Clone, Serialize, Deserialize)]
391pub struct ValuationHistoryResponse {
392 pub history: ValuationHistoryData,
394}
395
396#[derive(Debug, Clone, Serialize, Deserialize)]
398pub struct ValuationHistoryData {
399 pub metrics: ValuationHistoryMetrics,
401}
402
403#[derive(Debug, Clone, Serialize, Deserialize)]
405pub struct ValuationHistoryMetrics {
406 pub pe: Option<ValuationHistoryMetric>,
408 pub pb: Option<ValuationHistoryMetric>,
410 pub ps: Option<ValuationHistoryMetric>,
412}
413
414#[derive(Debug, Clone, Serialize, Deserialize)]
416pub struct ValuationHistoryMetric {
417 pub desc: String,
419 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
421 pub high: Option<Decimal>,
422 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
424 pub low: Option<Decimal>,
425 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
427 pub median: Option<Decimal>,
428 pub list: Vec<ValuationPoint>,
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
436pub struct IndustryValuationList {
437 pub list: Vec<IndustryValuationItem>,
439}
440
441#[derive(Debug, Clone, Serialize, Deserialize)]
443pub struct IndustryValuationItem {
444 pub symbol: String,
446 pub name: String,
448 pub currency: String,
450 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
452 pub assets: Option<Decimal>,
453 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
455 pub bps: Option<Decimal>,
456 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
458 pub eps: Option<Decimal>,
459 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
461 pub dps: Option<Decimal>,
462 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
464 pub div_yld: Option<Decimal>,
465 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
467 pub div_payout_ratio: Option<Decimal>,
468 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
470 pub five_y_avg_dps: Option<Decimal>,
471 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
473 pub pe: Option<Decimal>,
474 pub history: Vec<IndustryValuationHistory>,
476}
477
478#[derive(Debug, Clone, Serialize, Deserialize)]
480pub struct IndustryValuationHistory {
481 pub date: String,
483 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
485 pub pe: Option<Decimal>,
486 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
488 pub pb: Option<Decimal>,
489 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
491 pub ps: Option<Decimal>,
492}
493
494#[derive(Debug, Clone, Serialize, Deserialize)]
498pub struct IndustryValuationDist {
499 pub pe: Option<ValuationDist>,
501 pub pb: Option<ValuationDist>,
503 pub ps: Option<ValuationDist>,
505}
506
507#[derive(Debug, Clone, Serialize, Deserialize)]
509pub struct ValuationDist {
510 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
512 pub low: Option<Decimal>,
513 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
515 pub high: Option<Decimal>,
516 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
518 pub median: Option<Decimal>,
519 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
521 pub value: Option<Decimal>,
522 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
524 pub ranking: Option<Decimal>,
525 pub rank_index: String,
527 pub rank_total: String,
529}
530
531#[derive(Debug, Clone, Serialize, Deserialize)]
535pub struct CompanyOverview {
536 pub name: String,
538 pub company_name: String,
540 pub founded: String,
542 pub listing_date: String,
544 pub market: String,
546 pub region: String,
548 pub address: String,
550 pub office_address: String,
552 pub website: String,
554 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
556 pub issue_price: Option<Decimal>,
557 pub shares_offered: String,
559 pub chairman: String,
561 pub secretary: String,
563 pub audit_inst: String,
565 pub category: String,
567 pub year_end: String,
569 pub employees: String,
571 #[serde(rename = "Phone")]
573 pub phone: String,
574 pub fax: String,
576 pub email: String,
578 pub legal_repr: String,
580 pub manager: String,
582 pub bus_license: String,
584 pub accounting_firm: String,
586 pub securities_rep: String,
588 pub legal_counsel: String,
590 pub zip_code: String,
592 pub ticker: String,
594 pub icon: String,
596 pub profile: String,
598 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
600 pub ads_ratio: String,
601 pub sector: i32,
603}
604
605#[derive(Debug, Clone, Serialize, Deserialize)]
609pub struct ExecutiveList {
610 pub professional_list: Vec<ExecutiveGroup>,
612}
613
614#[derive(Debug, Clone, Serialize, Deserialize)]
616pub struct ExecutiveGroup {
617 #[serde(default, with = "crate::serde_utils::symbol_opt")]
619 pub symbol: Option<String>,
620 pub forward_url: String,
622 pub total: i32,
624 pub professionals: Vec<Professional>,
626}
627
628#[derive(Debug, Clone, Serialize, Deserialize)]
630pub struct Professional {
631 pub id: String,
633 pub name: String,
635 pub name_zhcn: String,
637 pub name_en: String,
639 pub title: String,
641 pub biography: String,
643 pub photo: String,
645 pub wiki_url: String,
647}
648
649#[derive(Debug, Clone, Serialize, Deserialize)]
653pub struct ShareholderList {
654 pub shareholder_list: Vec<Shareholder>,
656 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
658 pub forward_url: String,
659 pub total: i32,
661}
662
663#[derive(Debug, Clone, Serialize, Deserialize)]
665pub struct Shareholder {
666 pub shareholder_id: String,
668 pub shareholder_name: String,
670 pub institution_type: String,
672 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
674 pub percent_of_shares: Option<Decimal>,
675 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
677 pub shares_changed: Option<Decimal>,
678 pub report_date: String,
680 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
682 pub stocks: Vec<ShareholderStock>,
683}
684
685#[derive(Debug, Clone, Serialize, Deserialize)]
687pub struct ShareholderStock {
688 pub symbol: String,
690 pub code: String,
692 pub market: String,
694 pub chg: String,
696}
697
698#[derive(Debug, Clone, Serialize, Deserialize)]
702pub struct FundHolders {
703 pub lists: Vec<FundHolder>,
705}
706
707#[derive(Debug, Clone, Serialize, Deserialize)]
709pub struct FundHolder {
710 pub code: String,
712 pub symbol: String,
714 pub currency: String,
716 pub name: String,
718 #[serde(with = "crate::serde_utils::decimal_empty_is_0")]
720 pub position_ratio: Decimal,
721 pub report_date: String,
723}
724
725#[derive(Debug, Clone, Serialize, Deserialize)]
729pub struct CorpActions {
730 pub items: Vec<CorpActionItem>,
732}
733
734#[derive(Debug, Clone, Serialize, Deserialize)]
736pub struct CorpActionItem {
737 pub id: String,
739 pub date: String,
741 pub date_str: String,
743 pub date_type: String,
745 pub date_zone: String,
747 pub act_type: String,
749 pub act_desc: String,
751 pub action: String,
753 pub recent: bool,
755 pub is_delay: bool,
757 pub delay_content: String,
759 pub live: Option<CorpActionLive>,
761 pub security: Option<serde_json::Value>,
763}
764
765#[derive(Debug, Clone, Serialize, Deserialize)]
767pub struct CorpActionLive {
768 pub id: String,
770 #[serde(deserialize_with = "crate::serde_utils::deserialize_string_or_int_as_string")]
775 pub status: String,
776 pub started_at: String,
778 pub name: String,
780 pub icon: String,
782}
783
784#[derive(Debug, Clone, Serialize, Deserialize)]
788pub struct InvestRelations {
789 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
791 pub forward_url: String,
792 pub invest_securities: Vec<InvestSecurity>,
794}
795
796#[derive(Debug, Clone, Serialize, Deserialize)]
798pub struct InvestSecurity {
799 pub company_id: String,
801 pub company_name: String,
803 pub company_name_en: String,
805 pub company_name_zhcn: String,
807 pub symbol: String,
809 pub currency: String,
811 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
813 pub percent_of_shares: Option<Decimal>,
814 pub shares_rank: String,
816 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
818 pub shares_value: Option<Decimal>,
819}
820
821#[derive(Debug, Clone, Serialize, Deserialize)]
825pub struct OperatingList {
826 pub list: Vec<OperatingItem>,
828}
829
830#[derive(Debug, Clone, Serialize, Deserialize)]
832pub struct OperatingItem {
833 pub id: String,
835 pub report: String,
837 pub title: String,
839 pub txt: String,
841 pub latest: bool,
843 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
845 pub keywords: Vec<serde_json::Value>,
846 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
848 pub web_url: String,
849 pub financial: OperatingFinancial,
851}
852
853#[derive(Debug, Clone, Serialize, Deserialize)]
855pub struct OperatingFinancial {
856 pub code: String,
858 pub symbol: String,
860 pub currency: String,
862 pub name: String,
864 pub region: String,
866 pub report: String,
868 pub report_txt: String,
870 pub indicators: Vec<OperatingIndicator>,
872}
873
874#[derive(Debug, Clone, Serialize, Deserialize)]
876pub struct OperatingIndicator {
877 pub field_name: String,
879 pub indicator_name: String,
881 pub indicator_value: String,
883 #[serde(default, with = "crate::serde_utils::decimal_opt_str_is_none")]
885 pub yoy: Option<Decimal>,
886}
887
888#[derive(Debug, Clone, Serialize, Deserialize)]
892pub struct BuybackData {
893 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
895 pub recent_buybacks: Option<RecentBuybacks>,
896 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
898 pub buyback_history: Vec<BuybackHistoryItem>,
899 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
901 pub buyback_ratios: Vec<BuybackRatios>,
902}
903
904#[derive(Debug, Clone, Serialize, Deserialize)]
906pub struct RecentBuybacks {
907 pub currency: String,
909 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
911 pub net_buyback_ttm: Option<Decimal>,
912 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
914 pub net_buyback_yield_ttm: Option<Decimal>,
915}
916
917#[derive(Debug, Clone, Serialize, Deserialize)]
919pub struct BuybackHistoryItem {
920 pub fiscal_year: String,
922 pub fiscal_year_range: String,
924 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
926 pub net_buyback: Option<Decimal>,
927 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
929 pub net_buyback_yield: Option<Decimal>,
930 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
932 pub net_buyback_growth_rate: Option<Decimal>,
933 pub currency: String,
935}
936
937#[derive(Debug, Clone, Serialize, Deserialize)]
939pub struct BuybackRatios {
940 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
942 pub net_buyback_payout_ratio: Option<Decimal>,
943 #[serde(with = "crate::serde_utils::decimal_opt_str_is_none")]
945 pub net_buyback_to_cashflow_ratio: Option<Decimal>,
946}
947
948#[derive(Debug, Clone, Serialize, Deserialize)]
952pub struct StockRatings {
953 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
955 pub style_txt_name: String,
956 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
958 pub scale_txt_name: String,
959 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
961 pub report_period_txt: String,
962 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
964 pub multi_score: Option<f64>,
965 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
967 pub multi_letter: String,
968 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
970 pub multi_score_change: i32,
971 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
973 pub industry_name: String,
974 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
976 pub industry_rank: Option<i64>,
977 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
979 pub industry_total: Option<i64>,
980 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
982 pub industry_mean_score: Option<f64>,
983 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
985 pub industry_median_score: Option<f64>,
986 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
988 pub ratings: Vec<RatingCategory>,
989}
990
991#[derive(Debug, Clone, Serialize, Deserialize)]
993pub struct RatingCategory {
994 #[serde(rename = "type")]
996 pub kind: i32,
997 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
999 pub sub_indicators: Vec<RatingSubIndicatorGroup>,
1000}
1001
1002#[derive(Debug, Clone, Serialize, Deserialize)]
1004pub struct RatingSubIndicatorGroup {
1005 pub indicator: RatingIndicator,
1007 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1009 pub sub_indicators: Vec<RatingLeafIndicator>,
1010}
1011
1012#[derive(Debug, Clone, Serialize, Deserialize)]
1014pub struct RatingIndicator {
1015 pub name: String,
1017 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1019 pub score: Option<f64>,
1020 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1022 pub letter: String,
1023}
1024
1025#[derive(Debug, Clone, Serialize, Deserialize)]
1027pub struct RatingLeafIndicator {
1028 pub name: String,
1030 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1032 pub value: String,
1033 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1035 pub value_type: String,
1036 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1038 pub score: Option<f64>,
1039 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1041 pub letter: String,
1042}
1043
1044#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, EnumString, Display)]
1048pub enum InstitutionRecommend {
1049 Unknown,
1051 #[strum(serialize = "strong_buy")]
1053 StrongBuy,
1054 #[strum(serialize = "buy")]
1056 Buy,
1057 #[strum(serialize = "hold")]
1059 Hold,
1060 #[strum(serialize = "sell")]
1062 Sell,
1063 #[strum(serialize = "strong_sell")]
1065 StrongSell,
1066 #[strum(serialize = "underperform")]
1068 Underperform,
1069 #[strum(serialize = "no_opinion")]
1071 NoOpinion,
1072}
1073
1074impl_default_for_enum_string!(InstitutionRecommend);
1075impl_serde_for_enum_string!(InstitutionRecommend);
1076
1077#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
1079pub enum FinancialReportKind {
1080 #[serde(rename = "IS")]
1082 IncomeStatement,
1083 #[serde(rename = "BS")]
1085 BalanceSheet,
1086 #[serde(rename = "CF")]
1088 CashFlow,
1089 #[default]
1091 #[serde(rename = "ALL")]
1092 All,
1093}
1094
1095#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
1103pub enum FinancialStatementKind {
1104 #[serde(rename = "IS")]
1106 IncomeStatement,
1107 #[serde(rename = "BS")]
1109 BalanceSheet,
1110 #[serde(rename = "CF")]
1112 CashFlow,
1113}
1114
1115impl FinancialStatementKind {
1116 #[inline]
1118 pub fn as_str(&self) -> &'static str {
1119 match self {
1120 FinancialStatementKind::IncomeStatement => "IS",
1121 FinancialStatementKind::BalanceSheet => "BS",
1122 FinancialStatementKind::CashFlow => "CF",
1123 }
1124 }
1125}
1126
1127#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
1129pub enum IndustryRankIndicator {
1130 #[serde(rename = "leading-gainer")]
1132 LeadingGainer,
1133 #[serde(rename = "today-trend")]
1135 TodayTrend,
1136 #[serde(rename = "popularity")]
1138 Popularity,
1139 #[serde(rename = "market-cap")]
1141 MarketCap,
1142 #[serde(rename = "revenue")]
1144 Revenue,
1145 #[serde(rename = "revenue-growth")]
1147 RevenueGrowth,
1148 #[serde(rename = "net-profit")]
1150 NetProfit,
1151 #[serde(rename = "net-profit-growth")]
1153 NetProfitGrowth,
1154}
1155
1156impl IndustryRankIndicator {
1157 #[inline]
1159 pub fn as_str(&self) -> &'static str {
1160 match self {
1161 IndustryRankIndicator::LeadingGainer => "leading-gainer",
1162 IndustryRankIndicator::TodayTrend => "today-trend",
1163 IndustryRankIndicator::Popularity => "popularity",
1164 IndustryRankIndicator::MarketCap => "market-cap",
1165 IndustryRankIndicator::Revenue => "revenue",
1166 IndustryRankIndicator::RevenueGrowth => "revenue-growth",
1167 IndustryRankIndicator::NetProfit => "net-profit",
1168 IndustryRankIndicator::NetProfitGrowth => "net-profit-growth",
1169 }
1170 }
1171}
1172
1173#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
1175pub enum IndustryRankSortType {
1176 #[serde(rename = "single")]
1178 Single,
1179 #[serde(rename = "multi")]
1181 Multi,
1182}
1183
1184impl IndustryRankSortType {
1185 #[inline]
1187 pub fn as_str(&self) -> &'static str {
1188 match self {
1189 IndustryRankSortType::Single => "single",
1190 IndustryRankSortType::Multi => "multi",
1191 }
1192 }
1193}
1194
1195#[derive(Debug, Clone, Serialize, Deserialize)]
1199pub struct BusinessSegments {
1200 pub date: String,
1202 pub total: String,
1204 pub currency: String,
1206 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1208 pub business: Vec<BusinessSegmentItem>,
1209}
1210
1211#[derive(Debug, Clone, Serialize, Deserialize)]
1213pub struct BusinessSegmentItem {
1214 pub name: String,
1216 pub percent: String,
1218}
1219
1220#[derive(Debug, Clone, Serialize, Deserialize)]
1222pub struct BusinessSegmentsHistory {
1223 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1225 pub historical: Vec<BusinessSegmentsHistoricalItem>,
1226}
1227
1228#[derive(Debug, Clone, Serialize, Deserialize)]
1230pub struct BusinessSegmentsHistoricalItem {
1231 pub date: String,
1233 pub total: String,
1235 pub currency: String,
1237 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1239 pub business: Vec<BusinessSegmentHistoryItem>,
1240 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1242 pub regionals: Vec<BusinessSegmentHistoryItem>,
1243}
1244
1245#[derive(Debug, Clone, Serialize, Deserialize)]
1247pub struct BusinessSegmentHistoryItem {
1248 pub name: String,
1250 pub percent: String,
1252 pub value: String,
1254}
1255
1256#[derive(Debug, Clone, Serialize, Deserialize)]
1260pub struct InstitutionRatingViews {
1261 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1263 pub elist: Vec<InstitutionRatingViewItem>,
1264}
1265
1266#[derive(Debug, Clone, Serialize, Deserialize)]
1268pub struct InstitutionRatingViewItem {
1269 pub date: String,
1271 pub buy: String,
1273 pub over: String,
1275 pub hold: String,
1277 pub under: String,
1279 pub sell: String,
1281 pub total: String,
1283}
1284
1285#[derive(Debug, Clone, Serialize, Deserialize)]
1289pub struct IndustryRankResponse {
1290 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1292 pub items: Vec<IndustryRankGroup>,
1293}
1294
1295#[derive(Debug, Clone, Serialize, Deserialize)]
1297pub struct IndustryRankGroup {
1298 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1300 pub lists: Vec<IndustryRankItem>,
1301}
1302
1303#[derive(Debug, Clone, Serialize, Deserialize)]
1305pub struct IndustryRankItem {
1306 pub name: String,
1308 pub symbol: String,
1310 pub chg: String,
1312 pub leading_name: String,
1314 pub leading_ticker: String,
1316 pub leading_chg: String,
1318 pub value_name: String,
1320 pub value_data: String,
1322}
1323
1324#[derive(Debug, Clone, Serialize, Deserialize)]
1328pub struct IndustryPeersResponse {
1329 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1331 pub top: Option<IndustryPeersTop>,
1332 pub chain: Option<IndustryPeerNode>,
1334}
1335
1336#[derive(Debug, Clone, Serialize, Deserialize)]
1338pub struct IndustryPeersTop {
1339 pub name: String,
1341 pub market: String,
1343}
1344
1345#[derive(Debug, Clone, Serialize, Deserialize)]
1347pub struct IndustryPeerNode {
1348 pub name: String,
1350 pub symbol: String,
1352 pub stock_num: i32,
1354 pub chg: String,
1356 pub ytd_chg: String,
1358 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1360 pub next: Vec<IndustryPeerNode>,
1361}
1362
1363#[derive(Debug, Clone, Serialize, Deserialize)]
1367pub struct FinancialReportSnapshot {
1368 pub name: String,
1370 pub ticker: String,
1372 pub fp_start: String,
1374 pub fp_end: String,
1376 pub currency: String,
1378 pub report_desc: String,
1380 pub fo_revenue: Option<SnapshotForecastMetric>,
1382 pub fo_ebit: Option<SnapshotForecastMetric>,
1384 pub fo_eps: Option<SnapshotForecastMetric>,
1386 pub fr_revenue: Option<SnapshotReportedMetric>,
1388 pub fr_profit: Option<SnapshotReportedMetric>,
1390 pub fr_operate_cash: Option<SnapshotReportedMetric>,
1392 pub fr_invest_cash: Option<SnapshotReportedMetric>,
1394 pub fr_finance_cash: Option<SnapshotReportedMetric>,
1396 pub fr_total_assets: Option<SnapshotReportedMetric>,
1398 pub fr_total_liability: Option<SnapshotReportedMetric>,
1400 pub fr_roe_ttm: String,
1402 pub fr_profit_margin: String,
1404 pub fr_profit_margin_ttm: String,
1406 pub fr_asset_turn_ttm: String,
1408 pub fr_leverage_ttm: String,
1410 pub fr_debt_assets_ratio: String,
1412}
1413
1414#[derive(Debug, Clone, Serialize, Deserialize)]
1416pub struct SnapshotForecastMetric {
1417 pub value: String,
1419 pub yoy: String,
1421 pub cmp_desc: String,
1423 pub est_value: String,
1425}
1426
1427#[derive(Debug, Clone, Serialize, Deserialize)]
1429pub struct SnapshotReportedMetric {
1430 pub value: String,
1432 pub yoy: String,
1434}
1435
1436#[derive(Debug, Clone, Serialize, Deserialize)]
1440pub struct ShareholderTopResponse {
1441 pub data: serde_json::Value,
1443}
1444
1445#[derive(Debug, Clone, Serialize, Deserialize)]
1449pub struct ShareholderDetailResponse {
1450 pub data: serde_json::Value,
1452}
1453
1454#[derive(Debug, Clone, Serialize, Deserialize)]
1458pub struct ValuationHistoryPoint {
1459 pub date: String,
1461 pub pe: String,
1463 pub pb: String,
1465 pub ps: String,
1467}
1468
1469#[derive(Debug, Clone, Serialize, Deserialize)]
1471pub struct ValuationComparisonItem {
1472 pub symbol: String,
1474 pub name: String,
1476 pub currency: String,
1478 pub market_value: String,
1480 pub price_close: String,
1482 pub pe: String,
1484 pub pb: String,
1486 pub ps: String,
1488 pub roe: String,
1490 pub eps: String,
1492 pub bps: String,
1494 pub dps: String,
1496 pub div_yld: String,
1498 pub assets: String,
1500 pub history: Vec<ValuationHistoryPoint>,
1502}
1503
1504#[derive(Debug, Clone, Serialize, Deserialize)]
1506pub struct ValuationComparisonResponse {
1507 pub list: Vec<ValuationComparisonItem>,
1509}
1510
1511#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
1513pub enum FinancialReportPeriod {
1514 #[serde(rename = "af")]
1516 Annual,
1517 #[serde(rename = "saf")]
1519 SemiAnnual,
1520 #[serde(rename = "q1")]
1522 Q1,
1523 #[serde(rename = "q2")]
1525 Q2,
1526 #[serde(rename = "q3")]
1528 Q3,
1529 #[serde(rename = "qf")]
1531 QuarterlyFull,
1532 #[serde(rename = "3q")]
1534 ThreeQ,
1535}
1536
1537#[derive(Debug, FromPrimitive, IntoPrimitive, Copy, Clone, Hash, Eq, PartialEq)]
1541#[repr(i32)]
1542pub enum ElementType {
1543 #[num_enum(default)]
1545 Unknown = 0,
1546 Holdings = 1,
1548 Regional = 2,
1550 AssetClass = 3,
1552 Industry = 4,
1554}
1555
1556impl Serialize for ElementType {
1557 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
1558 where
1559 S: serde::Serializer,
1560 {
1561 serializer.serialize_i32((*self).into())
1562 }
1563}
1564
1565impl<'de> Deserialize<'de> for ElementType {
1566 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
1567 where
1568 D: serde::Deserializer<'de>,
1569 {
1570 Ok(ElementType::from(i32::deserialize(deserializer)?))
1571 }
1572}
1573
1574#[derive(Debug, Clone, Serialize, Deserialize)]
1576pub struct HoldingDetail {
1577 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1579 pub industry_id: String,
1580 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1582 pub industry_name: String,
1583 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1585 pub index: String,
1586 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1588 pub index_name: String,
1589 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1591 pub holding_type: String,
1592 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1594 pub holding_type_name: String,
1595}
1596
1597#[derive(Debug, Clone, Serialize, Deserialize)]
1599pub struct AssetAllocationItem {
1600 pub name: String,
1602 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1604 pub code: String,
1605 pub position_ratio: String,
1607 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1609 pub symbol: String,
1610 #[serde(rename = "name_locales_map", default)]
1612 pub name_locales: HashMap<String, String>,
1613 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1615 pub holding_detail: Option<HoldingDetail>,
1616}
1617
1618#[derive(Debug, Clone, Serialize, Deserialize)]
1620pub struct AssetAllocationGroup {
1621 pub report_date: String,
1623 pub asset_type: ElementType,
1625 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1627 pub lists: Vec<AssetAllocationItem>,
1628}
1629
1630#[derive(Debug, Clone, Serialize, Deserialize)]
1632pub struct AssetAllocationResponse {
1633 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1635 pub info: Vec<AssetAllocationGroup>,
1636}
1637
1638#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
1642pub enum MacroeconomicCountry {
1643 #[serde(rename = "Hong Kong SAR China")]
1645 HongKong,
1646 #[serde(rename = "China (Mainland)")]
1648 China,
1649 #[serde(rename = "United States")]
1651 UnitedStates,
1652 #[serde(rename = "Euro Zone")]
1654 EuroZone,
1655 #[serde(rename = "Japan")]
1657 Japan,
1658 #[serde(rename = "Singapore")]
1660 Singapore,
1661}
1662
1663#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1665pub enum MacroeconomicImportance {
1666 Low = 1,
1668 Medium = 2,
1670 High = 3,
1672}
1673
1674impl MacroeconomicImportance {
1675 pub fn from_i32(v: i32) -> Option<Self> {
1677 match v {
1678 1 => Some(Self::Low),
1679 2 => Some(Self::Medium),
1680 3 => Some(Self::High),
1681 _ => None,
1682 }
1683 }
1684}
1685
1686#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1688pub struct MultiLanguageText {
1689 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1691 pub english: String,
1692 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1694 pub simplified_chinese: String,
1695 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1697 pub traditional_chinese: String,
1698}
1699
1700#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1702pub struct MacroeconomicIndicator {
1703 pub indicator_code: String,
1705 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1707 pub source_org: String,
1708 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1710 pub country: String,
1711 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1713 pub name: String,
1714 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1716 pub adjustment_factor: String,
1717 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1719 pub periodicity: String,
1720 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1722 pub category: String,
1723 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1725 pub describe: String,
1726 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1728 pub importance: i32,
1729 #[serde(
1731 default,
1732 with = "crate::serde_utils::rfc3339_opt",
1733 rename = "start_date"
1734 )]
1735 pub start_date: Option<OffsetDateTime>,
1736}
1737
1738#[derive(Debug, Clone, Serialize, Deserialize)]
1740pub struct MacroeconomicIndicatorListResponse {
1741 #[serde(
1743 default,
1744 deserialize_with = "crate::serde_utils::null_as_default",
1745 rename = "list"
1746 )]
1747 pub data: Vec<MacroeconomicIndicator>,
1748 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1750 pub count: i32,
1751}
1752
1753#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1755pub struct Macroeconomic {
1756 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1758 pub period: String,
1759 #[serde(default, with = "crate::serde_utils::rfc3339_opt")]
1761 pub release_at: Option<OffsetDateTime>,
1762 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1764 pub actual_value: String,
1765 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1767 pub previous_value: String,
1768 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1770 pub forecast_value: String,
1771 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1773 pub revised_value: String,
1774 #[serde(default, with = "crate::serde_utils::rfc3339_opt")]
1776 pub next_release_at: Option<OffsetDateTime>,
1777 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1779 pub unit: String,
1780 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1782 pub unit_prefix: String,
1783}
1784
1785#[derive(Debug, Clone, Serialize, Deserialize)]
1787pub struct MacroeconomicResponse {
1788 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1790 pub info: MacroeconomicIndicator,
1791 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1793 pub data: Vec<Macroeconomic>,
1794 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1796 pub count: i32,
1797}
1798
1799#[derive(Debug, Clone, Serialize, Deserialize)]
1805pub struct USRankTag {
1806 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1808 pub key: String,
1809 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1811 pub location: i32,
1812 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1814 pub title: String,
1815 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1817 pub text: String,
1818 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1820 pub rank_type: i32,
1821 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1823 pub highlight_text: String,
1824}
1825
1826#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1828pub struct USSharelistItem {
1829 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1831 pub chg: String,
1832 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1834 pub id: String,
1835 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1837 pub name: String,
1838}
1839
1840#[derive(Debug, Clone, Serialize, Deserialize)]
1842pub struct USCompanyOverview {
1843 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1845 pub intro: String,
1846 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1848 pub market_cap: String,
1849 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1851 pub ccy_symbol: String,
1852 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1854 pub top_rank_tags: Vec<USRankTag>,
1855 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1857 pub detail_url: String,
1858 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1860 pub share_list: Vec<USSharelistItem>,
1861}
1862
1863#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1865pub struct USValuationMetric {
1866 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1868 pub circle: String,
1869 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1871 pub part: String,
1872 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1874 pub metric: String,
1875 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1877 pub desc: String,
1878 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1880 pub industry_median: String,
1881}
1882
1883#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1885pub struct USValuationOverview {
1886 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1888 pub metrics: std::collections::HashMap<String, USValuationMetric>,
1889 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1891 pub indicator: String,
1892 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1894 pub range: i32,
1895 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1897 pub date: String,
1898 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1900 pub ccy_symbol: String,
1901 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1903 pub aichat_data: USAIChatData,
1904 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1906 pub ai_summary: String,
1907}
1908
1909#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1911pub struct USFinancialStatementField {
1912 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1914 pub display_order: i32,
1915 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1917 pub field: String,
1918 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1920 pub id: String,
1921 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1923 pub level: i64,
1924 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1926 pub name: String,
1927 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1929 pub value: String,
1930 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1932 pub value_type: String,
1933 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1935 pub yoy: String,
1936}
1937
1938#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1940pub struct USFinancialStatementPeriod {
1941 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1943 pub ff_period: String,
1944 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1946 pub ff_year: i32,
1947 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1949 pub fields: Vec<USFinancialStatementField>,
1950 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1952 pub fp_end: String,
1953 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1955 pub report_txt: String,
1956 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1958 pub rpt_date: String,
1959}
1960
1961#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1963pub struct USFinancialStatement {
1964 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1966 pub currency: String,
1967 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1969 pub report: String,
1970 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1972 pub list: Vec<USFinancialStatementPeriod>,
1973 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1975 pub empty_fields: Vec<String>,
1976}
1977
1978#[derive(Debug, Clone, Serialize, Deserialize, Default)]
1980pub struct USFiscalYearDividend {
1981 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1983 pub dividend: String,
1984 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1986 pub dividend_yield: String,
1987 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1989 pub fiscal_year: String,
1990 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1992 pub currency: String,
1993 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
1995 pub fiscal_year_range: String,
1996}
1997
1998#[derive(Debug, Clone, Serialize, Deserialize)]
2000pub struct USETFDividendInfo {
2001 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2003 pub dividend_ttm: String,
2004 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2006 pub dividend_yield_ttm: String,
2007 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2009 pub dividend_frequency: String,
2010 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2012 pub currency: String,
2013 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2015 pub fiscal_year_info: Vec<USFiscalYearDividend>,
2016}
2017
2018#[derive(Debug, Clone, Serialize, Deserialize)]
2020pub struct USDividendItem {
2021 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2023 pub dividend: String,
2024 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2026 pub dividend_type: String,
2027 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2029 pub ex_date: String,
2030 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2032 pub payment_date: String,
2033 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2035 pub record_date: String,
2036}
2037
2038#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2040pub struct USRecentDividend {
2041 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2043 pub dividend_ttm: String,
2044 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2046 pub dividend_yield_ttm: String,
2047 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2049 pub payouts: String,
2050 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2052 pub currency: String,
2053}
2054
2055#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2057pub struct USDividendHistoryItem {
2058 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2060 pub fiscal_year: String,
2061 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2063 pub fiscal_year_range: String,
2064 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2066 pub total_shareholder_yield: String,
2067 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2069 pub dividend: String,
2070 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2072 pub dividend_yield: String,
2073 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2075 pub dividend_growth_rate: String,
2076 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2078 pub dividend_payout_ratio: String,
2079 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2081 pub dividend_to_cashflow_ratio: String,
2082 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2084 pub net_buyback: String,
2085 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2087 pub net_buyback_yield: String,
2088 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2090 pub net_buyback_growth_rate: String,
2091 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2093 pub net_buyback_payout_ratio: String,
2094 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2096 pub net_buyback_to_cashflow_ratio: String,
2097 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2099 pub currency: String,
2100}
2101
2102#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2104pub struct USDividendPayoutRecord {
2105 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2107 pub dividend: String,
2108 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2110 pub dividend_type: String,
2111 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2113 pub currency: String,
2114 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2116 pub ex_date: String,
2117 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2119 pub payment_date: String,
2120 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2122 pub record_date: String,
2123 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2125 pub title: String,
2126 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2128 pub start_time_unix: String,
2129}
2130
2131#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2133pub struct USCompanyDividends {
2134 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2136 pub recent_dividends: USRecentDividend,
2137 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2139 pub dividend_history: Vec<USDividendHistoryItem>,
2140 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2142 pub payout_ratios: Vec<USDividendHistoryItem>,
2143 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2145 pub dividend_payout_history: Vec<USDividendPayoutRecord>,
2146}
2147
2148#[derive(Debug, Clone, Serialize, Deserialize)]
2150pub struct USETFFile {
2151 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2153 pub file_name: String,
2154 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2156 pub file_path: String,
2157 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2159 pub update_date: String,
2160 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2162 pub code: String,
2163 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2165 pub format: String,
2166}
2167
2168#[derive(Debug, Clone, Serialize, Deserialize)]
2170pub struct USETFFilesResponse {
2171 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2173 pub files: Vec<USETFFile>,
2174}
2175
2176#[derive(Debug, Clone, Serialize, Deserialize)]
2180pub(crate) struct V2MacroIndicator {
2181 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2182 pub indicator_id: i32,
2183 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2184 pub indicator_name: String,
2185 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2186 pub market: String,
2187 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2188 pub importance: i32,
2189 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2190 pub description: String,
2191 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2193 pub frequence: String,
2194}
2195
2196#[derive(Debug, Clone, Serialize, Deserialize)]
2198pub(crate) struct V2MacroIndicatorListResponse {
2199 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2200 pub indicator_list: Vec<V2MacroIndicator>,
2201 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2203 pub total: i32,
2204}
2205
2206#[derive(Debug, Clone, Serialize, Deserialize)]
2208pub(crate) struct V2IndicatorDataDetail {
2209 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2210 pub actual_data: String,
2211 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2212 pub previous_data: String,
2213 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2214 pub estimated_data: String,
2215 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2216 pub published_time: String,
2217 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2218 pub observation_date: String,
2219}
2220
2221#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2223pub(crate) struct V2MacroIndicatorDetail {
2224 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2225 pub indicator_id: i32,
2226 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2227 pub indicator_name: String,
2228 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2229 pub unit: String,
2230 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2231 pub description: String,
2232 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2233 pub market: String,
2234 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2235 pub frequence: String,
2236 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2237 pub importance: i32,
2238 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2239 pub indicator_data: Vec<V2IndicatorDataDetail>,
2240}
2241
2242#[derive(Debug, Clone, Default, Serialize, Deserialize)]
2245pub(crate) struct V2MacroIndicatorDataResponse {
2246 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2248 pub indicator: V2MacroIndicatorDetail,
2249 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2251 pub total: i32,
2252}
2253
2254#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2258pub struct USReportPeriod {
2259 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2261 pub start_date: String,
2262 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2264 pub end_date: String,
2265 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2267 pub report_txt: String,
2268}
2269
2270#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2272pub struct USFinancialISItem {
2273 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2275 pub revenue: String,
2276 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2278 pub net_income: String,
2279 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2281 pub net_margin: String,
2282 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2284 pub report: USReportPeriod,
2285}
2286
2287#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2289pub struct USFinancialBSItem {
2290 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2292 pub debt_assets_ratio: String,
2293 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2295 pub total_assets: String,
2296 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2298 pub total_liabilities: String,
2299 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2301 pub report: USReportPeriod,
2302}
2303
2304#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2306pub struct USFinancialCFItem {
2307 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2309 pub operating: String,
2310 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2312 pub investing: String,
2313 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2315 pub financing: String,
2316 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2318 pub report: USReportPeriod,
2319}
2320
2321#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2323pub struct USFinancialOverview {
2324 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2326 pub ccy_symbol: String,
2327 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2329 pub report_type: String,
2330 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2332 pub is_list: Vec<USFinancialISItem>,
2333 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2335 pub bs_list: Vec<USFinancialBSItem>,
2336 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2338 pub cf_list: Vec<USFinancialCFItem>,
2339}
2340
2341#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2345pub struct USKeyMetricItem {
2346 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2348 pub ff_period: String,
2349 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2351 pub ff_year: i32,
2352 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2354 pub fp_end: String,
2355 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2357 pub report_txt: String,
2358 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2360 pub rpt_date: String,
2361 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2363 pub fields: Vec<serde_json::Value>,
2364}
2365
2366#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2368pub struct USKeyFinancialMetrics {
2369 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2371 pub currency: String,
2372 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2374 pub report: String,
2375 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2377 pub empty_fields: Vec<String>,
2378 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2380 pub list: Vec<USKeyMetricItem>,
2381}
2382
2383#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2387pub struct USAIChatData {
2388 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2390 pub agent_id: String,
2391 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2393 pub handoff_agent_id: String,
2394 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2396 pub symbol: String,
2397 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2399 pub text: String,
2400 #[serde(
2402 default,
2403 deserialize_with = "crate::serde_utils::null_as_default",
2404 rename = "type"
2405 )]
2406 pub chat_type: String,
2407 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2409 pub workflow_type: String,
2410}
2411
2412#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2414pub struct USConsensusEstimate {
2415 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2417 pub actual: String,
2418 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2420 pub estimate: String,
2421}
2422
2423#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2425pub struct USConsensusItem {
2426 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2428 pub ebit: USConsensusEstimate,
2429 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2431 pub eps: USConsensusEstimate,
2432 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2434 pub fiscal_year: i64,
2435 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2437 pub report_txt: String,
2438 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2440 pub revenue: USConsensusEstimate,
2441}
2442
2443#[derive(Debug, Clone, Serialize, Deserialize, Default)]
2445pub struct USAnalystConsensus {
2446 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2448 pub ai_summary: String,
2449 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2451 pub aichat_data: USAIChatData,
2452 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2454 pub currency: String,
2455 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2457 pub report: String,
2458 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2460 pub list: Vec<USConsensusItem>,
2461 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2463 pub opt_reports: Vec<String>,
2464 #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")]
2466 pub h5_data: serde_json::Value,
2467}
2468
2469#[cfg(test)]
2470mod tests {
2471 use super::*;
2472
2473 #[test]
2474 fn us_company_dividends_tolerates_null_recent_dividends() {
2475 let parsed: USCompanyDividends = serde_json::from_str(
2479 r#"{"dividend_history":[],"dividend_payout_history":[],"payout_ratios":[],"recent_dividends":null}"#,
2480 )
2481 .unwrap();
2482 assert!(parsed.recent_dividends.dividend_ttm.is_empty());
2483 }
2484
2485 #[test]
2486 fn institution_rating_detail_tolerates_null_series() {
2487 let parsed: InstitutionRatingDetail =
2490 serde_json::from_str(r#"{"ccy_symbol":"HK$","evaluate":null,"target":null}"#).unwrap();
2491 assert!(parsed.target.list.is_empty());
2492 assert!(parsed.evaluate.list.is_empty());
2493 }
2494}