Skip to main content

alpaca_sdk/
lib.rs

1//! Targets the Alpaca API itself, documented at [docs.alpaca.markets]. Where these
2//! docs describe what an endpoint does, they describe the API; where they describe
3//! how this crate represents it, that is a choice made here.
4//!
5//! Each API surface is its own feature-gated module — `trading`, `data` and
6//! `broker`. The `blocking` feature adds `blocking::Blocking`, a synchronous
7//! façade over any of them; `polars` adds `data::ToFrame`, and implies `data`.
8//!
9//! The README is the rest of this page: what the crate is, the feature table,
10//! the quick-start examples, how the types behave, how the routes are verified,
11//! and the minimum supported Rust version.
12//!
13//! [docs.alpaca.markets]: https://docs.alpaca.markets/us/reference/
14
15#![cfg_attr(docsrs, feature(doc_cfg))]
16// The README is included so that its five examples compile as doctests. They
17// are the crate's front door and nothing was checking them, so five batches of
18// breaking changes went past without anything noticing whether they still
19// built. They did — but only because nobody had needed to find out.
20#![doc = include_str!("../README.md")]
21
22// `reqwest` is depended on with `default-features = false`, and none of
23// `trading`, `data` or `broker` implies a TLS backend — only the two features
24// below reach `reqwest/rustls` and `reqwest/native-tls`. So
25// `default-features = false, features = ["broker"]` used to compile cleanly and
26// then fail *every* HTTPS request at runtime, because the client in
27// `rest::Rest` was built with no backend to negotiate with. Failing the build
28// is the only place that mistake is cheap to find.
29#[cfg(not(any(feature = "rustls-tls", feature = "native-tls")))]
30compile_error!(
31    "alpaca-sdk requires a TLS backend: enable exactly one of the `rustls-tls` \
32     or `native-tls` features. Disabling default features turns off \
33     `rustls-tls`, and none of `trading`, `data` or `broker` enables a backend \
34     on its own, so every HTTPS request would fail at runtime."
35);
36
37pub mod auth;
38pub mod backoff;
39#[cfg(feature = "blocking")]
40#[cfg_attr(docsrs, doc(cfg(feature = "blocking")))]
41pub mod blocking;
42pub mod config;
43pub mod error;
44pub mod rest;
45pub mod types;
46
47#[cfg(feature = "_sse")]
48mod sse;
49
50#[cfg(feature = "broker")]
51#[cfg_attr(docsrs, doc(cfg(feature = "broker")))]
52pub mod broker;
53#[cfg(feature = "data")]
54#[cfg_attr(docsrs, doc(cfg(feature = "data")))]
55pub mod data;
56#[cfg(feature = "trading")]
57#[cfg_attr(docsrs, doc(cfg(feature = "trading")))]
58pub mod trading;
59
60/// The `polars` this crate was built against.
61///
62/// Re-exported because [`ToFrame`](crate::data::ToFrame) hands back a
63/// `polars::prelude::DataFrame`, and a caller who depends on a different polars
64/// version gets two incompatible `DataFrame` types with the same name. Reach for
65/// this one, or match the version in `Cargo.toml`.
66///
67/// Because the version is part of this crate's public API, **a major or minor
68/// bump of `polars` is treated as a breaking change of `alpaca-sdk`** and gets
69/// one here too. `polars` is pre-1.0 and moves quickly, where a minor bump is
70/// the breaking one — so in practice its release cadence, not this crate's,
71/// drives how often `alpaca-sdk`'s own version has to break.
72#[cfg(feature = "polars")]
73#[cfg_attr(docsrs, doc(cfg(feature = "polars")))]
74pub use polars;
75
76/// The `rust_decimal` this crate was built against.
77///
78/// Re-exported for the same reason as the `polars` re-export: every price, quantity and
79/// balance in this crate is a `rust_decimal::Decimal`, and a caller who depends
80/// on a different `rust_decimal` version gets two incompatible `Decimal` types
81/// with the same name and an error that does not explain itself. Reach for this
82/// one, or match the version in `Cargo.toml`.
83///
84/// Because the version is part of this crate's public API, **a major or minor
85/// bump of `rust_decimal` is treated as a breaking change of `alpaca-sdk`** and
86/// gets one here too.
87///
88/// It is also the way to the rest of that crate without declaring the
89/// dependency twice — `RoundingStrategy` for the rounding modes, and the
90/// conversions:
91///
92/// ```
93/// use alpaca_sdk::Decimal;
94///
95/// let limit: Decimal = "185.50".parse().unwrap();
96/// assert_eq!(limit.to_string(), "185.50");
97/// ```
98///
99/// The `dec!` literal macro is **not** reachable through this re-export: it sits
100/// behind `rust_decimal`'s `macros` feature, which is off here because it costs
101/// a proc-macro dependency the crate itself does not use. A caller who wants it
102/// depends on `rust_decimal` with that feature directly, and cargo unifies the
103/// two — the same arrangement `polars` and its `lazy` feature already have.
104pub use rust_decimal;
105
106/// The numeric type for every price, quantity and balance this crate exchanges.
107///
108/// Alpaca sends these as strings; reading one as an `f64` loses precision on the
109/// one class of field where it is least acceptable. Market data floats that
110/// arrive as JSON numbers stay `f64` and are not this type.
111pub use rust_decimal::Decimal;
112
113pub use auth::Credentials;
114pub use config::{BaseUrl, RetryBackoff, RetryConfig};
115pub use error::{ApiError, Error, Result, TransportError};
116pub use rest::{Replay, RestClient, RestConfig};
117#[cfg(feature = "_sse")]
118pub use sse::{Event as SseEvent, EventStreamRequest};