#![cfg(feature = "crypto")]
use finance_query::crypto::CoinQuote;
#[allow(dead_code)]
fn _verify_coin_quote_fields(c: CoinQuote) {
let _: String = c.id;
let _: String = c.symbol;
let _: String = c.name;
let _: Option<f64> = c.current_price;
let _: Option<f64> = c.market_cap;
let _: Option<u32> = c.market_cap_rank;
let _: Option<f64> = c.price_change_percentage_24h;
let _: Option<f64> = c.total_volume;
let _: Option<f64> = c.circulating_supply;
let _: Option<String> = c.image;
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_crypto_top_coins() {
use finance_query::crypto;
let top = crypto::coins("usd", 10).await.unwrap();
assert!(!top.is_empty(), "should return coins");
assert!(top.len() <= 10);
for coin in &top {
let price = coin.current_price.unwrap_or(0.0);
let change = coin.price_change_percentage_24h.unwrap_or(0.0);
let rank = coin.market_cap_rank.unwrap_or(0);
println!(
"#{} {} ({}): ${:.2} ({:+.2}%)",
rank, coin.name, coin.symbol, price, change
);
}
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_crypto_single_coin_bitcoin() {
use finance_query::crypto;
let btc = crypto::coin("bitcoin", "usd").await.unwrap();
assert_eq!(btc.id, "bitcoin");
assert_eq!(btc.symbol.to_uppercase(), "BTC");
let price = btc.current_price.unwrap_or(0.0);
assert!(price > 0.0, "BTC price should be positive");
println!("Bitcoin: ${:.2}", price);
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_crypto_single_coin_ethereum() {
use finance_query::crypto;
let eth = crypto::coin("ethereum", "usd").await.unwrap();
let mktcap = eth.market_cap.unwrap_or(0.0);
println!("Ethereum market cap: ${:.2}B", mktcap / 1e9);
assert!(mktcap > 0.0);
}
#[allow(dead_code)]
fn _verify_coin_quote_fields_doc(c: CoinQuote) {
let _: String = c.id;
let _: String = c.symbol;
let _: String = c.name;
let _: Option<f64> = c.current_price;
let _: Option<f64> = c.market_cap;
let _: Option<u32> = c.market_cap_rank;
let _: Option<f64> = c.price_change_percentage_24h;
let _: Option<f64> = c.total_volume;
let _: Option<f64> = c.circulating_supply;
let _: Option<String> = c.image;
}
#[allow(dead_code)]
fn _verify_crypto_quote_price(q: finance_query::CryptoQuote) {
let _: Option<f64> = q.price;
}
#[allow(dead_code)]
#[cfg(all(feature = "indicators", feature = "risk"))]
async fn _verify_crypto_coin_indicators_and_risk() -> finance_query::Result<()> {
use finance_query::indicators::Indicator;
use finance_query::{Capability, Interval, Provider, Providers, TimeRange};
let providers = Providers::builder()
.route(Capability::CRYPTO, [Provider::CoinGecko])
.build()
.await?;
let btc = providers.crypto("BTC");
let summary = btc
.indicators("usd", Interval::OneDay, TimeRange::ThreeMonths)
.await?;
let _: Option<f64> = summary.rsi_14;
let _rsi_21 = btc
.indicator(
Indicator::Rsi(21),
"usd",
Interval::OneDay,
TimeRange::ThreeMonths,
)
.await?;
let risk = btc
.risk("usd", Interval::OneDay, TimeRange::OneYear)
.await?;
let _: f64 = risk.var_95;
let _: f64 = risk.max_drawdown;
Ok(())
}
#[tokio::test]
#[ignore = "requires network access"]
async fn test_crypto_coin_handle() {
use finance_query::{Capability, Interval, Provider, Providers, TimeRange};
let providers = Providers::builder()
.route(Capability::CRYPTO, [Provider::CoinGecko])
.build()
.await
.unwrap();
let btc = providers.crypto("bitcoin");
let quote = btc.quote("usd").await.unwrap();
assert!(quote.price.unwrap_or(0.0) > 0.0);
let btc_chart = providers.crypto("BTC");
let chart = btc_chart
.chart("usd", Interval::OneDay, TimeRange::OneMonth)
.await
.unwrap();
assert!(!chart.candles.is_empty());
let history = btc_chart.history("usd", TimeRange::OneMonth).await.unwrap();
assert!(!history.candles.is_empty());
}