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}
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");
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}
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
)?;
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
);
Source

pub async fn call_api( &self, request: TushareRequest, ) -> 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/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}
Source

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

Call Tushare API with automatic type conversion to TushareEntityList<T>

This method provides a clean, type-safe way to get paginated API responses. You specify the entity type T, and get back a TushareEntityList<T> with built-in pagination metadata.

§Type Parameters
  • T - The entity type that implements FromTushareData
§Arguments
  • request - API request parameters
§Returns

Returns a TushareEntityList<T> containing:

  • items: Vec<T> - The converted data items
  • has_more: bool - Whether more pages are available
  • count: i64 - Total number of records across all pages
§Example
use tushare_api::{TushareClient, Api, request, TushareEntityList, params, fields, TushareRequest, DeriveFromTushareData};
#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct Stock {
    pub ts_code: String,
    pub name: String,
    pub area: Option<String>,
}
 
    let client = TushareClient::from_env()?;
     
    // Clean, intuitive API call
    let stocks: TushareEntityList<Stock> = client.call_api_as(request!(
        Api::StockBasic, {
            "list_status" => "L",
            "limit" => "100"
        }, [
            "ts_code", "name", "area"
        ]
    )).await?;
     
    // Access pagination info
    println!("Current page: {} stocks", stocks.len());
    println!("Total available: {} stocks", stocks.count());
    println!("Has more pages: {}", stocks.has_more());
     
    // Iterate over items
    for stock in &stocks {
        println!("{}: {} ({})", 
                 stock.ts_code, 
                 stock.name, 
                 stock.area.as_deref().unwrap_or("Unknown"));
    }
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<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,