ta_lib_in_rust/
lib.rs

1//! # Technical Indicators
2//!
3//! A comprehensive Rust library for calculating financial technical indicators
4//! using the [Polars](https://pola.rs/) DataFrame library.
5//!
6//! This crate provides functions to calculate various technical indicators
7//! from OHLCV (Open, High, Low, Close, Volume) data stored in Polars DataFrames.
8//!
9//! ## Categories
10//!
11//! The indicators are organized into the following categories:
12//!
13//! - **Moving Averages**: Trend-following indicators that smooth price data
14//! - **Oscillators**: Indicators that fluctuate within a bounded range
15//! - **Volatility**: Indicators that measure the rate of price movement
16//! - **Volume**: Indicators based on trading volume
17//! - **Trend**: Indicators designed to identify market direction
18//! - **Momentum**: Indicators that measure the rate of price change
19//! - **Strategy**: Trading strategies combining multiple indicators
20//!
21//! ## Usage Examples
22//!
23//! ### Basic Indicator Calculation
24//!
25//! ```rust
26//! use polars::prelude::*;
27//! use ta_lib_in_rust::indicators::moving_averages::calculate_sma;
28//!
29//! fn main() -> PolarsResult<()> {
30//!     let close_prices = Series::new(
31//!         "close".into(),
32//!         &[
33//!             100.0, 101.0, 102.0, 103.0, 105.0, 104.0, 106.0, 107.0, 109.0, 108.0,
34//!             107.0, 109.0, 111.0, 114.0, 113.0, 116.0, 119.0, 120.0, 119.0, 117.0,
35//!             118.0, 120.0, 123.0, 122.0, 120.0, 118.0, 119.0, 121.0, 124.0, 125.0,
36//!         ],
37//!     );
38//!     // Create a sample DataFrame with price data
39//!     let mut df = DataFrame::new(vec![close_prices.clone().into()])?;
40//!
41//!     // Calculate a Simple Moving Average
42//!     let sma_10 = calculate_sma(&df, "close", 10)?;
43//!     df.with_column(sma_10)?;
44//!
45//!     println!("{}", df);
46//!     Ok(())
47//! }
48//! ```
49//!
50//! ### Combining Multiple Indicators
51//!
52//! ```rust
53//! use polars::prelude::*;
54//! use ta_lib_in_rust::indicators::{
55//!     moving_averages::{calculate_sma, calculate_ema},
56//!     oscillators::calculate_rsi,
57//!     volatility::calculate_bollinger_bands,
58//! };
59//!
60//! fn main() -> PolarsResult<()> {
61//!     // Create a DataFrame with price data
62//!     let close = Series::new("close", &[100.0, 102.0, 104.0, 103.0, 105.0, 107.0, 108.0,
63//!                                        107.0, 106.0, 105.0, 107.0, 108.0, 109.0, 110.0]);
64//!     let high = Series::new("high", &[101.0, 103.0, 104.5, 103.5, 106.0, 107.5, 108.5,
65//!                                      107.2, 106.5, 105.5, 107.5, 108.5, 109.5, 111.0]);
66//!     let low = Series::new("low", &[99.0, 101.5, 103.0, 102.0, 104.0, 106.0, 107.0,
67//!                                    106.0, 105.0, 104.0, 106.0, 107.5, 108.5, 109.0]);
68//!     let mut df = DataFrame::new(vec![close.clone(), high.clone(), low.clone()])?;
69//!     
70//!     // Calculate multiple indicators
71//!     let sma_5 = calculate_sma(&df, "close", 5)?;
72//!     let ema_8 = calculate_ema(&df, "close", 8)?;
73//!     let rsi_7 = calculate_rsi(&df, 7, "close")?;
74//!     let (bb_middle, bb_upper, bb_lower) = calculate_bollinger_bands(&df, 10, 2.0, "close")?;
75//!     
76//!     // Add all indicators to the DataFrame
77//!     df = df.with_columns([
78//!         sma_5, ema_8, rsi_7, bb_middle, bb_upper, bb_lower
79//!     ])?;
80//!     
81//!     // Create custom trading signals
82//!     let bullish_signal = df.clone()
83//!         .lazy()
84//!         .with_columns([
85//!             (col("close").gt(col("sma_5"))
86//!              & col("close").gt(col("bb_middle"))
87//!              & col("rsi_7").gt(lit(50.0)))
88//!             .alias("bullish")
89//!         ])
90//!         .collect()?;
91//!     
92//!     println!("DataFrame with indicators and signals:");
93//!     println!("{}", bullish_signal);
94//!     
95//!     Ok(())
96//! }
97//! ```
98//!
99//! ### Running a Trading Strategy Backtest
100//!
101//! ```rust
102//! use polars::prelude::*;
103//! use ta_lib_in_rust::strategy::daily::multi_indicator_daily_1::{
104//!     run_strategy, calculate_performance, StrategyParams
105//! };
106//!
107//! fn main() -> PolarsResult<()> {
108//!     // Load data from CSV
109//!     let df = CsvReadOptions::default()
110//!         .with_has_header(true)
111//!         .try_into_reader_with_file_path(Some("path/to/ohlcv_data.csv".into()))?
112//!         .finish()?;
113//!
114//!     // Set strategy parameters
115//!     let params = StrategyParams {
116//!         sma_short_period: 20,
117//!         sma_long_period: 50,
118//!         rsi_period: 14,
119//!         rsi_overbought: 70.0,
120//!         rsi_oversold: 30.0,
121//!         bb_period: 20,
122//!         bb_std_dev: 2.0,
123//!         macd_fast: 12,
124//!         macd_slow: 26,
125//!         macd_signal: 9,
126//!         min_signals_for_buy: 3,
127//!         min_signals_for_sell: 3,
128//!     };
129//!
130//!     // Run the strategy to generate buy and sell signals
131//!     let signals = run_strategy(&df, &params)?;
132//!
133//!     // Calculate performance metrics
134//!     let close_series = df.column("close")?;
135//!     let (
136//!         final_value,     // Final portfolio value
137//!         total_return,    // Total return percentage
138//!         num_trades,      // Number of trades executed
139//!         win_rate,        // Percentage of winning trades
140//!         max_drawdown,    // Maximum drawdown percentage
141//!         profit_factor,   // Ratio of gross profit to gross loss
142//!     ) = calculate_performance(
143//!         close_series,
144//!         &signals.buy_signals,
145//!         &signals.sell_signals,
146//!         10000.0,  // Initial capital
147//!     );
148//!
149//!     println!("Strategy Backtest Results:");
150//!     println!("Final Portfolio Value: ${:.2}", final_value);
151//!     println!("Total Return: {:.2}%", total_return);
152//!     println!("Number of Trades: {}", num_trades);
153//!     println!("Win Rate: {:.2}%", win_rate);
154//!     println!("Maximum Drawdown: {:.2}%", max_drawdown * 100.0);
155//!     println!("Profit Factor: {:.2}", profit_factor);
156//!
157//!     Ok(())
158//! }
159//! ```
160//!
161//! ### Comparing Multiple Strategies
162//!
163//! ```rust
164//! use polars::prelude::*;
165//! use ta_lib_in_rust::strategy::minute::{
166//!     multi_indicator_minute_1,
167//!     multi_indicator_minute_2,
168//!     multi_indicator_minute_3
169//! };
170//!
171//! fn main() -> PolarsResult<()> {
172//!     // Load minute data from CSV
173//!     let mut df = CsvReadOptions::default()
174//!         .with_has_header(true)
175//!         .try_into_reader_with_file_path(Some("path/to/minute_data.csv".into()))?
176//!         .finish()?;
177//!
178//!     // Cast volume to float if needed
179//!     df = df.lazy()
180//!         .with_columns([
181//!             col("volume").cast(DataType::Float64),
182//!         ])
183//!         .collect()?;
184//!
185//!     // Initialize strategies with default parameters
186//!     let params1 = multi_indicator_minute_1::StrategyParams::default();
187//!     let params2 = multi_indicator_minute_2::StrategyParams::default();
188//!     let params3 = multi_indicator_minute_3::StrategyParams::default();
189//!
190//!     // Run strategies
191//!     let signals1 = multi_indicator_minute_1::run_strategy(&df, &params1)?;
192//!     let signals2 = multi_indicator_minute_2::run_strategy(&df, &params2)?;
193//!     let signals3 = multi_indicator_minute_3::run_strategy(&df, &params3)?;
194//!
195//!     // Calculate performance for each strategy
196//!     let close_prices = df.column("close")?;
197//!
198//!     let (final_value1, return1, trades1, win_rate1, drawdown1, _, _) =
199//!         multi_indicator_minute_1::calculate_performance(
200//!             close_prices,
201//!             &signals1.buy_signals,
202//!             &signals1.sell_signals,
203//!             10000.0,
204//!             true
205//!         );
206//!
207//!     let (final_value2, return2, trades2, win_rate2, drawdown2, _, _) =
208//!         multi_indicator_minute_2::calculate_performance(
209//!             close_prices,
210//!             &signals2.buy_signals,
211//!             &signals2.sell_signals,
212//!             &signals2.position_sizes,
213//!             10000.0,
214//!             true,
215//!             None
216//!         );
217//!
218//!     // Compare results
219//!     println!("Strategy Comparison:");
220//!     println!("Metric      | Strategy 1    | Strategy 2");
221//!     println!("------------------------------------");
222//!     println!("Return      | {:.2}%        | {:.2}%", return1, return2);
223//!     println!("Final Value | ${:.2}      | ${:.2}", final_value1, final_value2);
224//!     println!("Win Rate    | {:.2}%        | {:.2}%", win_rate1, win_rate2);
225//!     println!("Max Drawdown| {:.2}%        | {:.2}%", drawdown1*100.0, drawdown2*100.0);
226//!     
227//!     // Determine best performer
228//!     if return1 > return2 {
229//!         println!("\nStrategy 1 performed better on absolute return");
230//!     } else {
231//!         println!("\nStrategy 2 performed better on absolute return");
232//!     }
233//!     
234//!     // Risk-adjusted comparison
235//!     let risk_adjusted1 = return1 / (drawdown1 * 100.0);
236//!     let risk_adjusted2 = return2 / (drawdown2 * 100.0);
237//!     
238//!     if risk_adjusted1 > risk_adjusted2 {
239//!         println!("Strategy 1 performed better on risk-adjusted basis");
240//!     } else {
241//!         println!("Strategy 2 performed better on risk-adjusted basis");
242//!     }
243//!
244//!     Ok(())
245//! }
246//! ```
247//!
248//! See the documentation for each module for more detailed information and examples.
249
250pub mod indicators;
251pub mod strategy;
252pub mod util;
253
254// Re-export commonly used items
255pub use indicators::*;
256pub use strategy::*;
257
258// This is a placeholder function - should be removed before final release
259pub fn add(left: u64, right: u64) -> u64 {
260    left + right
261}
262
263#[cfg(test)]
264mod tests {
265    use super::*;
266
267    #[test]
268    fn it_works() {
269        let result = add(2, 2);
270        assert_eq!(result, 4);
271    }
272}