pub struct KLINE {
pub ticker: String,
pub timestamp: Vec<i64>,
pub open: Option<Vec<f64>>,
pub high: Option<Vec<f64>>,
pub low: Option<Vec<f64>>,
pub close: Vec<f64>,
pub volume: Option<Vec<f64>>,
pub adjclose: Option<Vec<f64>>,
}Expand description
KLINE Struct
§Description
- Represents historical price/volume data for a financial instrument
- Stores OHLCV (Open, High, Low, Close, Volume) data with UNIX timestamps
- Supports both adjusted and unadjusted closing prices
- Designed for efficient time series analysis and portfolio construction
- Flexible data ingestion from multiple sources
§Fields
ticker: Instrument symbol (e.g., “AAPL”, “BTC-USD”)timestamp: UNIX timestamps (seconds since epoch) for each data pointopen: Opening prices (optional)high: Daily high prices (optional)low: Daily low prices (optional)close: Closing prices (required)volume: Trading volumes (optional)adjclose: Adjusted closing prices (optional)
§Features
- Multi-format Support: Load data from CSV, JSON, and Polars DataFrames
- Flexible Integration: Works seamlessly with
TickersandPortfoliostructs - Performance Analysis: Enables risk/return calculations and reporting
§Example: Loading Data and Generating Reports
use std::error::Error;
use finalytics::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Method 1: Load from CSV files
let aapl_csv = KLINE::from_csv("AAPL", "../examples/datasets/aapl.csv")?;
let goog_csv = KLINE::from_csv("GOOG", "../examples/datasets/goog.csv")?;
let gspc_csv = KLINE::from_csv("^GSPC", "../examples/datasets/gspc.csv")?;
// Method 2: Load from JSON files
let msft_json = KLINE::from_json("MSFT", "../examples/datasets/msft.json")?;
let btc_json = KLINE::from_json("BTC-USD", "../examples/datasets/btcusd.json")?;
// Method 3: Load from Polars DataFrame
let df = KLINE::from_csv("NVDA","../examples/datasets/nvda.csv")?.to_dataframe()?;
let nvda_df = KLINE::from_dataframe("NVDA", &df)?;
// Combine all data sources
let tickers_data = vec![aapl_csv, goog_csv, msft_json, btc_json, nvda_df];
// Initialize Tickers Struct
let tickers = Tickers::builder()
.tickers_data(Some(tickers_data))
.benchmark_data(Some(gspc_csv))
.confidence_level(0.95)
.risk_free_rate(0.02)
.build();
// Generate a Single Ticker Report
let ticker = tickers.clone().get_ticker("AAPL").await?;
ticker.report(Some(ReportType::Performance)).await?.show()?;
// Generate a Multiple Ticker Report
tickers.report(Some(ReportType::Performance)).await?.show()?;
// Portfolio optimization (in-sample performance stats computed automatically)
let mut portfolio = tickers.optimize(Some(ObjectiveFunction::MaxSharpe), None).await?;
portfolio.report(Some(ReportType::Optimization)).await?.show()?;
// Optionally: update with new KLINE data for out-of-sample evaluation
let eval_tickers = vec![
KLINE::from_csv("AAPL", "../examples/datasets/aapl.csv")?,
KLINE::from_csv("GOOG", "../examples/datasets/goog.csv")?,
KLINE::from_csv("MSFT", "../examples/datasets/msft.csv")?,
KLINE::from_csv("BTC-USD", "../examples/datasets/btcusd.csv")?,
KLINE::from_csv("NVDA", "../examples/datasets/nvda.csv")?,
];
let eval_bench = KLINE::from_csv("^GSPC", "../examples/datasets/gspc.csv")?;
portfolio.update_data(eval_tickers, Some(eval_bench)).await?;
portfolio.performance_stats()?;
portfolio.report(Some(ReportType::Performance)).await?.show()?;
Ok(())
}§Supported Data Sources
-
CSV Files:
timestamp,open,high,low,close,volume,adjclose 1672704000,130.28,130.90,124.17,125.07,112117500,124.82 1672790400,126.89,128.66,125.08,126.36,89113600,126.11 -
JSON Files:
{ "timestamp": [1672704000, 1672790400], "open": [130.28, 126.89], "high": [130.90, 128.66], "low": [124.17, 125.08], "close": [125.07, 126.36], "volume": [112117500, 89113600], "adjclose": [124.82, 126.11] } -
Polars DataFrames:
use polars::prelude::*; let df = df!( "timestamp" => &[1672704000, 1672790400], "open" => &[130.28, 126.89], "high" => &[130.90, 128.66], "low" => &[124.17, 125.08], "close" => &[125.07, 126.36], "volume" => &[112117500.0, 89113600.0], "adjclose" => &[124.82, 126.11] );
§Important Notes
- All sources must include
timestampandclosecolumns - Column names are case-sensitive and must match exactly
- Timestamps should be UNIX format (seconds since epoch)
- Missing columns will be initialized as
None
Fields§
§ticker: String§timestamp: Vec<i64>§open: Option<Vec<f64>>§high: Option<Vec<f64>>§low: Option<Vec<f64>>§close: Vec<f64>§volume: Option<Vec<f64>>§adjclose: Option<Vec<f64>>Implementations§
Source§impl KLINE
impl KLINE
pub fn interval_days(&self) -> IntervalDays
pub fn start_date(&self) -> String
pub fn end_date(&self) -> String
pub fn to_dataframe(&self) -> Result<DataFrame, Box<dyn Error>>
pub fn from_dataframe( ticker: &str, df: &DataFrame, ) -> Result<KLINE, Box<dyn Error>>
Sourcepub fn from_csv(ticker: &str, path: &str) -> Result<Self, Box<dyn Error>>
pub fn from_csv(ticker: &str, path: &str) -> Result<Self, Box<dyn Error>>
Examples found in repository?
examples/example.rs (line 273)
269async fn custom_data() -> Result<(), Box<dyn Error>> {
270 println!("=== 7. Custom Data (KLINE) ===");
271
272 // Load data from CSV files
273 let aapl = KLINE::from_csv("AAPL", "examples/datasets/aapl.csv")?;
274 let msft = KLINE::from_csv("MSFT", "examples/datasets/msft.csv")?;
275 let nvda = KLINE::from_csv("NVDA", "examples/datasets/nvda.csv")?;
276 let goog = KLINE::from_csv("GOOG", "examples/datasets/goog.csv")?;
277 let btcusd = KLINE::from_csv("BTC-USD", "examples/datasets/btcusd.csv")?;
278 let gspc = KLINE::from_csv("^GSPC", "examples/datasets/gspc.csv")?;
279
280 // Single Ticker from custom data
281 println!("--- Custom Ticker ---");
282 let custom_ticker = Ticker::builder()
283 .ticker("AAPL")
284 .benchmark_symbol("^GSPC")
285 .confidence_level(0.95)
286 .risk_free_rate(0.02)
287 .ticker_data(Some(aapl.clone()))
288 .benchmark_data(Some(gspc.clone()))
289 .build();
290
291 custom_ticker
292 .report(Some(ReportType::Performance))
293 .await?
294 .show()?;
295
296 // Multiple Tickers from custom data
297 println!("--- Custom Tickers ---");
298 let custom_tickers = Tickers::builder()
299 .tickers(vec!["NVDA", "GOOG", "AAPL", "MSFT", "BTC-USD"])
300 .benchmark_symbol("^GSPC")
301 .confidence_level(0.95)
302 .risk_free_rate(0.02)
303 .tickers_data(Some(vec![
304 nvda.clone(),
305 goog.clone(),
306 aapl.clone(),
307 msft.clone(),
308 btcusd.clone(),
309 ]))
310 .benchmark_data(Some(gspc.clone()))
311 .build();
312
313 custom_tickers
314 .report(Some(ReportType::Performance))
315 .await?
316 .show()?;
317
318 // Portfolio optimization from custom data
319 println!("--- Custom Portfolio ---");
320 let mut custom_portfolio = Portfolio::builder()
321 .ticker_symbols(vec!["NVDA", "GOOG", "AAPL", "MSFT", "BTC-USD"])
322 .benchmark_symbol("^GSPC")
323 .confidence_level(0.95)
324 .risk_free_rate(0.02)
325 .objective_function(ObjectiveFunction::MaxSharpe)
326 .tickers_data(Some(vec![nvda, goog, aapl, msft, btcusd]))
327 .benchmark_data(Some(gspc))
328 .build()
329 .await?;
330
331 custom_portfolio.optimize()?;
332 custom_portfolio
333 .report(Some(ReportType::Optimization))
334 .await?
335 .show()?;
336
337 Ok(())
338}pub fn from_json(ticker: &str, path: &str) -> Result<Self, Box<dyn Error>>
Trait Implementations§
Auto Trait Implementations§
impl Freeze for KLINE
impl RefUnwindSafe for KLINE
impl Send for KLINE
impl Sync for KLINE
impl Unpin for KLINE
impl UnsafeUnpin for KLINE
impl UnwindSafe for KLINE
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Key for Twhere
T: Clone,
impl<T> Key for Twhere
T: Clone,
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
The inverse inclusion map: attempts to construct
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
Checks if
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
Use with care! Same as
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
The inclusion map: converts
self to the equivalent element of its superset.