use polars::prelude::*;
use crate::indicators::moving_averages::calculate_vwap;
mod vwap_analysis;
mod opening_range;
mod intraday_momentum;
mod adaptive_rsi;
mod rapid_macd;
mod gap_analysis;
pub use vwap_analysis::*;
pub use opening_range::*;
pub use intraday_momentum::*;
pub use adaptive_rsi::*;
pub use rapid_macd::*;
pub use gap_analysis::*;
pub fn add_day_trading_indicators(
df: &DataFrame,
time_col: Option<&str>,
date_col: Option<&str>,
) -> PolarsResult<DataFrame> {
let mut result = df.clone();
if df.schema().contains("volume") {
let vwap = calculate_vwap(df)?;
result.with_column(vwap)?;
vwap_analysis::add_vwap_bands(&mut result)?;
}
if let Some(time_column) = time_col {
if df.schema().contains(time_column) {
opening_range::add_opening_range_analysis(&mut result, time_column)?;
}
}
intraday_momentum::add_intraday_momentum_index(&mut result, 14)?;
adaptive_rsi::add_adaptive_rsi(&mut result, 7)?;
rapid_macd::add_rapid_macd(&mut result, None, None, None)?;
if let Some(date_column) = date_col {
if df.schema().contains(date_column) {
gap_analysis::add_gap_analysis(&mut result, Some(0.5))?;
}
}
Ok(result)
}
pub fn generate_day_trading_signals(df: &DataFrame) -> PolarsResult<Series> {
let required_indicators = [
"vwap", "adaptive_rsi", "rapid_macd", "intraday_momentum_index"
];
for indicator in required_indicators {
if !df.schema().contains(indicator) {
return Err(PolarsError::ComputeError(
format!("Required indicator '{}' not found", indicator).into(),
));
}
}
let momentum_signals = intraday_momentum::calculate_momentum_reversal_signals(df)?;
let macd_signals = rapid_macd::calculate_rapid_macd_signals(df)?;
let has_gap_signals = df.schema().contains("gap_trade_signal");
let gap_signals = if has_gap_signals {
df.column("gap_trade_signal")?.i32()?
} else {
let mut empty_signals = Vec::with_capacity(df.height());
for _ in 0..df.height() {
empty_signals.push(0);
}
Series::new("empty_gap_signals", empty_signals).i32()?
};
let mom_vals = momentum_signals.i32()?;
let macd_vals = macd_signals.i32()?;
let mut combined_signals = Vec::with_capacity(df.height());
for i in 0..df.height() {
let mom = mom_vals.get(i).unwrap_or(0);
let macd = macd_vals.get(i).unwrap_or(0);
let gap = gap_signals.get(i).unwrap_or(0);
let mut bullish_count = 0;
let mut bearish_count = 0;
if mom > 0 { bullish_count += 1; }
if mom < 0 { bearish_count += 1; }
if macd > 0 { bullish_count += 1; }
if macd < 0 { bearish_count += 1; }
if gap > 0 { bullish_count += 1; }
if gap < 0 { bearish_count += 1; }
if bullish_count >= 2 && bearish_count == 0 {
combined_signals.push(1); } else if bearish_count >= 2 && bullish_count == 0 {
combined_signals.push(-1); } else if bullish_count > bearish_count {
combined_signals.push(1); } else if bearish_count > bullish_count {
combined_signals.push(-1); } else {
combined_signals.push(0); }
}
Ok(Series::new("day_trading_signal", combined_signals))
}