pub struct TushareClient { /* private fields */ }Expand description
Tushare API client
Implementations§
Sourcepub fn builder() -> TushareClientBuilder
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
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}Sourcepub fn new(token: &str) -> Self
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
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}Sourcepub fn from_env() -> TushareResult<Self>
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
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}Sourcepub fn from_env_with_timeout(
connect_timeout: Duration,
timeout: Duration,
) -> TushareResult<Self>
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 durationtimeout- 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}Sourcepub fn with_timeout(
token: &str,
connect_timeout: Duration,
timeout: Duration,
) -> Self
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 Tokenconnect_timeout- Connection timeout durationtimeout- 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}Sourcepub async fn call_api<T>(&self, request: &T) -> TushareResult<TushareResponse>where
for<'a> &'a T: TryInto<TushareRequest>,
for<'a> <&'a T as TryInto<TushareRequest>>::Error: Into<TushareError>,
pub async fn call_api<T>(&self, request: &T) -> TushareResult<TushareResponse>where
for<'a> &'a T: TryInto<TushareRequest>,
for<'a> <&'a T as TryInto<TushareRequest>>::Error: Into<TushareError>,
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
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}Sourcepub async fn call_api_as<T, R>(
&self,
request: R,
) -> TushareResult<TushareEntityList<T>>where
T: FromTushareData,
for<'a> &'a R: TryInto<TushareRequest>,
for<'a> <&'a R as TryInto<TushareRequest>>::Error: Into<TushareError>,
pub async fn call_api_as<T, R>(
&self,
request: R,
) -> TushareResult<TushareEntityList<T>>where
T: FromTushareData,
for<'a> &'a R: TryInto<TushareRequest>,
for<'a> <&'a R as TryInto<TushareRequest>>::Error: Into<TushareError>,
调用 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
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§
Auto Trait Implementations§
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more