#![allow(
clippy::unnecessary_wraps,
clippy::missing_errors_doc,
clippy::doc_markdown,
clippy::unreadable_literal,
clippy::too_many_lines,
clippy::missing_panics_doc,
reason = "pedagogical examples prioritize narrative clarity over production lint style"
)]
use chrono::{DateTime, Utc};
use paft::market::quote::{GenericQuote, Quote};
use paft::market::responses::history::{
GenericCandle, GenericHistoryResponse, Ohlc, OhlcPriceBasis, PriceBasis,
};
use paft::prelude::{
AssetKind, Currency, Exchange, Instrument, IsoCurrency, MarketState, PriceAmount,
QuantityAmount, ToDataFrame, ToDataFrameVec,
};
use paft::{Decimal, Result};
use serde::{Deserialize, Serialize};
#[derive(
Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default, df_derive_macros::ToDataFrame,
)]
#[df_derive(trait = "::paft::dataframe::ToDataFrame")]
struct HftMeta {
rx_ns: u64,
seq: u64,
venue: String,
}
fn main() -> Result<()> {
println!("== 1. Standard Quote DataFrame schema (M = ()) ==");
standard_quote_schema()?;
println!("\n== 2. Quote enriched with HftMeta ==");
enriched_quote_dataframe()?;
println!("\n== 3. HistoryResponse with one HftMeta per candle ==");
history_dataframe()?;
Ok(())
}
fn standard_quote_schema() -> Result<()> {
let q = Quote {
instrument: Instrument::from_symbol_and_exchange(
"AAPL",
Exchange::NASDAQ,
AssetKind::Equity,
)?,
name: Some("Apple Inc.".to_string()),
currency: usd(),
price: Some(price(150)),
previous_close: Some(price(147)),
day_volume: Some(quantity(78_900_000)),
market_state: Some(MarketState::Regular),
as_of: None,
bid: None,
ask: None,
provider: (),
};
let df = q.to_dataframe().unwrap();
println!("columns: {:?}", df.get_column_names());
println!("rows: {}", df.height());
println!("\nDataFrame:\n{df}");
Ok(())
}
fn enriched_quote_dataframe() -> Result<()> {
let quotes: Vec<GenericQuote<HftMeta>> = vec![
GenericQuote {
instrument: Instrument::from_symbol_and_exchange(
"AAPL",
Exchange::NASDAQ,
AssetKind::Equity,
)?,
name: Some("Apple Inc.".to_string()),
currency: usd(),
price: Some(price(150)),
previous_close: Some(price(147)),
day_volume: Some(quantity(78_900_000)),
market_state: Some(MarketState::Regular),
as_of: None,
bid: None,
ask: None,
provider: HftMeta {
rx_ns: 1_700_000_000_000_000_001,
seq: 1,
venue: "NASDAQ".into(),
},
},
GenericQuote {
instrument: Instrument::from_symbol_and_exchange(
"MSFT",
Exchange::NASDAQ,
AssetKind::Equity,
)?,
name: Some("Microsoft".to_string()),
currency: usd(),
price: Some(price(420)),
previous_close: Some(price(418)),
day_volume: Some(quantity(20_000_000)),
market_state: Some(MarketState::Regular),
as_of: None,
bid: None,
ask: None,
provider: HftMeta {
rx_ns: 1_700_000_000_000_000_002,
seq: 2,
venue: "NASDAQ".into(),
},
},
];
let df = quotes.as_slice().to_dataframe().unwrap();
println!("columns: {:?}", df.get_column_names());
println!("rows: {}", df.height());
println!("\nDataFrame:\n{df}");
Ok(())
}
fn history_dataframe() -> Result<()> {
let response: GenericHistoryResponse<(), HftMeta> = GenericHistoryResponse {
candles: vec![
mk_candle(1_700_000_000, 150, 152, 149, 151, 1),
mk_candle(1_700_000_060, 151, 153, 150, 152, 2),
mk_candle(1_700_000_120, 152, 154, 151, 153, 3),
],
actions: vec![],
price_basis: OhlcPriceBasis::uniform(PriceBasis::provider_latest_adjusted()),
meta: None,
provider: (),
};
let df = response.candles.as_slice().to_dataframe().unwrap();
println!("columns: {:?}", df.get_column_names());
println!("rows: {}", df.height());
println!("\nDataFrame:\n{df}");
Ok(())
}
fn mk_candle(
ts_secs: i64,
open: i64,
high: i64,
low: i64,
close: i64,
seq: u64,
) -> GenericCandle<HftMeta> {
GenericCandle {
ts: ts(ts_secs),
currency: usd(),
ohlc: Ohlc::new(price(open), price(high), price(low), price(close)),
close_unadj: None,
volume: Some(quantity(1_000)),
provider: HftMeta {
rx_ns: 1_700_000_000_000_000_000 + seq,
seq,
venue: "AAPL".into(),
},
}
}
fn price(units: i64) -> PriceAmount {
PriceAmount::new(Decimal::from(units))
}
fn quantity(units: i64) -> QuantityAmount {
QuantityAmount::from_decimal(Decimal::from(units)).unwrap()
}
const fn usd() -> Currency {
Currency::Iso(IsoCurrency::USD)
}
const fn ts(secs: i64) -> DateTime<Utc> {
DateTime::from_timestamp(secs, 0).unwrap()
}