1use serde_derive::*;
2use serde::Deserialize;
3use jqdata_derive::*;
4use bigdecimal::BigDecimal;
5use std::io::Read;
6use crate::{Result, Error};
7
8#[derive(Debug, Serialize, Deserialize)]
16pub struct Request<P> {
17    token: String,
18    method: String,
19    #[serde(flatten)]
20    payload: P,
21}
22
23pub trait HasMethod {
26    fn method(&self) -> String;
27}
28
29impl<P: HasMethod> Request<P> {
30    pub fn new(token: String, payload: P) -> Self {
31        Request{
32            token,
33            method: payload.method(),
34            payload,
35        }
36    }
37}
38
39pub trait BodyConsumer<T> 
42where for<'de> T: Deserialize<'de>
43{
44    fn consume_body<R: Read>(body: R) -> Result<T>;
45}
46
47pub trait CsvListBodyConsumer {
50    type Output: for<'de> Deserialize<'de>;
51
52    fn consume<R: Read>(body: R) -> Result<Vec<Self::Output>> {
53        let mut reader = csv::ReaderBuilder::new()
54        .from_reader(body);
56        let header_cols: Vec<&str> = reader.headers()?.into_iter().collect();
58        if header_cols.is_empty() {
59            return Err(Error::Server("empty response body returned".to_owned()));
60        }
61        let first_col = header_cols.first().cloned().unwrap();
62        if first_col.starts_with("error") {
63            return Err(Error::Server(first_col.to_owned()));
64        }
65        let mut rs = Vec::new();
66        for r in reader.deserialize() {
67            let s: Self::Output = r?;
68            rs.push(s);
69        }
70        Ok(rs)
71    }
72}
73
74pub trait LineBodyConsumer {
77    fn consume<R: Read>(body: R) -> Result<Vec<String>> {
78        use std::io::BufRead;
79        let reader = std::io::BufReader::new(body);
80        let mut rs = Vec::new();
81        for line in reader.lines() {
82            rs.push(line?);
83        }
84        Ok(rs)
85    }
86}
87
88pub trait SingleBodyConsumer<T> where T: std::str::FromStr, Error: From<T::Err> {
91    fn consume<R: Read>(body: R) -> Result<T> {
92        let mut body = body;
93        let mut vec = Vec::new();
94        std::io::copy(&mut body, &mut vec)?;
95        let s = String::from_utf8(vec)?;
96        let result = s.parse()?;
97        Ok(result)
98    }
99}
100
101pub trait JsonBodyConsumer {
104    type Output: for<'de> Deserialize<'de>;
105
106    fn consume<R: Read>(body: R) -> Result<Self::Output> {
107        let result = serde_json::from_reader(body)?;
108        Ok(result)
109    }
110}
111
112#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
114#[serde(rename_all = "snake_case")]
115pub enum SecurityKind {
116    Stock,
117    Fund,
118    Index,
119    Futures,
120    #[serde(rename = "etf")]
121    ETF,
122    #[serde(rename = "lof")]
123    LOF,
124    #[serde(rename = "fja")]
125    FJA,
126    #[serde(rename = "fjb")]
127    FJB,
128    #[serde(rename = "QDII_fund")]
129    QDIIFund,
130    OpenFund,
131    BondFund,
132    StockFund,
133    MoneyMarketFund,
134    MixtureFund,
135    Options,
136}
137
138#[derive(Debug, Serialize, Deserialize, PartialEq)]
140pub struct Security {
141    pub code: String,
142    pub display_name: String,
143    pub name: String,
144    pub start_date: String,
145    pub end_date: String,
146    #[serde(rename = "type")]
147    pub kind: SecurityKind,
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub parent: Option<String>,
150}
151
152#[derive(Debug, Serialize, Deserialize, Jqdata)]
154#[method("get_all_securities")]
155#[consume(format = "csv", type = "Security")]
156pub struct GetAllSecurities {
157    pub code: SecurityKind,
158    #[serde(skip_serializing_if = "Option::is_none")]
159    pub date: Option<String>,
160}
161
162#[derive(Debug, Serialize, Deserialize, Jqdata)]
164#[method("get_security_info")]
165#[consume(format = "csv", type = "Security")]
166pub struct GetSecurityInfo {
167    pub code: String,
168}
169
170#[derive(Debug, Serialize, Deserialize, Jqdata)]
172#[method("get_index_stocks")]
173#[consume(format = "line")]
174pub struct GetIndexStocks {
175    pub code: String,
176    pub date: String,
177}
178
179#[derive(Debug, Serialize, Deserialize, Jqdata)]
182#[method("get_margincash_stocks")]
183#[consume(format = "line")]
184pub struct GetMargincashStocks {
185    #[serde(skip_serializing_if = "Option::is_none")]
186    pub date: Option<String>,
187}
188
189#[derive(Debug, Serialize, Deserialize, Jqdata)]
191#[method("get_locked_shares")]
192#[consume(format = "csv", type = "LockedShare")]
193pub struct GetLockedShares {
194    pub code: String,
195    pub date: String,
196    pub end_date: String,
197}
198
199#[derive(Debug, Serialize, Deserialize)]
200pub struct LockedShare {
201    pub day: String,
202    pub code: String,
203    pub num: BigDecimal,
204    pub rate1: BigDecimal,
205    pub rate2: BigDecimal,
206}
207
208#[derive(Debug, Serialize, Deserialize, Jqdata)]
212#[method("get_index_weights")]
213#[consume(format = "csv", type = "IndexWeight")]
214pub struct GetIndexWeights {
215    pub code: String,
216    pub date: String,
217}
218
219#[derive(Debug, Serialize, Deserialize)]
220pub struct IndexWeight {
221    pub code: String,
222    pub display_name: String,
223    pub date: String,
224    pub weight: BigDecimal,
225}
226
227#[derive(Debug, Serialize, Deserialize, Jqdata)]
236#[method("get_industries")]
237#[consume(format = "csv", type = "IndustryIndex")]
238pub struct GetIndustries {
239    pub code: String,
240}
241
242#[derive(Debug, Serialize, Deserialize)]
243pub struct IndustryIndex {
244    pub index: String,
245    pub name: String,
246    pub start_date: String,
247}
248
249#[derive(Debug, Serialize, Deserialize, Jqdata)]
254#[method("get_industry")]
255#[consume(format = "csv", type = "Industry")]
256pub struct GetIndustry {
257    pub code: String,
258    pub date: String,
259}
260
261#[derive(Debug, Serialize, Deserialize)]
262pub struct Industry {
263    pub industry: String,
264    pub industry_code: String,
265    pub industry_name: String,
266}
267
268#[derive(Debug, Serialize, Deserialize, Jqdata)]
273#[method("get_industry_stocks")]
274#[consume(format = "line")]
275pub struct GetIndustryStocks {
276    pub code: String,
277    pub date: String,
278}
279
280#[derive(Debug, Serialize, Deserialize, Jqdata)]
285#[method("get_concepts")]
286#[consume(format = "csv", type = "Concept")]
287pub struct GetConcepts {}
288
289#[derive(Debug, Serialize, Deserialize)]
290pub struct Concept {
291    pub code: String,
292    pub name: String,
293    pub start_date: String,
294}
295
296#[derive(Debug, Serialize, Deserialize, Jqdata)]
301#[method("get_concept_stocks")]
302#[consume(format = "line")]
303pub struct GetConceptStocks {
304    pub code: String,
305    pub date: String,
306}
307
308#[derive(Debug, Serialize, Deserialize, Jqdata)]
313#[method("get_trade_days")]
314#[consume(format = "line")]
315pub struct GetTradeDays {
316    pub date: String,
317    #[serde(skip_serializing_if = "Option::is_none")]
318    pub end_date: Option<String>,
319}
320
321#[derive(Debug, Serialize, Deserialize, Jqdata)]
323#[method("get_all_trade_days")]
324#[consume(format = "line")]
325pub struct GetAllTradeDays {}
326
327#[derive(Debug, Serialize, Deserialize, Jqdata)]
343#[method("get_mtss")]
344#[consume(format = "csv", type = "Mtss")]
345pub struct GetMtss {
346    pub code: String,
347    pub date: String,
348    pub end_date: String,
349}
350
351#[derive(Debug, Serialize, Deserialize)]
352pub struct Mtss {
353    pub date: String,
354    pub sec_code: String,
355    pub fin_value: BigDecimal,
356    pub fin_refund_value: BigDecimal,
357    pub sec_value: BigDecimal,
358    pub sec_sell_value: BigDecimal,
359    pub sec_refund_value: BigDecimal,
360    pub fin_sec_value: BigDecimal,
361}
362
363#[derive(Debug, Serialize, Deserialize, Jqdata)]
383#[method("get_money_flow")]
384#[consume(format = "csv", type = "MoneyFlow")]
385pub struct GetMoneyFlow {
386    pub code: String,
387    pub date: String,
388    pub end_date: String,
389}
390
391#[derive(Debug, Serialize, Deserialize)]
392pub struct MoneyFlow {
393    pub date: String,
394    pub sec_code: String,
395    pub change_pct: BigDecimal,
396    pub net_amount_main: BigDecimal,
397    pub net_pct_main: BigDecimal,
398    pub net_amount_xl: BigDecimal,
399    pub net_pct_xl: BigDecimal,
400    pub net_amount_l: BigDecimal,
401    pub net_pct_l: BigDecimal,
402    pub net_amount_m: BigDecimal,
403    pub net_pct_m: BigDecimal,
404    pub net_amount_s: BigDecimal,
405    pub net_pct_s: BigDecimal,
406}
407
408#[derive(Debug, Serialize, Deserialize, Jqdata)]
428#[method("get_billboard_list")]
429#[consume(format = "csv", type = "BillboardStock")]
430pub struct GetBillboardList {
431    pub code: String,
432    pub date: String,
433    pub end_date: String,
434}
435
436#[derive(Debug, Serialize, Deserialize)]
437pub struct BillboardStock {
438    pub code: String,
439    pub day: String,
440    pub direction: String,
441    pub rank: i32,
442    pub abnormal_code: String,
443    pub abnormal_name: String,
444    pub sales_depart_name: String,
445    pub buy_value: BigDecimal,
446    pub buy_rate: BigDecimal,
447    pub sell_value: BigDecimal,
448    pub sell_rate: BigDecimal,
449    pub total_value: BigDecimal,
450    pub net_value: BigDecimal,
451    pub amount: BigDecimal,
452}
453
454#[derive(Debug, Serialize, Deserialize, Jqdata)]
459#[method("get_future_contracts")]
460#[consume(format = "line")]
461pub struct GetFutureContracts {
462    pub code: String,
463    pub date: String,
464}
465
466#[derive(Debug, Serialize, Deserialize, Jqdata)]
471#[method("get_dominant_future")]
472#[consume(format = "line")]
473pub struct GetDominantFuture {
474    pub code: String,
475    pub date: String,
476}
477
478#[derive(Debug, Serialize, Deserialize, Jqdata)]
498#[method("get_fund_info")]
499#[consume(format = "json", type = "FundInfo")]
500pub struct GetFundInfo {
501    pub code: String,
502    pub date: String,
503}
504
505#[derive(Debug, Serialize, Deserialize)]
506pub struct FundInfo {
507    pub fund_name: String,
508    pub fund_type: String,
509    pub fund_establishment_day: String,
510    pub fund_manager: String,
511    pub fund_management_fee: String,
512    pub fund_custodian_fee: String,
513    pub fund_status: String,
514    pub fund_size: String,
515    pub fund_share: BigDecimal,
516    pub fund_asset_allocation_proportion: String,
517    pub heavy_hold_stocks: Vec<String>,
518    pub heavy_hold_stocks_proportion: BigDecimal,
519    pub heavy_hold_bond: Vec<String>,
520    pub heavy_hold_bond_proportion: BigDecimal,
521}
522
523#[derive(Debug, Serialize, Deserialize, Jqdata)]
539#[method("get_current_tick")]
540#[consume(format = "csv", type = "Tick")]
541pub struct GetCurrentTick {
542    pub code: String,
543}
544
545#[derive(Debug, Serialize, Deserialize)]
546pub struct Tick {
547    pub time: BigDecimal,
548    pub current: BigDecimal,
549    pub high: BigDecimal,
550    pub low: BigDecimal,
551    pub volumn: BigDecimal,
552    pub money: BigDecimal,
553    pub position: BigDecimal,
554    pub a1_v: BigDecimal,
555    pub a2_v: BigDecimal,
556    pub a3_v: BigDecimal,
557    pub a4_v: BigDecimal,
558    pub a5_v: BigDecimal,
559    pub a1_p: BigDecimal,
560    pub a2_p: BigDecimal,
561    pub a3_p: BigDecimal,
562    pub a4_p: BigDecimal,
563    pub a5_p: BigDecimal,
564    pub b1_v: BigDecimal,
565    pub b2_v: BigDecimal,
566    pub b3_v: BigDecimal,
567    pub b4_v: BigDecimal,
568    pub b5_v: BigDecimal,
569    pub b1_p: BigDecimal,
570    pub b2_p: BigDecimal,
571    pub b3_p: BigDecimal,
572    pub b4_p: BigDecimal,
573    pub b5_p: BigDecimal,
574}
575
576#[derive(Debug, Serialize, Deserialize, Jqdata)]
580#[method("get_current_ticks")]
581#[consume(format = "csv", type = "Tick")]
582pub struct GetCurrentTicks {
583    pub code: String,
584}
585
586#[derive(Debug, Serialize, Deserialize, Jqdata)]
600#[method("get_extras")]
601#[consume(format = "csv", type = "Extra")]
602pub struct GetExtras {
603    pub code: String,
604    pub date: String,
605    pub end_date: String,
606}
607
608#[derive(Debug, Serialize, Deserialize)]
609pub struct Extra {
610    pub date: String,
611    pub is_st: Option<i8>,
612    pub acc_net_value: Option<f64>,
613    pub unit_net_value: Option<f64>,
614    pub futures_sett_price: Option<f64>,
615    pub futures_positions: Option<f64>,
616    pub adj_net_value: Option<f64>,
617}
618
619#[derive(Debug, Serialize, Deserialize, Jqdata)]
643#[method("get_price")]
644#[consume(format = "csv", type = "Price")]
645pub struct GetPrice {
646    pub date: String,
647    pub count: u32,
648    pub unit: String,
649    #[serde(skip_serializing_if = "Option::is_none")]
650    pub end_date: Option<String>,
651    #[serde(skip_serializing_if = "Option::is_none")]
652    pub fq_ref_date: Option<String>,
653}
654
655#[derive(Debug, Serialize, Deserialize)]
656pub struct Price {
657    pub date: String,
658    pub open: BigDecimal,
659    pub close: BigDecimal,
660    pub high: BigDecimal,
661    pub low: BigDecimal,
662    pub volume: BigDecimal,
663    pub money: BigDecimal,
664    pub paused: Option<u8>,
665    pub high_limit: Option<f64>,
666    pub low_limit: Option<f64>,
667    pub avg: Option<f64>,
668    pub pre_close: Option<f64>,
669    pub open_interest: Option<f64>,
670}
671
672#[derive(Debug, Serialize, Deserialize, Jqdata)]
696#[method("get_price_period")]
697#[consume(format = "csv", type = "Price")]
698pub struct GetPricePeriod {
699    pub code: String,
700    pub unit: String,
701    pub date: String,
702    pub end_date: String,
703    #[serde(skip_serializing_if = "Option::is_none")]
704    pub fq_ref_date: Option<String>,
705}
706
707#[derive(Debug, Serialize, Deserialize, Jqdata)]
719#[method("get_ticks")]
720#[consume(format = "csv", type = "Tick")]
721pub struct GetTicks {
722    pub code: String,
723    #[serde(skip_serializing_if = "Option::is_none")]
724    pub count: Option<u32>,
725    pub end_date: String,
726    pub skip: bool,
727}
728
729#[derive(Debug, Serialize, Deserialize, Jqdata)]
742#[method("get_ticks_period")]
743#[consume(format = "csv", type = "Tick")]
744pub struct GetTicksPeriod {
745    pub code: String,
746    pub date: String,
747    pub end_date: String,
748    pub skip: bool,
749}
750
751#[derive(Debug, Serialize, Deserialize, Jqdata)]
765#[method("get_factor_values")]
766#[consume(format = "csv", type = "FactorValue")]
767pub struct GetFactorValues {
768    pub code: String,
769    pub columns: String,
770    pub date: String,
771    pub end_date: String,
772}
773
774#[derive(Debug, Serialize, Deserialize)]
775pub struct FactorValue {
776    pub date: String,
777    pub cfo_to_ev: Option<f64>,
778    pub net_profit_ratio: Option<f64>,
779}
780
781#[derive(Debug, Serialize, Deserialize, Jqdata)]
791#[method(run_query)]
792#[consume(format = "line")]
793pub struct RunQuery {
794    pub table: String,
795    pub columns: String,
796    #[serde(skip_serializing_if = "Option::is_none")]
797    pub conditions: Option<String>,
798    #[serde(skip_serializing_if = "Option::is_none")]
799    pub count: Option<u32>,
800}
801
802#[derive(Debug, Serialize, Deserialize, Jqdata)]
804#[method("get_query_count")]
805#[consume(format = "single", type = "i32")]
806pub struct GetQueryCount {}