1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//! `coinbasis` — comprehensive crypto tax-lot cost-basis accounting.
//!
//! Hand it a ledger of [`Transaction`]s and current prices; it returns realized
//! capital gains (with holding-period classification), ordinary income,
//! unrealized P/L, portfolio valuation, and tax-year reports. The crate performs
//! **no network access and no file I/O** — callers supply all data.
//!
//! # Example
//! ```
//! use coinbasis::{CostBasisMethod, Portfolio, Transaction};
//! use chrono::{TimeZone, Utc};
//! use rust_decimal::Decimal;
//!
//! let txs = vec![
//! Transaction::Buy { timestamp: Utc.with_ymd_and_hms(2020,1,1,0,0,0).unwrap(),
//! wallet: "hot".into(), asset: "btc".into(),
//! quantity: Decimal::new(1, 0), unit_price: Decimal::new(100, 0), fee: Decimal::new(0, 0) },
//! Transaction::Sell { timestamp: Utc.with_ymd_and_hms(2022,1,1,0,0,0).unwrap(),
//! wallet: "hot".into(), asset: "btc".into(),
//! quantity: Decimal::new(1, 0), unit_price: Decimal::new(500, 0), fee: Decimal::new(0, 0) },
//! ];
//! let portfolio = Portfolio::from_transactions(&txs).unwrap();
//! let gains = portfolio.realized_gains(CostBasisMethod::Fifo).unwrap();
//! assert_eq!(gains[0].gain, Decimal::new(400, 0));
//! ```
//!
//! # Concepts
//!
//! - **Ledger in, reports out.** You build a [`Portfolio`] from a `Vec` of
//! [`Transaction`]s (in the order they occurred) and query it. The crate
//! replays the ledger internally; it stores no mutable state and performs no
//! I/O.
//! - **Cost-basis methods.** Disposals are matched to open lots by
//! [`CostBasisMethod`]: `Fifo`, `Lifo`, `Hifo`, `Average`, or `SpecificId`
//! (where you name the lots via a [`LotSelection`]). The same ledger yields
//! different realized gains under different methods.
//! - **Per-wallet lots.** Lots are pooled per `(asset, wallet)`. A disposal can
//! only draw from the wallet it names; transfers move lots between wallets
//! while preserving basis and the holding-period clock.
//! - **Holding period.** Each realized lot is classified [`Term::Short`] or
//! [`Term::Long`] at a 365-day boundary.
//! - **Gifts use the IRS dual-basis rule.** A received gift inherits the donor's
//! basis for gains, the lesser of (donor basis, FMV at receipt) for losses,
//! and realizes nothing in between.
//!
//! # Examples
//!
//! Runnable examples live in the `examples/` directory — start with
//! `cargo run --example quickstart`, then `cost_basis_methods`,
//! `wallet_transfers`, `gifts`, `tax_reports`, `valuation`, and
//! `portfolio_stats`.
//!
//! # Not tax advice
//! `coinbasis` is a calculation library. It does not file taxes, give legal
//! advice, or guarantee conformance with any jurisdiction's rules. The default
//! model follows current US federal treatment (see the crate docs). Provided
//! "as is", without warranty of any kind.
// Re-exports are added back in the tasks that define each item:
pub use PortfolioError;
pub use ;
pub use Portfolio;
pub use ;
pub use ;
pub use ;