Expand description
§Technical Indicators
A comprehensive Rust library for calculating financial technical indicators using the Polars DataFrame library.
This crate provides functions to calculate various technical indicators from OHLCV (Open, High, Low, Close, Volume) data stored in Polars DataFrames.
§Categories
The indicators are organized into the following categories:
- Moving Averages: Trend-following indicators that smooth price data
- Oscillators: Indicators that fluctuate within a bounded range
- Volatility: Indicators that measure the rate of price movement
- Volume: Indicators based on trading volume
- Trend: Indicators designed to identify market direction
- Momentum: Indicators that measure the rate of price change
- Strategy: Trading strategies combining multiple indicators
§Usage Examples
§Basic Indicator Calculation
use polars::prelude::*;
use ta_lib_in_rust::indicators::moving_averages::calculate_sma;
fn main() -> PolarsResult<()> {
let close_prices = Series::new(
"close".into(),
&[
100.0, 101.0, 102.0, 103.0, 105.0, 104.0, 106.0, 107.0, 109.0, 108.0,
107.0, 109.0, 111.0, 114.0, 113.0, 116.0, 119.0, 120.0, 119.0, 117.0,
118.0, 120.0, 123.0, 122.0, 120.0, 118.0, 119.0, 121.0, 124.0, 125.0,
],
);
// Create a sample DataFrame with price data
let mut df = DataFrame::new(vec![close_prices.clone().into()])?;
// Calculate a Simple Moving Average
let sma_10 = calculate_sma(&df, "close", 10)?;
df.with_column(sma_10)?;
println!("{}", df);
Ok(())
}
§Combining Multiple Indicators
use polars::prelude::*;
use ta_lib_in_rust::indicators::{
moving_averages::{calculate_sma, calculate_ema},
oscillators::calculate_rsi,
volatility::calculate_bollinger_bands,
};
fn main() -> PolarsResult<()> {
// Create a DataFrame with price data
let close = Series::new("close", &[100.0, 102.0, 104.0, 103.0, 105.0, 107.0, 108.0,
107.0, 106.0, 105.0, 107.0, 108.0, 109.0, 110.0]);
let high = Series::new("high", &[101.0, 103.0, 104.5, 103.5, 106.0, 107.5, 108.5,
107.2, 106.5, 105.5, 107.5, 108.5, 109.5, 111.0]);
let low = Series::new("low", &[99.0, 101.5, 103.0, 102.0, 104.0, 106.0, 107.0,
106.0, 105.0, 104.0, 106.0, 107.5, 108.5, 109.0]);
let mut df = DataFrame::new(vec![close.clone(), high.clone(), low.clone()])?;
// Calculate multiple indicators
let sma_5 = calculate_sma(&df, "close", 5)?;
let ema_8 = calculate_ema(&df, "close", 8)?;
let rsi_7 = calculate_rsi(&df, 7, "close")?;
let (bb_middle, bb_upper, bb_lower) = calculate_bollinger_bands(&df, 10, 2.0, "close")?;
// Add all indicators to the DataFrame
df = df.with_columns([
sma_5, ema_8, rsi_7, bb_middle, bb_upper, bb_lower
])?;
// Create custom trading signals
let bullish_signal = df.clone()
.lazy()
.with_columns([
(col("close").gt(col("sma_5"))
& col("close").gt(col("bb_middle"))
& col("rsi_7").gt(lit(50.0)))
.alias("bullish")
])
.collect()?;
println!("DataFrame with indicators and signals:");
println!("{}", bullish_signal);
Ok(())
}
§Running a Trading Strategy Backtest
use polars::prelude::*;
use ta_lib_in_rust::strategy::daily::multi_indicator_daily_1::{
run_strategy, calculate_performance, StrategyParams
};
fn main() -> PolarsResult<()> {
// Load data from CSV
let df = CsvReadOptions::default()
.with_has_header(true)
.try_into_reader_with_file_path(Some("path/to/ohlcv_data.csv".into()))?
.finish()?;
// Set strategy parameters
let params = StrategyParams {
sma_short_period: 20,
sma_long_period: 50,
rsi_period: 14,
rsi_overbought: 70.0,
rsi_oversold: 30.0,
bb_period: 20,
bb_std_dev: 2.0,
macd_fast: 12,
macd_slow: 26,
macd_signal: 9,
min_signals_for_buy: 3,
min_signals_for_sell: 3,
};
// Run the strategy to generate buy and sell signals
let signals = run_strategy(&df, ¶ms)?;
// Calculate performance metrics
let close_series = df.column("close")?;
let (
final_value, // Final portfolio value
total_return, // Total return percentage
num_trades, // Number of trades executed
win_rate, // Percentage of winning trades
max_drawdown, // Maximum drawdown percentage
profit_factor, // Ratio of gross profit to gross loss
) = calculate_performance(
close_series,
&signals.buy_signals,
&signals.sell_signals,
10000.0, // Initial capital
);
println!("Strategy Backtest Results:");
println!("Final Portfolio Value: ${:.2}", final_value);
println!("Total Return: {:.2}%", total_return);
println!("Number of Trades: {}", num_trades);
println!("Win Rate: {:.2}%", win_rate);
println!("Maximum Drawdown: {:.2}%", max_drawdown * 100.0);
println!("Profit Factor: {:.2}", profit_factor);
Ok(())
}
§Comparing Multiple Strategies
use polars::prelude::*;
use ta_lib_in_rust::strategy::minute::{
multi_indicator_minute_1,
multi_indicator_minute_2,
multi_indicator_minute_3
};
fn main() -> PolarsResult<()> {
// Load minute data from CSV
let mut df = CsvReadOptions::default()
.with_has_header(true)
.try_into_reader_with_file_path(Some("path/to/minute_data.csv".into()))?
.finish()?;
// Cast volume to float if needed
df = df.lazy()
.with_columns([
col("volume").cast(DataType::Float64),
])
.collect()?;
// Initialize strategies with default parameters
let params1 = multi_indicator_minute_1::StrategyParams::default();
let params2 = multi_indicator_minute_2::StrategyParams::default();
let params3 = multi_indicator_minute_3::StrategyParams::default();
// Run strategies
let signals1 = multi_indicator_minute_1::run_strategy(&df, ¶ms1)?;
let signals2 = multi_indicator_minute_2::run_strategy(&df, ¶ms2)?;
let signals3 = multi_indicator_minute_3::run_strategy(&df, ¶ms3)?;
// Calculate performance for each strategy
let close_prices = df.column("close")?;
let (final_value1, return1, trades1, win_rate1, drawdown1, _, _) =
multi_indicator_minute_1::calculate_performance(
close_prices,
&signals1.buy_signals,
&signals1.sell_signals,
10000.0,
true
);
let (final_value2, return2, trades2, win_rate2, drawdown2, _, _) =
multi_indicator_minute_2::calculate_performance(
close_prices,
&signals2.buy_signals,
&signals2.sell_signals,
&signals2.position_sizes,
10000.0,
true,
None
);
// Compare results
println!("Strategy Comparison:");
println!("Metric | Strategy 1 | Strategy 2");
println!("------------------------------------");
println!("Return | {:.2}% | {:.2}%", return1, return2);
println!("Final Value | ${:.2} | ${:.2}", final_value1, final_value2);
println!("Win Rate | {:.2}% | {:.2}%", win_rate1, win_rate2);
println!("Max Drawdown| {:.2}% | {:.2}%", drawdown1*100.0, drawdown2*100.0);
// Determine best performer
if return1 > return2 {
println!("\nStrategy 1 performed better on absolute return");
} else {
println!("\nStrategy 2 performed better on absolute return");
}
// Risk-adjusted comparison
let risk_adjusted1 = return1 / (drawdown1 * 100.0);
let risk_adjusted2 = return2 / (drawdown2 * 100.0);
if risk_adjusted1 > risk_adjusted2 {
println!("Strategy 1 performed better on risk-adjusted basis");
} else {
println!("Strategy 2 performed better on risk-adjusted basis");
}
Ok(())
}
§Advanced Intraday Strategy Example
See examples/enhanced_minute_strategy_example.rs
for a full example of an advanced minute-level multi-indicator strategy. This example demonstrates:
- Loading minute-level OHLCV data from CSV
- Running a multi-indicator strategy with risk management
- Calculating and printing performance metrics
- Saving all signals and indicators to a CSV file (
enhanced_minute_strategy_results.csv
) for further analysis
See the documentation for each module for more detailed information and examples.
Re-exports§
pub use indicators::*;
pub use strategy::*;
Modules§
- indicators
- strategy
- Trading Strategies
- util