Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Tushare API - Rust Library
A comprehensive Rust client library for accessing Tushare financial data APIs. This library provides type-safe, async access to all Tushare data interfaces.
✨ Features
- 🚀 Async/Await Support: Built for high-performance async operations
- 🔒 Type Safety: Strongly typed API enums and comprehensive error handling
- 🔧 Developer Friendly: Convenient macros and builder patterns
- 📊 Third-Party Type Support: Built-in support for
rust_decimal
,chrono
,uuid
, andbigdecimal
- 🌍 Production Ready: Comprehensive error handling and security features
📋 Requirements
- Tushare API Token: Register at Tushare Pro to get your API token
📦 Installation
Add this to your Cargo.toml
:
[]
= "1.1.1"
# Optional: Enable third-party type support
# tushare-api = { version = "1.1.1", features = ["rust_decimal", "chrono"] }
# Or enable all third-party types
# tushare-api = { version = "1.1.1", features = ["all_types"] }
# Optional: Enable tracing support
# tushare-api = { version = "1.1.1", features = ["tracing"] }
🚀 Quick Start
use ;
async
📖 API Usage Guide
1. How to Import Tushare API
// Basic imports
use ;
// For convenient macros
use ;
// For logging configuration
use ;
// For HTTP client configuration and connection pool settings
use ;
// For custom timeouts
use Duration;
2. How to Create Tushare Client
The library provides multiple ways to create a client:
Method 1: Using Environment Variable (Recommended)
// Set environment variable first
set_var;
// Create client with default settings
let client = from_env?;
// Create client with custom timeouts
let client = from_env_with_timeout?;
Method 2: Direct Token
// Create client with default settings
let client = new;
// Create client with custom timeouts
let client = with_timeout;
Method 3: Using Builder Pattern
// Basic builder with timeouts and logging
let client = builder
.with_token
.with_connect_timeout
.with_timeout
.with_log_level
.log_requests
.log_responses
.log_sensitive_data
.log_performance
.build?;
// Advanced builder with connection pool settings
let client = builder
.with_token
.with_connect_timeout
.with_timeout
.with_pool_max_idle_per_host // Max 20 idle connections per host
.with_pool_idle_timeout // Keep connections for 60s
.with_log_level
.build?;
// Using HttpClientConfig for advanced HTTP settings
let http_config = new
.with_connect_timeout
.with_timeout
.with_pool_max_idle_per_host
.with_pool_idle_timeout;
let client = builder
.with_token
.with_http_config
.with_log_level
.build?;
3. How to Send Requests
Method 1: Using Convenient Macros (Recommended)
use ;
// Single API call with parameters and fields
let response = client.call_api.await?;
// API call without parameters
let response = client.call_api.await?;
// API call without fields (get all fields)
let response = client.call_api.await?;
Method 2: Using Individual Macros
use ;
// Create parameters
let params = params!;
// Create fields
let fields = fields!;
// Create request
let request = TushareRequest ;
// Send request
let response = client.call_api.await?;
Method 3: Manual Construction
use HashMap;
let mut params = new;
params.insert;
params.insert;
let fields = vec!;
let request = TushareRequest ;
let response = client.call_api.await?;
4. Automatic Struct Conversion with Procedural Macros
The library provides powerful procedural macros to automatically convert Tushare API responses into strongly-typed Rust structs, eliminating the need for manual parsing.
Using Procedural Macros
use ;
use DeriveFromTushareData;
// Define your struct with automatic conversion
async
Field Mapping and Optional Fields
use ;
use DeriveFromTushareData;
// Advanced struct with field mapping and optional fields
// Implement Default for convenience
async
Generated Struct Structure
When you use the new generic pagination container, you get a clean, type-safe interface:
// Your original struct
// Use the generic TushareEntityList<T> container:
// TushareEntityList<Stock> {
// pub items: Vec<Stock>, // Your data items
// pub has_more: bool, // Pagination: more pages available?
// pub count: i64, // Pagination: total record count
// }
When you call:
let stocks: = client.call_api_as.await?;
// OR
let stocks = client..await?;
You get a TushareEntityList<Stock>
struct with:
items
-Vec<Stock>
containing the actual converted datahas_more
-bool
indicating if there are more pages to fetchcount
-i64
showing the total number of records available
Plus these automatically generated methods:
stocks.len()
- Number of items in current pagestocks.is_empty()
- Whether current page is emptystocks.items()
- Get items as slicestocks.has_more()
- Check if more pages availablestocks.count()
- Get total record countstocks.iter()
- Iterate over items (via Deref)for stock in &stocks { ... }
- Direct iteration support
Pagination Support
The generic TushareEntityList<T>
container provides built-in pagination support with a clean, intuitive interface:
items: Vec<T>
- The actual data itemshas_more: bool
- Whether more pages are availablecount: i64
- Total number of records
use ;
async
Supported Field Types
The procedural macros support the following Rust types:
Basic Types:
String
- Required string fieldOption<String>
- Optional string fieldf64
,f32
- Required floating-point numbersOption<f64>
,Option<f32>
- Optional floating-point numbersi64
,i32
,i16
,i8
,isize
- Required signed integersOption<i64>
,Option<i32>
, etc. - Optional signed integersu64
,u32
,u16
,u8
,usize
- Required unsigned integersOption<u64>
,Option<u32>
, etc. - Optional unsigned integersbool
- Required booleanOption<bool>
- Optional booleanchar
- Required characterOption<char>
- Optional character
Third-Party Types (with feature flags):
rust_decimal::Decimal
- High-precision decimal (feature:rust_decimal
)bigdecimal::BigDecimal
- Arbitrary precision decimal (feature:bigdecimal
)chrono::NaiveDate
- Date without timezone (feature:chrono
)chrono::NaiveDateTime
- DateTime without timezone (feature:chrono
)chrono::DateTime<Utc>
- UTC DateTime (feature:chrono
)uuid::Uuid
- UUID type (feature:uuid
)- All above types with
Option<T>
for optional fields
5. Third-Party Type Support
The library provides built-in support for popular third-party types through optional feature flags. This is especially useful for financial applications that require high-precision arithmetic or date/time handling.
Enabling Third-Party Types
Add the desired features to your Cargo.toml
:
[]
# Enable specific types
= { = "1.1.1", = ["rust_decimal", "chrono"] }
# Or enable all third-party types
= { = "1.1.1", = ["all_types"] }
Example with High-Precision Decimals
use ;
async
Example with Date/Time Types
use ;
Custom Date Format Support
The library supports custom date format parsing using the #[tushare(date_format = "...")]
attribute. This is especially useful when dealing with APIs that return dates in non-standard formats.
use ;
async
Common Date Format Patterns
Format String | Example Input | Description |
---|---|---|
"%Y-%m-%d" |
"2024-03-15" |
ISO date format |
"%d/%m/%Y" |
"15/03/2024" |
European format |
"%m-%d-%Y" |
"03-15-2024" |
US format |
"%d.%m.%Y" |
"15.03.2024" |
German format |
"%Y年%m月%d日" |
"2024年03月15日" |
Chinese format |
"%Y%m%d" |
"20240315" |
Compact format |
"%Y-%m-%d %H:%M:%S" |
"2024-03-15 14:30:00" |
DateTime format |
"%Y/%m/%d %H:%M" |
"2024/03/15 14:30" |
Custom DateTime |
"%Y-%m-%d %H:%M:%S %z" |
"2024-03-15 14:30:00 +0800" |
With timezone |
Benefits of Custom Date Formats
- Precise Control: Specify exact format per field
- No Wrapper Types: Use chrono types directly
- Type Safety: Compile-time format validation
- Flexible: Works with optional fields
- Clear Syntax: Declarative and intuitive
- Error Handling: Detailed error messages for debugging
Supported Third-Party Types
Type | Feature Flag | Description | Example Values |
---|---|---|---|
rust_decimal::Decimal |
rust_decimal |
High-precision decimal | "123.456" , 123.456 |
bigdecimal::BigDecimal |
bigdecimal |
Arbitrary precision | "999999999999999999999.123" |
chrono::NaiveDate |
chrono |
Date without timezone | "20240315" , "2024-03-15" |
chrono::NaiveDateTime |
chrono |
DateTime without timezone | "2024-03-15 14:30:00" |
chrono::DateTime<Utc> |
chrono |
UTC DateTime | RFC3339 format |
uuid::Uuid |
uuid |
UUID type | "550e8400-e29b-41d4-a716-446655440000" |
For detailed documentation and examples, see Third-Party Types Guide.
Manual Conversion (Alternative Approach)
If you prefer not to use procedural macros, you can still use the manual approach:
use ;
use TushareError;
use Value;
// Manual implementation of FromTushareData
async
5. How to Configure Logging
The library supports both log
and tracing
ecosystems with flexible configuration.
Using with env_logger
(Default)
// Set log level and initialize logger
set_var;
init;
// Create client with logging configuration
let client = builder
.with_token
.with_log_level
.log_requests // Log request details
.log_responses // Don't log response content (can be large)
.log_sensitive_data // Don't log sensitive data like tokens
.log_performance // Log performance metrics
.build?;
Using with tracing
(Optional Feature)
First, enable the tracing feature in your Cargo.toml
:
[]
= { = "1.1.1", = ["tracing"] }
= "0.1"
= "0.3"
Then in your code:
use tracing_subscriber;
// Initialize tracing subscriber
set_var;
fmt
.with_env_filter
.init;
// Client configuration remains the same
let client = builder
.with_token
.with_log_level
.log_requests
.log_responses
.log_performance
.build?;
Using tracing-log
Bridge
If you want to use tracing
but the library is compiled without the tracing feature:
[]
= "1.1.1" # Without tracing feature
= "0.1"
= "0.3"
= "0.2"
use tracing_subscriber;
use LogTracer;
// Initialize log-to-tracing bridge
init?;
// Set up tracing subscriber
set_var;
fmt
.with_env_filter
.init;
Log Levels and Output
LogLevel::Off
: No loggingLogLevel::Error
: Only errorsLogLevel::Warn
: Errors and warningsLogLevel::Info
: Basic API call information (default)LogLevel::Debug
: Detailed request/response informationLogLevel::Trace
: All information including raw response content
Example log output:
INFO [abc123] Starting Tushare API call: stock_basic, params count: 2, fields count: 3
DEBUG [abc123] API request details - API: stock_basic, params: {...}, fields: [...]
DEBUG [abc123] Sending HTTP request to Tushare API
DEBUG [abc123] Received HTTP response, status code: 200
INFO [abc123] API call successful, duration: 245ms, data rows returned: 100
6. Main Data Structures
TushareClient
The main client for interacting with Tushare APIs.
TushareRequest
Represents an API request with parameters and field specifications.
TushareResponse
Represents the response from Tushare API.
TushareData
Contains the actual data returned by the API.
Api Enum
Strongly typed enumeration of all supported APIs.
Error Types
Comprehensive error handling with specific error types.
pub type TushareResult<T> = ;
Logging Configuration
🔧 Advanced Usage
Processing Response Data
let response = client.call_api.await?;
// Access field names
println!;
// Process each data row
for item in response.data.items
Custom API Usage
// For APIs not yet included in the enum
let response = client.call_api.await?;
🔍 Examples
Check out the examples/
directory for complete working examples:
# Run basic usage example
# Run tracing integration example
📋 Changelog
For a detailed history of changes, new features, and bug fixes, see CHANGELOG.md.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.