Skip to content

Crypto

Feature flag required

The CoinGecko functions (crypto::coins, crypto::coin) require the crypto feature:

[dependencies]
finance-query = { version = "*", features = ["crypto"] }
The 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.