Crypto¶
Cargo Docs
Feature flag required
The CoinGecko functions (crypto::coins, crypto::coin) require the crypto feature:
CryptoCoin handle (providers.crypto(id)) is also gated on the crypto feature when
using the CoinGecko provider, but the handle type itself is available with other provider
features (alphavantage, fmp, polygon).
Top Coins¶
Fetch the top N coins by market cap, priced in a given vs-currency:
use finance_query::crypto;
let top = crypto::coins("usd", 10).await?;
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
);
}
Single Coin¶
Fetch a single coin's quote by its CoinGecko ID:
use finance_query::crypto;
let btc = crypto::coin("bitcoin", "usd").await?;
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);
CoinQuote Fields¶
CoinQuote is returned by both crypto::coins and crypto::coin.
| Field | Type | Description |
|---|---|---|
id |
String |
CoinGecko coin ID (e.g., "bitcoin") |
symbol |
String |
Ticker symbol in uppercase (e.g., "BTC") |
name |
String |
Full coin name (e.g., "Bitcoin") |
current_price |
Option<f64> |
Current price in the requested currency |
market_cap |
Option<f64> |
Market capitalisation |
market_cap_rank |
Option<u32> |
Market cap rank (1 = highest) |
price_change_percentage_24h |
Option<f64> |
24-hour price change percentage |
total_volume |
Option<f64> |
24-hour trading volume |
circulating_supply |
Option<f64> |
Circulating supply |
image |
Option<String> |
URL to the coin's logo image |
use finance_query::crypto::CoinQuote;
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;
}
Coin Handle¶
The CryptoCoin handle provides a domain-oriented interface for quote, chart, and history
queries backed by your configured providers. Construct it via Providers::crypto.
quote is keyed by the CoinGecko coin id (e.g. "bitcoin") and is keyless via CoinGecko:
use finance_query::{Capability, Provider, Providers};
# async fn run() -> Result<(), Box<dyn std::error::Error>> {
let providers = Providers::builder()
.route(Capability::CRYPTO, [Provider::CoinGecko])
.build()
.await?;
let btc = providers.crypto("bitcoin");
let quote = btc.quote("usd").await?;
# Ok(()) }
Chart vs. quote identifiers
chart/history route through Capability::CHART, not CRYPTO. On the default
Yahoo route the handle id must be the coin's ticker (e.g. "BTC", which Yahoo
resolves as "BTC-USD") — not the CoinGecko id. To use the CoinGecko id for charts
too, route Capability::CHART to a crypto-aware provider (Polygon, FMP, or Alpha Vantage).
use finance_query::{Capability, Provider, Providers};
use finance_query::{Interval, TimeRange};
# async fn run() -> Result<(), Box<dyn std::error::Error>> {
let providers = Providers::builder()
.route(Capability::CRYPTO, [Provider::CoinGecko])
.build()
.await?;
// Ticker id ("BTC") so the default Yahoo CHART route resolves "BTC-USD".
let btc = providers.crypto("BTC");
let chart = btc.chart("usd", Interval::OneDay, TimeRange::OneMonth).await?;
let history = btc.history("usd", TimeRange::OneMonth).await?;
# Ok(()) }
quote returns a CryptoQuote
where the price field is price (not current_price):
use finance_query::CryptoQuote;
fn verify_crypto_quote_price(q: CryptoQuote) {
let _: Option<f64> = q.price;
}
Indicators & Risk¶
indicators/indicator (requires the indicators feature) and risk
(requires the risk feature) compute from the same vs_currency-priced
chart data as chart/history above — annualised with a 24/7 (365-day)
calendar, since crypto trades every day of the year:
use finance_query::{Capability, Provider, Providers};
use finance_query::{Interval, TimeRange};
use finance_query::indicators::Indicator;
# async fn run() -> Result<(), Box<dyn std::error::Error>> {
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?;
if let Some(rsi) = summary.rsi_14 {
println!("RSI(14): {:.2}", rsi);
}
let rsi_21 = btc
.indicator(Indicator::Rsi(21), "usd", Interval::OneDay, TimeRange::ThreeMonths)
.await?;
let risk = btc.risk("usd", Interval::OneDay, TimeRange::OneYear).await?;
println!("VaR 95%: {:.2}%", risk.var_95 * 100.0);
println!("Max Drawdown: {:.2}%", risk.max_drawdown * 100.0);
# Ok(()) }
risk takes no benchmark parameter — beta is always None, since crypto
has no natural benchmark to compare against.