TushareClient

Struct TushareClient 

Source
pub struct TushareClient { /* private fields */ }
Expand description

Tushare API client

Implementations§

Source§

impl TushareClient

Source

pub fn builder() -> TushareClientBuilder

Create client builder

Examples found in repository?
examples/tracing_example.rs (line 47)
10async fn main() -> Result<(), Box<dyn std::error::Error>> {
11    println!("=== Tushare API Tracing Integration Example ===");
12    
13    // Method 1: Using tracing-log bridge (recommended for mixed ecosystems)
14    #[cfg(all(feature = "tracing", feature = "tracing-log"))] 
15    {
16        println!("\n--- Method 1: Using tracing-log bridge ---");
17        use tracing_subscriber;
18        use tracing_log::LogTracer;
19        
20        // Initialize log-to-tracing bridge
21        LogTracer::init()?;
22        
23        // Set up tracing subscriber
24        tracing_subscriber::fmt()
25            .with_env_filter("debug")
26            .with_target(false)
27            .with_thread_ids(true)
28            .with_level(true)
29            .with_max_level(tracing::Level::DEBUG)
30            .init();
31    }
32    
33    // Method 2: Using native tracing feature (when library is compiled with tracing feature)
34    #[cfg(feature = "tracing")]
35    {
36        println!("\n--- Method 2: Using native tracing feature ---");
37        println!("库和用户程序都使用 tracing\n");
38        
39        // 直接初始化 tracing subscriber
40        tracing_subscriber::fmt()
41            .with_max_level(tracing::Level::DEBUG)
42            .init();
43    }
44
45    println!("初始化 Tushare 客户端...");
46    
47    let client = TushareClient::builder()
48        .with_token("demo_token_for_testing")
49        .with_log_level(LogLevel::Debug)
50        .log_requests(true)
51        .log_responses(false)
52        .log_performance(true)
53        .build()?;
54
55    println!("创建测试请求...");
56    
57    let mut params = HashMap::new();
58    params.insert("list_status".to_string(), "L".to_string());
59    
60    let request = TushareRequest {
61        api_name: Api::StockBasic,
62        params,
63        fields: vec!["ts_code".to_string(), "name".to_string()],
64    };
65
66    println!("发送 API 请求(注意观察日志输出)...");
67    
68    // 这会触发我们库的日志输出
69    match client.call_api(&request).await {
70        Ok(_response) => {
71            println!("✅ API 调用成功(实际会因为 token 无效而失败,但能看到日志)");
72        }
73        Err(e) => {
74            println!("❌ API 调用失败(预期行为): {}", e);
75        }
76    }
77
78    #[cfg(not(feature = "tracing"))]
79    {
80        println!("\n--- Tracing feature not enabled ---");
81        println!("To enable tracing support, compile with: cargo build --features tracing");
82        println!("Or add tracing-log bridge support with: cargo build --features tracing-log");
83    }
84
85    println!("\n=== 总结 ===");
86    #[cfg(feature = "tracing")]
87    println!("✅ 使用了原生 tracing 支持,日志输出更加结构化");
88    
89    #[cfg(not(feature = "tracing"))]
90    println!("✅ 使用了 tracing-log 桥接,成功捕获了库的 log 输出");
91
92    Ok(())
93}
More examples
Hide additional examples
examples/logging_example.rs (line 14)
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // 注意:在实际使用中,您需要初始化一个日志记录器(如 env_logger)
8    // env_logger::init();
9
10    println!("=== Tushare API 日志功能演示 ===\n");
11
12    // 示例 1: 使用默认日志配置
13    println!("1. 使用默认日志配置:");
14    let client1 = TushareClient::builder()
15        .with_token("your_token_here")
16        .build()?;
17
18    // 示例 2: 自定义日志级别
19    println!("\n2. 自定义日志级别为 Debug:");
20    let client2 = TushareClient::builder()
21        .with_token("your_token_here")
22        .with_log_level(LogLevel::Debug)
23        .build()?;
24
25    // 示例 3: 详细的日志配置
26    println!("\n3. 详细的日志配置:");
27    let client3 = TushareClient::builder()
28        .with_token("your_token_here")
29        .with_log_level(LogLevel::Trace)
30        .log_requests(true)
31        .log_responses(true)
32        .log_sensitive_data(false) // 生产环境建议设为 false
33        .log_performance(true)
34        .with_connect_timeout(Duration::from_secs(5))
35        .with_timeout(Duration::from_secs(30))
36        .build()?;
37
38    // 示例 4: 使用自定义 LogConfig
39    println!("\n4. 使用自定义 LogConfig:");
40    let log_config = LogConfig {
41        level: LogLevel::Info,
42        log_requests: true,
43        log_responses: false,
44        log_responses_err: true,
45        log_sensitive_data: false,
46        log_performance: true,
47    };
48    
49    let client4 = TushareClient::builder()
50        .with_token("your_token_here")
51        .with_log_config(log_config)
52        .build()?;
53
54    // 示例 5: 关闭日志
55    println!("\n5. 关闭日志:");
56    let client5 = TushareClient::builder()
57        .with_token("your_token_here")
58        .with_log_level(LogLevel::Off)
59        .build()?;
60
61    // 演示 API 调用(需要有效的 token)
62    if std::env::var("TUSHARE_TOKEN").is_ok() {
63        println!("\n=== 实际 API 调用演示 ===");
64        
65        let client = TushareClient::builder()
66            .with_token(&std::env::var("TUSHARE_TOKEN")?)
67            .with_log_level(LogLevel::Info)
68            .log_performance(true)
69            .build()?;
70
71        let mut params = HashMap::new();
72        params.insert("list_status".to_string(), "L".to_string());
73        
74        let req = TushareRequest {
75            api_name: Api::StockBasic,
76            params,
77            fields: vec!["ts_code".to_string(), "name".to_string()],
78        };
79
80        match client.call_api(&req).await {
81            Ok(response) => {
82                if let Some(data) = response.data {
83                    println!("✅ API 调用成功,返回 {} 条记录", data.items.len());
84                }
85            }
86            Err(e) => {
87                println!("❌ API 调用失败: {}", e);
88            }
89        }
90    } else {
91        println!("\n💡 提示: 设置 TUSHARE_TOKEN 环境变量以查看实际的 API 调用日志");
92    }
93
94    println!("\n=== 日志级别说明 ===");
95    println!("• Off    - 关闭所有日志");
96    println!("• Error  - 只记录错误信息");
97    println!("• Warn   - 记录错误和警告");
98    println!("• Info   - 记录基本信息(推荐)");
99    println!("• Debug  - 记录详细调试信息");
100    println!("• Trace  - 记录所有信息包括原始数据");
101
102    println!("\n=== 日志配置选项说明 ===");
103    println!("• log_requests      - 是否记录请求参数");
104    println!("• log_responses     - 是否记录响应内容(可能很大)");
105    println!("• log_sensitive_data - 是否记录敏感数据(如 token)");
106    println!("• log_performance   - 是否记录性能指标(耗时等)");
107
108    Ok(())
109}
Source

pub fn new(token: &str) -> Self

Create a new Tushare client with default timeout settings

§Arguments
  • token - Tushare API Token
§Example
use tushare_api::TushareClient;
 
let client = TushareClient::new("your_token_here");
Examples found in repository?
examples/generic_api_usage.rs (line 11)
5async fn main() -> TushareResult<()> {
6    // 从环境变量获取 Tushare token
7    let token = env::var("TUSHARE_TOKEN")
8        .expect("请设置环境变量 TUSHARE_TOKEN");
9
10    // 创建客户端
11    let client = TushareClient::new(&token);
12
13    println!("=== 使用通用 API 方法获取股票列表 ===");
14    
15    // 使用宏构建请求(支持直接使用字符串字面量)
16    let request = TushareRequest {
17        api_name: Api::StockBasic,
18        params: params!("list_status" => "L"),
19        fields: fields!["ts_code", "symbol", "name", "area", "industry", "list_date"],
20    };
21    
22    // 调用通用 API 方法
23    let response = client.call_api(&request).await?;
24    
25    println!("API 调用成功!");
26    println!("请求 ID: {}", response.request_id);
27    println!("返回码: {}", response.code);
28    if let Some(data) = response.data {
29        println!("返回字段: {:?}", data.fields);
30        println!("数据条数: {}", data.items.len());
31        
32        // 显示前5条记录
33        println!("\n前5条股票记录:");
34        for (i, item) in data.items.iter().take(5).enumerate() {
35            println!("{}. {:?}", i + 1, item);
36        }
37    }
38    
39    println!("\n=== 使用通用 API 方法查询特定股票 ===");
40    
41    // 查询特定股票
42    let request = TushareRequest {
43        api_name: Api::StockBasic,
44        params: params!("ts_code" => "000001.SZ"),
45        fields: fields!["ts_code", "name", "industry", "market", "list_date"],
46    };
47    
48    let response = client.call_api(&request).await?;
49
50    if let Some(data) = response.data {
51        if let Some(stock_data) = data.items.first() {
52            println!("找到股票信息:");
53            for (field, value) in data.fields.iter().zip(stock_data.iter()) {
54                println!("  {}: {}", field, value);
55            }
56        } else {
57            println!("未找到该股票");
58        }
59    }
60
61    Ok(())
62}
More examples
Hide additional examples
examples/basic_usage.rs (line 13)
7async fn main() -> TushareResult<()> {
8    // 从环境变量获取 token
9    let token = env::var("TUSHARE_TOKEN")
10        .expect("请设置环境变量 TUSHARE_TOKEN");
11
12    // 创建客户端(使用默认超时设置)
13    let client = TushareClient::new(&token);
14    
15    println!("=== 使用默认超时设置获取股票基本信息 ===");
16    
17    let request = TushareRequest {
18        api_name: Api::StockBasic,
19        params: params!("list_status" => "L"),
20        fields: fields!["ts_code", "name", "industry", "area"],
21    };
22    
23    match client.call_api(&request).await {
24        Ok(response) => {
25            if let Some(data) = response.data {
26                println!("成功获取到 {} 条记录", data.items.len());
27
28                // 显示前10条记录
29                println!("\n前10条股票信息:");
30                for (i, item) in data.items.iter().take(10).enumerate() {
31                    println!("{}. {:?}", i + 1, item);
32                }
33            }
34        }
35        Err(e) => {
36            eprintln!("获取股票列表失败: {}", e);
37        }
38    }
39    
40    println!("\n=== 使用自定义超时设置查询特定股票 ===");
41    
42    // 创建客户端(自定义超时设置)
43    let client_with_timeout = TushareClient::with_timeout(
44        &token,
45        Duration::from_secs(5),  // 连接超时 5 秒
46        Duration::from_secs(60)  // 请求超时 60 秒
47    );
48    
49    let mut stock_params = HashMap::new();
50    stock_params.insert("ts_code".into(), "000001.SZ".into());
51    
52    let stock_request = TushareRequest {
53        api_name: Api::StockBasic,
54        params: stock_params,
55        fields: vec![
56            "ts_code".into(),
57            "symbol".into(),
58            "name".into(),
59            "area".into(),
60            "industry".into(),
61            "list_date".into(),
62        ],
63    };
64    
65    match client_with_timeout.call_api(&stock_request).await {
66        Ok(response) => {
67            if let Some(data) = response.data {
68                if let Some(item) = data.items.first() {
69                    println!("找到股票信息:");
70                    for (field, value) in data.fields.iter().zip(item.iter()) {
71                        println!("  {}: {}", field, value);
72                    }
73                } else {
74                    println!("未找到该股票");
75                }
76            }
77        }
78        Err(e) => {
79            eprintln!("查询股票失败: {}", e);
80        }
81    }
82
83    Ok(())
84}
Source

pub fn from_env() -> TushareResult<Self>

Create a new Tushare client from TUSHARE_TOKEN environment variable with default timeout settings

§Errors

Returns TushareError::InvalidToken if TUSHARE_TOKEN environment variable does not exist or is empty

§Example
use tushare_api::{TushareClient, TushareResult};
 
// Requires TUSHARE_TOKEN environment variable to be set
let client = TushareClient::from_env()?;
Examples found in repository?
examples/stock_conversion_example.rs (line 14)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    // Create client (you need to set TUSHARE_TOKEN environment variable)
14    let client = TushareClient::from_env()?;
15
16    // Create request for stock basic data
17    let request = request!(Api::StockBasic, {
18        "list_status" => "L"
19    }, [
20        "ts_code", "symbol", "name"
21    ]);
22
23    // Use the new generic method to get TushareEntityList<Stock> directly
24    let stock_list: TushareEntityList<Stock> = client.call_api_as(request).await?;
25
26    // Display the results
27    println!("Found {} stocks:", stock_list.len());
28    for (i, stock) in stock_list.iter().take(10).enumerate() {
29        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
30    }
31
32    if stock_list.len() > 10 {
33        println!("... and {} more stocks", stock_list.len() - 10);
34    }
35    
36    // Show pagination info
37    println!("Total records: {}", stock_list.count());
38    println!("Has more pages: {}", stock_list.has_more());
39
40    Ok(())
41}
More examples
Hide additional examples
examples/simple_stock_conversion.rs (line 14)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    // Create client (you need to set TUSHARE_TOKEN environment variable)
14    let client = TushareClient::from_env()?;
15
16    // Create request for stock basic data
17    let request = request!(Api::StockBasic, {
18        "list_status" => "L"
19    }, [
20        "ts_code", "symbol", "name"
21    ]);
22
23    // Method 1: Use the generic call_api_as method with TushareEntityList
24    println!("=== Method 1: Using call_api_as with TushareEntityList ===");
25    let stock_list: TushareEntityList<Stock> = client.call_api_as(request.clone()).await?;
26    
27    println!("Found {} stocks:", stock_list.len());
28    for (i, stock) in stock_list.iter().take(5).enumerate() {
29        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
30    }
31    
32    // Show pagination info
33    println!("Total records: {}", stock_list.count());
34    println!("Has more pages: {}", stock_list.has_more());
35
36    // Method 2: Use the traditional call_api and manual conversion
37    println!("\n=== Method 2: Using call_api + manual conversion ===");
38    let response = client.call_api(&request).await?;
39    let stocks: Vec<Stock> = tushare_api::utils::response_to_vec(response)?;
40    
41    println!("Found {} stocks:", stocks.len());
42    for (i, stock) in stocks.iter().take(5).enumerate() {
43        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
44    }
45
46    Ok(())
47}
examples/custom_type_example.rs (line 116)
111async fn main() -> Result<(), Box<dyn std::error::Error>> {
112    // Set up logging
113    env_logger::init();
114    
115    // Create client from environment variable
116    let client = TushareClient::from_env()?;
117    
118    // Create request for daily stock data
119    let request = TushareRequest::new(
120        Api::Daily,
121        params![
122            "ts_code" => "000001.SZ",
123            "start_date" => "20240101",
124            "end_date" => "20240131"
125        ],
126        fields![
127            "ts_code", "trade_date", "open", "high", "low", "close", "vol", "amount"
128        ]
129    );
130    
131    println!("Fetching daily stock data with custom Decimal types...");
132    
133    // Call API and get typed response with automatic conversion
134    let stock_prices: TushareEntityList<StockPrice> = client.call_api_as(request).await?;
135    
136    println!("Retrieved {} stock price records", stock_prices.len());
137    println!("Has more data: {}", stock_prices.has_more());
138    println!("Total count: {}", stock_prices.count());
139    
140    // Display first few records
141    for (i, price) in stock_prices.iter().take(5).enumerate() {
142        println!("\nRecord {}:", i + 1);
143        println!("  Stock Code: {}", price.ts_code);
144        println!("  Trade Date: {}", price.trade_date);
145        println!("  Open Price: {}", price.open_price);
146        println!("  High Price: {}", price.high_price);
147        println!("  Low Price: {}", price.low_price);
148        println!("  Close Price: {}", price.close_price);
149        
150        if let Some(vol) = &price.volume {
151            println!("  Volume: {}", vol);
152        }
153        
154        if let Some(amount) = &price.amount {
155            println!("  Amount: {}", amount);
156        }
157    }
158    
159    Ok(())
160}
examples/macro_conversion_example.rs (line 88)
86async fn main() -> Result<(), Box<dyn std::error::Error>> {
87    // 创建客户端
88    let client = TushareClient::from_env()?;
89
90    println!("=== 示例1: 使用 FromTushareData 派生宏获取股票基本信息 ===");
91    
92    let request = request!(Api::StockBasic, {
93        "list_status" => "L"
94    }, [
95        "ts_code", "symbol", "name", "area", "industry", "market", "list_date"
96    ]);
97
98    // 直接获取 TushareEntityList<Stock> 类型
99    let stock_list: TushareEntityList<Stock> = client.call_api_as(request).await?;
100    
101    println!("找到 {} 只股票:", stock_list.len());
102    for (i, stock) in stock_list.iter().take(5).enumerate() {
103        println!("{}. {} ({}) - {} [{}] {}", 
104            i + 1, 
105            stock.ts_code, 
106            stock.symbol, 
107            stock.name,
108            stock.area.as_deref().unwrap_or("未知"),
109            stock.industry.as_deref().unwrap_or("未知行业")
110        );
111    }
112    
113    // 显示分页信息
114    println!("总记录数: {}, 是否有更多页面: {}", stock_list.count(), stock_list.has_more());
115
116    println!("\n=== 示例2: 获取简单股票信息 ===");
117    
118    let simple_request = request!(Api::StockBasic, {
119        "list_status" => "L"
120    }, [
121        "ts_code", "symbol", "name"
122    ]);
123
124    let simple_stock_list: TushareEntityList<SimpleStock> = client.call_api_as(simple_request).await?;
125    
126    println!("找到 {} 只股票 (简化版):", simple_stock_list.len());
127    for (i, stock) in simple_stock_list.iter().take(3).enumerate() {
128        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
129    }
130
131    println!("\n=== 示例3: 获取基金信息 ===");
132    
133    let fund_request = request!(Api::FundBasic, {
134        "market" => "E"
135    }, [
136        "ts_code", "name", "management", "custodian", "fund_type", "found_date", "list_date", "status"
137    ]);
138
139    let fund_list: TushareEntityList<Fund> = client.call_api_as(fund_request).await?;
140    
141    println!("找到 {} 只基金:", fund_list.len());
142    for (i, fund) in fund_list.iter().take(3).enumerate() {
143        println!("{}. {} - {} [{}] 管理人: {}", 
144            i + 1, 
145            fund.ts_code, 
146            fund.name,
147            fund.fund_type.as_deref().unwrap_or("未知类型"),
148            fund.management.as_deref().unwrap_or("未知")
149        );
150    }
151
152    Ok(())
153}
examples/env_usage.rs (line 9)
5async fn main() -> TushareResult<()> {
6    println!("=== 使用环境变量 TUSHARE_TOKEN 创建客户端 ===");
7    
8    // 从环境变量创建客户端(使用默认超时设置)
9    let client = match TushareClient::from_env() {
10        Ok(client) => {
11            println!("✅ 成功从环境变量 TUSHARE_TOKEN 创建客户端");
12            client
13        }
14        Err(e) => {
15            eprintln!("❌ 无法从环境变量创建客户端: {}", e);
16            eprintln!("请确保设置了环境变量 TUSHARE_TOKEN");
17            eprintln!("例如: export TUSHARE_TOKEN=your_token_here");
18            return Err(e);
19        }
20    };
21    
22    // 使用宏构建请求(支持直接使用字符串字面量)
23    let request = TushareRequest {
24        api_name: Api::StockBasic,
25        params: params!("list_status" => "L"),
26        fields: fields!["ts_code", "name", "industry", "area"],
27    };
28    
29    // 调用 API
30    match client.call_api(&request).await {
31        Ok(response) => {
32            if let Some(data) = response.data {
33                println!("✅ 成功获取到 {} 条记录", data.items.len());
34
35                // 显示前5条记录
36                println!("\n前5条股票信息:");
37                for (i, item) in data.items.iter().take(5).enumerate() {
38                    println!("{}. {:?}", i + 1, item);
39                }
40            }
41        }
42        Err(e) => {
43            eprintln!("❌ 获取股票列表失败: {}", e);
44        }
45    }
46    
47    println!("\n=== 使用环境变量和自定义超时设置 ===");
48    
49    // 从环境变量创建客户端(自定义超时设置)
50    let client_with_timeout = TushareClient::from_env_with_timeout(
51        Duration::from_secs(5),  // 连接超时 5 秒
52        Duration::from_secs(60)  // 请求超时 60 秒
53    )?;
54    
55    println!("\n=== 演示自定义 API 调用 ===\n");
56    
57    let custom_request = TushareRequest {
58        api_name: Api::Custom("daily".to_string()),
59        params: params!("ts_code" => "000001.SZ"),
60        fields: fields!["ts_code", "trade_date", "close"],
61    };
62    
63    match client_with_timeout.call_api(&custom_request).await {
64        Ok(response) => {
65            if let Some(data) = response.data {
66                if let Some(item) = data.items.first() {
67                    println!("✅ 找到股票信息:");
68                    for (field, value) in data.fields.iter().zip(item.iter()) {
69                        println!("  {}: {}", field, value);
70                    }
71                } else {
72                    println!("未找到该股票");
73                }
74            }
75        }
76        Err(e) => {
77            eprintln!("❌ 查询股票失败: {}", e);
78        }
79    }
80
81    Ok(())
82}
Source

pub fn from_env_with_timeout( connect_timeout: Duration, timeout: Duration, ) -> TushareResult<Self>

Create a new Tushare client from TUSHARE_TOKEN environment variable with custom timeout settings

§Arguments
  • connect_timeout - Connection timeout duration
  • timeout - Request timeout duration
§Errors

Returns TushareError::InvalidToken if TUSHARE_TOKEN environment variable does not exist or is empty

§Example
use tushare_api::{TushareClient, TushareResult};
use std::time::Duration;
 
// Requires TUSHARE_TOKEN environment variable to be set
let client = TushareClient::from_env_with_timeout(
    Duration::from_secs(5),  // Connection timeout 5 seconds
    Duration::from_secs(60)  // Request timeout 60 seconds
)?;
Examples found in repository?
examples/env_usage.rs (lines 50-53)
5async fn main() -> TushareResult<()> {
6    println!("=== 使用环境变量 TUSHARE_TOKEN 创建客户端 ===");
7    
8    // 从环境变量创建客户端(使用默认超时设置)
9    let client = match TushareClient::from_env() {
10        Ok(client) => {
11            println!("✅ 成功从环境变量 TUSHARE_TOKEN 创建客户端");
12            client
13        }
14        Err(e) => {
15            eprintln!("❌ 无法从环境变量创建客户端: {}", e);
16            eprintln!("请确保设置了环境变量 TUSHARE_TOKEN");
17            eprintln!("例如: export TUSHARE_TOKEN=your_token_here");
18            return Err(e);
19        }
20    };
21    
22    // 使用宏构建请求(支持直接使用字符串字面量)
23    let request = TushareRequest {
24        api_name: Api::StockBasic,
25        params: params!("list_status" => "L"),
26        fields: fields!["ts_code", "name", "industry", "area"],
27    };
28    
29    // 调用 API
30    match client.call_api(&request).await {
31        Ok(response) => {
32            if let Some(data) = response.data {
33                println!("✅ 成功获取到 {} 条记录", data.items.len());
34
35                // 显示前5条记录
36                println!("\n前5条股票信息:");
37                for (i, item) in data.items.iter().take(5).enumerate() {
38                    println!("{}. {:?}", i + 1, item);
39                }
40            }
41        }
42        Err(e) => {
43            eprintln!("❌ 获取股票列表失败: {}", e);
44        }
45    }
46    
47    println!("\n=== 使用环境变量和自定义超时设置 ===");
48    
49    // 从环境变量创建客户端(自定义超时设置)
50    let client_with_timeout = TushareClient::from_env_with_timeout(
51        Duration::from_secs(5),  // 连接超时 5 秒
52        Duration::from_secs(60)  // 请求超时 60 秒
53    )?;
54    
55    println!("\n=== 演示自定义 API 调用 ===\n");
56    
57    let custom_request = TushareRequest {
58        api_name: Api::Custom("daily".to_string()),
59        params: params!("ts_code" => "000001.SZ"),
60        fields: fields!["ts_code", "trade_date", "close"],
61    };
62    
63    match client_with_timeout.call_api(&custom_request).await {
64        Ok(response) => {
65            if let Some(data) = response.data {
66                if let Some(item) = data.items.first() {
67                    println!("✅ 找到股票信息:");
68                    for (field, value) in data.fields.iter().zip(item.iter()) {
69                        println!("  {}: {}", field, value);
70                    }
71                } else {
72                    println!("未找到该股票");
73                }
74            }
75        }
76        Err(e) => {
77            eprintln!("❌ 查询股票失败: {}", e);
78        }
79    }
80
81    Ok(())
82}
Source

pub fn with_timeout( token: &str, connect_timeout: Duration, timeout: Duration, ) -> Self

Create a new Tushare client with custom timeout settings

§Arguments
  • token - Tushare API Token
  • connect_timeout - Connection timeout duration
  • timeout - Request timeout duration
§Example
use tushare_api::TushareClient;
use std::time::Duration;
 
let client = TushareClient::with_timeout(
    "your_token_here",
    Duration::from_secs(5),  // Connection timeout 5 seconds
    Duration::from_secs(60)  // Request timeout 60 seconds
);
Examples found in repository?
examples/basic_usage.rs (lines 43-47)
7async fn main() -> TushareResult<()> {
8    // 从环境变量获取 token
9    let token = env::var("TUSHARE_TOKEN")
10        .expect("请设置环境变量 TUSHARE_TOKEN");
11
12    // 创建客户端(使用默认超时设置)
13    let client = TushareClient::new(&token);
14    
15    println!("=== 使用默认超时设置获取股票基本信息 ===");
16    
17    let request = TushareRequest {
18        api_name: Api::StockBasic,
19        params: params!("list_status" => "L"),
20        fields: fields!["ts_code", "name", "industry", "area"],
21    };
22    
23    match client.call_api(&request).await {
24        Ok(response) => {
25            if let Some(data) = response.data {
26                println!("成功获取到 {} 条记录", data.items.len());
27
28                // 显示前10条记录
29                println!("\n前10条股票信息:");
30                for (i, item) in data.items.iter().take(10).enumerate() {
31                    println!("{}. {:?}", i + 1, item);
32                }
33            }
34        }
35        Err(e) => {
36            eprintln!("获取股票列表失败: {}", e);
37        }
38    }
39    
40    println!("\n=== 使用自定义超时设置查询特定股票 ===");
41    
42    // 创建客户端(自定义超时设置)
43    let client_with_timeout = TushareClient::with_timeout(
44        &token,
45        Duration::from_secs(5),  // 连接超时 5 秒
46        Duration::from_secs(60)  // 请求超时 60 秒
47    );
48    
49    let mut stock_params = HashMap::new();
50    stock_params.insert("ts_code".into(), "000001.SZ".into());
51    
52    let stock_request = TushareRequest {
53        api_name: Api::StockBasic,
54        params: stock_params,
55        fields: vec![
56            "ts_code".into(),
57            "symbol".into(),
58            "name".into(),
59            "area".into(),
60            "industry".into(),
61            "list_date".into(),
62        ],
63    };
64    
65    match client_with_timeout.call_api(&stock_request).await {
66        Ok(response) => {
67            if let Some(data) = response.data {
68                if let Some(item) = data.items.first() {
69                    println!("找到股票信息:");
70                    for (field, value) in data.fields.iter().zip(item.iter()) {
71                        println!("  {}: {}", field, value);
72                    }
73                } else {
74                    println!("未找到该股票");
75                }
76            }
77        }
78        Err(e) => {
79            eprintln!("查询股票失败: {}", e);
80        }
81    }
82
83    Ok(())
84}
Source

pub async fn call_api<T>(&self, request: &T) -> TushareResult<TushareResponse>

Call Tushare API with flexible string types support

§Arguments
  • request - API request parameters, supports direct use of string literals
§Returns

Returns API response result

§Example
use tushare_api::{TushareClient, TushareRequest, Api, params, fields, request};
 
    let client = TushareClient::new("your_token_here");
     
    // Now you can use string literals directly!
    let request = request!(Api::StockBasic, {
        "list_status" => "L"
    }, [
        "ts_code", "name"
    ]);
     
    let response = client.call_api(&request).await?;
    println!("Response: {:?}", response);
Examples found in repository?
examples/simple_stock_conversion.rs (line 38)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    // Create client (you need to set TUSHARE_TOKEN environment variable)
14    let client = TushareClient::from_env()?;
15
16    // Create request for stock basic data
17    let request = request!(Api::StockBasic, {
18        "list_status" => "L"
19    }, [
20        "ts_code", "symbol", "name"
21    ]);
22
23    // Method 1: Use the generic call_api_as method with TushareEntityList
24    println!("=== Method 1: Using call_api_as with TushareEntityList ===");
25    let stock_list: TushareEntityList<Stock> = client.call_api_as(request.clone()).await?;
26    
27    println!("Found {} stocks:", stock_list.len());
28    for (i, stock) in stock_list.iter().take(5).enumerate() {
29        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
30    }
31    
32    // Show pagination info
33    println!("Total records: {}", stock_list.count());
34    println!("Has more pages: {}", stock_list.has_more());
35
36    // Method 2: Use the traditional call_api and manual conversion
37    println!("\n=== Method 2: Using call_api + manual conversion ===");
38    let response = client.call_api(&request).await?;
39    let stocks: Vec<Stock> = tushare_api::utils::response_to_vec(response)?;
40    
41    println!("Found {} stocks:", stocks.len());
42    for (i, stock) in stocks.iter().take(5).enumerate() {
43        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
44    }
45
46    Ok(())
47}
More examples
Hide additional examples
examples/generic_api_usage.rs (line 23)
5async fn main() -> TushareResult<()> {
6    // 从环境变量获取 Tushare token
7    let token = env::var("TUSHARE_TOKEN")
8        .expect("请设置环境变量 TUSHARE_TOKEN");
9
10    // 创建客户端
11    let client = TushareClient::new(&token);
12
13    println!("=== 使用通用 API 方法获取股票列表 ===");
14    
15    // 使用宏构建请求(支持直接使用字符串字面量)
16    let request = TushareRequest {
17        api_name: Api::StockBasic,
18        params: params!("list_status" => "L"),
19        fields: fields!["ts_code", "symbol", "name", "area", "industry", "list_date"],
20    };
21    
22    // 调用通用 API 方法
23    let response = client.call_api(&request).await?;
24    
25    println!("API 调用成功!");
26    println!("请求 ID: {}", response.request_id);
27    println!("返回码: {}", response.code);
28    if let Some(data) = response.data {
29        println!("返回字段: {:?}", data.fields);
30        println!("数据条数: {}", data.items.len());
31        
32        // 显示前5条记录
33        println!("\n前5条股票记录:");
34        for (i, item) in data.items.iter().take(5).enumerate() {
35            println!("{}. {:?}", i + 1, item);
36        }
37    }
38    
39    println!("\n=== 使用通用 API 方法查询特定股票 ===");
40    
41    // 查询特定股票
42    let request = TushareRequest {
43        api_name: Api::StockBasic,
44        params: params!("ts_code" => "000001.SZ"),
45        fields: fields!["ts_code", "name", "industry", "market", "list_date"],
46    };
47    
48    let response = client.call_api(&request).await?;
49
50    if let Some(data) = response.data {
51        if let Some(stock_data) = data.items.first() {
52            println!("找到股票信息:");
53            for (field, value) in data.fields.iter().zip(stock_data.iter()) {
54                println!("  {}: {}", field, value);
55            }
56        } else {
57            println!("未找到该股票");
58        }
59    }
60
61    Ok(())
62}
examples/basic_usage.rs (line 23)
7async fn main() -> TushareResult<()> {
8    // 从环境变量获取 token
9    let token = env::var("TUSHARE_TOKEN")
10        .expect("请设置环境变量 TUSHARE_TOKEN");
11
12    // 创建客户端(使用默认超时设置)
13    let client = TushareClient::new(&token);
14    
15    println!("=== 使用默认超时设置获取股票基本信息 ===");
16    
17    let request = TushareRequest {
18        api_name: Api::StockBasic,
19        params: params!("list_status" => "L"),
20        fields: fields!["ts_code", "name", "industry", "area"],
21    };
22    
23    match client.call_api(&request).await {
24        Ok(response) => {
25            if let Some(data) = response.data {
26                println!("成功获取到 {} 条记录", data.items.len());
27
28                // 显示前10条记录
29                println!("\n前10条股票信息:");
30                for (i, item) in data.items.iter().take(10).enumerate() {
31                    println!("{}. {:?}", i + 1, item);
32                }
33            }
34        }
35        Err(e) => {
36            eprintln!("获取股票列表失败: {}", e);
37        }
38    }
39    
40    println!("\n=== 使用自定义超时设置查询特定股票 ===");
41    
42    // 创建客户端(自定义超时设置)
43    let client_with_timeout = TushareClient::with_timeout(
44        &token,
45        Duration::from_secs(5),  // 连接超时 5 秒
46        Duration::from_secs(60)  // 请求超时 60 秒
47    );
48    
49    let mut stock_params = HashMap::new();
50    stock_params.insert("ts_code".into(), "000001.SZ".into());
51    
52    let stock_request = TushareRequest {
53        api_name: Api::StockBasic,
54        params: stock_params,
55        fields: vec![
56            "ts_code".into(),
57            "symbol".into(),
58            "name".into(),
59            "area".into(),
60            "industry".into(),
61            "list_date".into(),
62        ],
63    };
64    
65    match client_with_timeout.call_api(&stock_request).await {
66        Ok(response) => {
67            if let Some(data) = response.data {
68                if let Some(item) = data.items.first() {
69                    println!("找到股票信息:");
70                    for (field, value) in data.fields.iter().zip(item.iter()) {
71                        println!("  {}: {}", field, value);
72                    }
73                } else {
74                    println!("未找到该股票");
75                }
76            }
77        }
78        Err(e) => {
79            eprintln!("查询股票失败: {}", e);
80        }
81    }
82
83    Ok(())
84}
examples/env_usage.rs (line 30)
5async fn main() -> TushareResult<()> {
6    println!("=== 使用环境变量 TUSHARE_TOKEN 创建客户端 ===");
7    
8    // 从环境变量创建客户端(使用默认超时设置)
9    let client = match TushareClient::from_env() {
10        Ok(client) => {
11            println!("✅ 成功从环境变量 TUSHARE_TOKEN 创建客户端");
12            client
13        }
14        Err(e) => {
15            eprintln!("❌ 无法从环境变量创建客户端: {}", e);
16            eprintln!("请确保设置了环境变量 TUSHARE_TOKEN");
17            eprintln!("例如: export TUSHARE_TOKEN=your_token_here");
18            return Err(e);
19        }
20    };
21    
22    // 使用宏构建请求(支持直接使用字符串字面量)
23    let request = TushareRequest {
24        api_name: Api::StockBasic,
25        params: params!("list_status" => "L"),
26        fields: fields!["ts_code", "name", "industry", "area"],
27    };
28    
29    // 调用 API
30    match client.call_api(&request).await {
31        Ok(response) => {
32            if let Some(data) = response.data {
33                println!("✅ 成功获取到 {} 条记录", data.items.len());
34
35                // 显示前5条记录
36                println!("\n前5条股票信息:");
37                for (i, item) in data.items.iter().take(5).enumerate() {
38                    println!("{}. {:?}", i + 1, item);
39                }
40            }
41        }
42        Err(e) => {
43            eprintln!("❌ 获取股票列表失败: {}", e);
44        }
45    }
46    
47    println!("\n=== 使用环境变量和自定义超时设置 ===");
48    
49    // 从环境变量创建客户端(自定义超时设置)
50    let client_with_timeout = TushareClient::from_env_with_timeout(
51        Duration::from_secs(5),  // 连接超时 5 秒
52        Duration::from_secs(60)  // 请求超时 60 秒
53    )?;
54    
55    println!("\n=== 演示自定义 API 调用 ===\n");
56    
57    let custom_request = TushareRequest {
58        api_name: Api::Custom("daily".to_string()),
59        params: params!("ts_code" => "000001.SZ"),
60        fields: fields!["ts_code", "trade_date", "close"],
61    };
62    
63    match client_with_timeout.call_api(&custom_request).await {
64        Ok(response) => {
65            if let Some(data) = response.data {
66                if let Some(item) = data.items.first() {
67                    println!("✅ 找到股票信息:");
68                    for (field, value) in data.fields.iter().zip(item.iter()) {
69                        println!("  {}: {}", field, value);
70                    }
71                } else {
72                    println!("未找到该股票");
73                }
74            }
75        }
76        Err(e) => {
77            eprintln!("❌ 查询股票失败: {}", e);
78        }
79    }
80
81    Ok(())
82}
examples/tracing_example.rs (line 69)
10async fn main() -> Result<(), Box<dyn std::error::Error>> {
11    println!("=== Tushare API Tracing Integration Example ===");
12    
13    // Method 1: Using tracing-log bridge (recommended for mixed ecosystems)
14    #[cfg(all(feature = "tracing", feature = "tracing-log"))] 
15    {
16        println!("\n--- Method 1: Using tracing-log bridge ---");
17        use tracing_subscriber;
18        use tracing_log::LogTracer;
19        
20        // Initialize log-to-tracing bridge
21        LogTracer::init()?;
22        
23        // Set up tracing subscriber
24        tracing_subscriber::fmt()
25            .with_env_filter("debug")
26            .with_target(false)
27            .with_thread_ids(true)
28            .with_level(true)
29            .with_max_level(tracing::Level::DEBUG)
30            .init();
31    }
32    
33    // Method 2: Using native tracing feature (when library is compiled with tracing feature)
34    #[cfg(feature = "tracing")]
35    {
36        println!("\n--- Method 2: Using native tracing feature ---");
37        println!("库和用户程序都使用 tracing\n");
38        
39        // 直接初始化 tracing subscriber
40        tracing_subscriber::fmt()
41            .with_max_level(tracing::Level::DEBUG)
42            .init();
43    }
44
45    println!("初始化 Tushare 客户端...");
46    
47    let client = TushareClient::builder()
48        .with_token("demo_token_for_testing")
49        .with_log_level(LogLevel::Debug)
50        .log_requests(true)
51        .log_responses(false)
52        .log_performance(true)
53        .build()?;
54
55    println!("创建测试请求...");
56    
57    let mut params = HashMap::new();
58    params.insert("list_status".to_string(), "L".to_string());
59    
60    let request = TushareRequest {
61        api_name: Api::StockBasic,
62        params,
63        fields: vec!["ts_code".to_string(), "name".to_string()],
64    };
65
66    println!("发送 API 请求(注意观察日志输出)...");
67    
68    // 这会触发我们库的日志输出
69    match client.call_api(&request).await {
70        Ok(_response) => {
71            println!("✅ API 调用成功(实际会因为 token 无效而失败,但能看到日志)");
72        }
73        Err(e) => {
74            println!("❌ API 调用失败(预期行为): {}", e);
75        }
76    }
77
78    #[cfg(not(feature = "tracing"))]
79    {
80        println!("\n--- Tracing feature not enabled ---");
81        println!("To enable tracing support, compile with: cargo build --features tracing");
82        println!("Or add tracing-log bridge support with: cargo build --features tracing-log");
83    }
84
85    println!("\n=== 总结 ===");
86    #[cfg(feature = "tracing")]
87    println!("✅ 使用了原生 tracing 支持,日志输出更加结构化");
88    
89    #[cfg(not(feature = "tracing"))]
90    println!("✅ 使用了 tracing-log 桥接,成功捕获了库的 log 输出");
91
92    Ok(())
93}
examples/logging_example.rs (line 80)
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7    // 注意:在实际使用中,您需要初始化一个日志记录器(如 env_logger)
8    // env_logger::init();
9
10    println!("=== Tushare API 日志功能演示 ===\n");
11
12    // 示例 1: 使用默认日志配置
13    println!("1. 使用默认日志配置:");
14    let client1 = TushareClient::builder()
15        .with_token("your_token_here")
16        .build()?;
17
18    // 示例 2: 自定义日志级别
19    println!("\n2. 自定义日志级别为 Debug:");
20    let client2 = TushareClient::builder()
21        .with_token("your_token_here")
22        .with_log_level(LogLevel::Debug)
23        .build()?;
24
25    // 示例 3: 详细的日志配置
26    println!("\n3. 详细的日志配置:");
27    let client3 = TushareClient::builder()
28        .with_token("your_token_here")
29        .with_log_level(LogLevel::Trace)
30        .log_requests(true)
31        .log_responses(true)
32        .log_sensitive_data(false) // 生产环境建议设为 false
33        .log_performance(true)
34        .with_connect_timeout(Duration::from_secs(5))
35        .with_timeout(Duration::from_secs(30))
36        .build()?;
37
38    // 示例 4: 使用自定义 LogConfig
39    println!("\n4. 使用自定义 LogConfig:");
40    let log_config = LogConfig {
41        level: LogLevel::Info,
42        log_requests: true,
43        log_responses: false,
44        log_responses_err: true,
45        log_sensitive_data: false,
46        log_performance: true,
47    };
48    
49    let client4 = TushareClient::builder()
50        .with_token("your_token_here")
51        .with_log_config(log_config)
52        .build()?;
53
54    // 示例 5: 关闭日志
55    println!("\n5. 关闭日志:");
56    let client5 = TushareClient::builder()
57        .with_token("your_token_here")
58        .with_log_level(LogLevel::Off)
59        .build()?;
60
61    // 演示 API 调用(需要有效的 token)
62    if std::env::var("TUSHARE_TOKEN").is_ok() {
63        println!("\n=== 实际 API 调用演示 ===");
64        
65        let client = TushareClient::builder()
66            .with_token(&std::env::var("TUSHARE_TOKEN")?)
67            .with_log_level(LogLevel::Info)
68            .log_performance(true)
69            .build()?;
70
71        let mut params = HashMap::new();
72        params.insert("list_status".to_string(), "L".to_string());
73        
74        let req = TushareRequest {
75            api_name: Api::StockBasic,
76            params,
77            fields: vec!["ts_code".to_string(), "name".to_string()],
78        };
79
80        match client.call_api(&req).await {
81            Ok(response) => {
82                if let Some(data) = response.data {
83                    println!("✅ API 调用成功,返回 {} 条记录", data.items.len());
84                }
85            }
86            Err(e) => {
87                println!("❌ API 调用失败: {}", e);
88            }
89        }
90    } else {
91        println!("\n💡 提示: 设置 TUSHARE_TOKEN 环境变量以查看实际的 API 调用日志");
92    }
93
94    println!("\n=== 日志级别说明 ===");
95    println!("• Off    - 关闭所有日志");
96    println!("• Error  - 只记录错误信息");
97    println!("• Warn   - 记录错误和警告");
98    println!("• Info   - 记录基本信息(推荐)");
99    println!("• Debug  - 记录详细调试信息");
100    println!("• Trace  - 记录所有信息包括原始数据");
101
102    println!("\n=== 日志配置选项说明 ===");
103    println!("• log_requests      - 是否记录请求参数");
104    println!("• log_responses     - 是否记录响应内容(可能很大)");
105    println!("• log_sensitive_data - 是否记录敏感数据(如 token)");
106    println!("• log_performance   - 是否记录性能指标(耗时等)");
107
108    Ok(())
109}
Source

pub async fn call_api_as<T, R>( &self, request: R, ) -> TushareResult<TushareEntityList<T>>

调用 Tushare API,并将响应的 data.items 解析为强类型的 TushareEntityList<T>

这是 Self::call_api 的便捷封装:先执行请求,再把响应转换为实体列表。

§Type Parameters
  • T: 单行数据对应的实体类型(需要实现 crate::traits::FromTushareData)。
  • R: 请求类型(需要实现 TryInto<TushareRequest>),通常可由参数自动推导。
§Errors
  • 请求构造失败、网络/HTTP 错误、JSON/数据映射失败等都会以 TushareError 返回。
§Example
let client = TushareClient::from_env()?;
let stocks: TushareEntityList<Stock> = client
    .call_api_as(request!(Api::StockBasic, {}, ["ts_code"]))
    .await?;
Examples found in repository?
examples/stock_conversion_example.rs (line 24)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    // Create client (you need to set TUSHARE_TOKEN environment variable)
14    let client = TushareClient::from_env()?;
15
16    // Create request for stock basic data
17    let request = request!(Api::StockBasic, {
18        "list_status" => "L"
19    }, [
20        "ts_code", "symbol", "name"
21    ]);
22
23    // Use the new generic method to get TushareEntityList<Stock> directly
24    let stock_list: TushareEntityList<Stock> = client.call_api_as(request).await?;
25
26    // Display the results
27    println!("Found {} stocks:", stock_list.len());
28    for (i, stock) in stock_list.iter().take(10).enumerate() {
29        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
30    }
31
32    if stock_list.len() > 10 {
33        println!("... and {} more stocks", stock_list.len() - 10);
34    }
35    
36    // Show pagination info
37    println!("Total records: {}", stock_list.count());
38    println!("Has more pages: {}", stock_list.has_more());
39
40    Ok(())
41}
More examples
Hide additional examples
examples/simple_stock_conversion.rs (line 25)
12async fn main() -> Result<(), Box<dyn std::error::Error>> {
13    // Create client (you need to set TUSHARE_TOKEN environment variable)
14    let client = TushareClient::from_env()?;
15
16    // Create request for stock basic data
17    let request = request!(Api::StockBasic, {
18        "list_status" => "L"
19    }, [
20        "ts_code", "symbol", "name"
21    ]);
22
23    // Method 1: Use the generic call_api_as method with TushareEntityList
24    println!("=== Method 1: Using call_api_as with TushareEntityList ===");
25    let stock_list: TushareEntityList<Stock> = client.call_api_as(request.clone()).await?;
26    
27    println!("Found {} stocks:", stock_list.len());
28    for (i, stock) in stock_list.iter().take(5).enumerate() {
29        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
30    }
31    
32    // Show pagination info
33    println!("Total records: {}", stock_list.count());
34    println!("Has more pages: {}", stock_list.has_more());
35
36    // Method 2: Use the traditional call_api and manual conversion
37    println!("\n=== Method 2: Using call_api + manual conversion ===");
38    let response = client.call_api(&request).await?;
39    let stocks: Vec<Stock> = tushare_api::utils::response_to_vec(response)?;
40    
41    println!("Found {} stocks:", stocks.len());
42    for (i, stock) in stocks.iter().take(5).enumerate() {
43        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
44    }
45
46    Ok(())
47}
examples/custom_type_example.rs (line 134)
111async fn main() -> Result<(), Box<dyn std::error::Error>> {
112    // Set up logging
113    env_logger::init();
114    
115    // Create client from environment variable
116    let client = TushareClient::from_env()?;
117    
118    // Create request for daily stock data
119    let request = TushareRequest::new(
120        Api::Daily,
121        params![
122            "ts_code" => "000001.SZ",
123            "start_date" => "20240101",
124            "end_date" => "20240131"
125        ],
126        fields![
127            "ts_code", "trade_date", "open", "high", "low", "close", "vol", "amount"
128        ]
129    );
130    
131    println!("Fetching daily stock data with custom Decimal types...");
132    
133    // Call API and get typed response with automatic conversion
134    let stock_prices: TushareEntityList<StockPrice> = client.call_api_as(request).await?;
135    
136    println!("Retrieved {} stock price records", stock_prices.len());
137    println!("Has more data: {}", stock_prices.has_more());
138    println!("Total count: {}", stock_prices.count());
139    
140    // Display first few records
141    for (i, price) in stock_prices.iter().take(5).enumerate() {
142        println!("\nRecord {}:", i + 1);
143        println!("  Stock Code: {}", price.ts_code);
144        println!("  Trade Date: {}", price.trade_date);
145        println!("  Open Price: {}", price.open_price);
146        println!("  High Price: {}", price.high_price);
147        println!("  Low Price: {}", price.low_price);
148        println!("  Close Price: {}", price.close_price);
149        
150        if let Some(vol) = &price.volume {
151            println!("  Volume: {}", vol);
152        }
153        
154        if let Some(amount) = &price.amount {
155            println!("  Amount: {}", amount);
156        }
157    }
158    
159    Ok(())
160}
examples/macro_conversion_example.rs (line 99)
86async fn main() -> Result<(), Box<dyn std::error::Error>> {
87    // 创建客户端
88    let client = TushareClient::from_env()?;
89
90    println!("=== 示例1: 使用 FromTushareData 派生宏获取股票基本信息 ===");
91    
92    let request = request!(Api::StockBasic, {
93        "list_status" => "L"
94    }, [
95        "ts_code", "symbol", "name", "area", "industry", "market", "list_date"
96    ]);
97
98    // 直接获取 TushareEntityList<Stock> 类型
99    let stock_list: TushareEntityList<Stock> = client.call_api_as(request).await?;
100    
101    println!("找到 {} 只股票:", stock_list.len());
102    for (i, stock) in stock_list.iter().take(5).enumerate() {
103        println!("{}. {} ({}) - {} [{}] {}", 
104            i + 1, 
105            stock.ts_code, 
106            stock.symbol, 
107            stock.name,
108            stock.area.as_deref().unwrap_or("未知"),
109            stock.industry.as_deref().unwrap_or("未知行业")
110        );
111    }
112    
113    // 显示分页信息
114    println!("总记录数: {}, 是否有更多页面: {}", stock_list.count(), stock_list.has_more());
115
116    println!("\n=== 示例2: 获取简单股票信息 ===");
117    
118    let simple_request = request!(Api::StockBasic, {
119        "list_status" => "L"
120    }, [
121        "ts_code", "symbol", "name"
122    ]);
123
124    let simple_stock_list: TushareEntityList<SimpleStock> = client.call_api_as(simple_request).await?;
125    
126    println!("找到 {} 只股票 (简化版):", simple_stock_list.len());
127    for (i, stock) in simple_stock_list.iter().take(3).enumerate() {
128        println!("{}. {} ({}) - {}", i + 1, stock.ts_code, stock.symbol, stock.name);
129    }
130
131    println!("\n=== 示例3: 获取基金信息 ===");
132    
133    let fund_request = request!(Api::FundBasic, {
134        "market" => "E"
135    }, [
136        "ts_code", "name", "management", "custodian", "fund_type", "found_date", "list_date", "status"
137    ]);
138
139    let fund_list: TushareEntityList<Fund> = client.call_api_as(fund_request).await?;
140    
141    println!("找到 {} 只基金:", fund_list.len());
142    for (i, fund) in fund_list.iter().take(3).enumerate() {
143        println!("{}. {} - {} [{}] 管理人: {}", 
144            i + 1, 
145            fund.ts_code, 
146            fund.name,
147            fund.fund_type.as_deref().unwrap_or("未知类型"),
148            fund.management.as_deref().unwrap_or("未知")
149        );
150    }
151
152    Ok(())
153}

Trait Implementations§

Source§

impl Debug for TushareClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,