fix: resolve all clippy warnings blocking push
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
70b99ad870
commit
ec9bf0410f
@@ -22,14 +22,10 @@ pub fn check_threshold(series: &[f64], level: f64, direction: i32) -> Vec<i8> {
|
|||||||
if prev.is_nan() || curr.is_nan() {
|
if prev.is_nan() || curr.is_nan() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if direction == 1 {
|
if (direction == 1 && prev <= level && curr > level)
|
||||||
if prev <= level && curr > level {
|
|| (direction == -1 && prev >= level && curr < level)
|
||||||
out[i] = 1;
|
{
|
||||||
}
|
out[i] = 1;
|
||||||
} else if direction == -1 {
|
|
||||||
if prev >= level && curr < level {
|
|
||||||
out[i] = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out
|
out
|
||||||
|
|||||||
@@ -1565,6 +1565,7 @@ pub struct MultiAssetBacktestResult {
|
|||||||
/// `weights_2d`: row-major (n_assets, n_bars)
|
/// `weights_2d`: row-major (n_assets, n_bars)
|
||||||
///
|
///
|
||||||
/// Callers must transpose from (n_bars, n_assets) if needed.
|
/// Callers must transpose from (n_bars, n_assets) if needed.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn backtest_multi_asset_core(
|
pub fn backtest_multi_asset_core(
|
||||||
close_2d: &[Vec<f64>],
|
close_2d: &[Vec<f64>],
|
||||||
weights_2d: &[Vec<f64>],
|
weights_2d: &[Vec<f64>],
|
||||||
@@ -1585,6 +1586,7 @@ pub fn backtest_multi_asset_core(
|
|||||||
|
|
||||||
// Apply portfolio constraints per bar
|
// Apply portfolio constraints per bar
|
||||||
let mut constrained: Vec<Vec<f64>> = weights_2d.to_vec();
|
let mut constrained: Vec<Vec<f64>> = weights_2d.to_vec();
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
if max_asset_weight != 1.0 || max_gross_exposure > 0.0 || max_net_exposure > 0.0 {
|
if max_asset_weight != 1.0 || max_gross_exposure > 0.0 || max_net_exposure > 0.0 {
|
||||||
for i in 0..n_bars {
|
for i in 0..n_bars {
|
||||||
// 1. Clamp per-asset weight
|
// 1. Clamp per-asset weight
|
||||||
@@ -1635,6 +1637,7 @@ pub fn backtest_multi_asset_core(
|
|||||||
|
|
||||||
// Portfolio return = sum of per-asset strategy returns
|
// Portfolio return = sum of per-asset strategy returns
|
||||||
let mut portfolio_returns = vec![0.0_f64; n_bars];
|
let mut portfolio_returns = vec![0.0_f64; n_bars];
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
for i in 0..n_bars {
|
for i in 0..n_bars {
|
||||||
let mut s = 0.0_f64;
|
let mut s = 0.0_f64;
|
||||||
for j in 0..n_assets {
|
for j in 0..n_assets {
|
||||||
|
|||||||
@@ -272,6 +272,7 @@ pub fn batch_atr(
|
|||||||
|
|
||||||
/// Apply Stochastic to each set of (high, low, close) columns.
|
/// Apply Stochastic to each set of (high, low, close) columns.
|
||||||
/// Returns `(slowk_columns, slowd_columns)`.
|
/// Returns `(slowk_columns, slowd_columns)`.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn batch_stoch(
|
pub fn batch_stoch(
|
||||||
high: &[Vec<f64>],
|
high: &[Vec<f64>],
|
||||||
low: &[Vec<f64>],
|
low: &[Vec<f64>],
|
||||||
|
|||||||
@@ -231,13 +231,7 @@ pub fn supertrend(
|
|||||||
// Direction and output only from index timeperiod (warmup = 0, NaN)
|
// Direction and output only from index timeperiod (warmup = 0, NaN)
|
||||||
if i >= timeperiod {
|
if i >= timeperiod {
|
||||||
let prev_dir = direction[i - 1];
|
let prev_dir = direction[i - 1];
|
||||||
direction[i] = if prev_dir == 0 {
|
direction[i] = if prev_dir == 0 || prev_dir == -1 {
|
||||||
if close[i] > upper_band[i] {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
} else if prev_dir == -1 {
|
|
||||||
if close[i] > upper_band[i] {
|
if close[i] > upper_band[i] {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
@@ -464,6 +458,7 @@ pub fn chandelier_exit(
|
|||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// `(tenkan, kijun, senkou_a, senkou_b, chikou)` arrays.
|
/// `(tenkan, kijun, senkou_a, senkou_b, chikou)` arrays.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn ichimoku(
|
pub fn ichimoku(
|
||||||
high: &[f64],
|
high: &[f64],
|
||||||
low: &[f64],
|
low: &[f64],
|
||||||
@@ -534,6 +529,7 @@ pub fn ichimoku(
|
|||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// `(pivot, r1, s1, r2, s2)` arrays. Index 0 is always `NaN` (no previous bar).
|
/// `(pivot, r1, s1, r2, s2)` arrays. Index 0 is always `NaN` (no previous bar).
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn pivot_points(
|
pub fn pivot_points(
|
||||||
high: &[f64],
|
high: &[f64],
|
||||||
low: &[f64],
|
low: &[f64],
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ pub fn correlation_matrix(data: &[Vec<f64>]) -> Vec<Vec<f64>> {
|
|||||||
assert!(n_assets > 0, "data must contain at least one asset column");
|
assert!(n_assets > 0, "data must contain at least one asset column");
|
||||||
let n_bars = data[0].len();
|
let n_bars = data[0].len();
|
||||||
assert!(n_bars >= 2, "data must have at least 2 rows (bars)");
|
assert!(n_bars >= 2, "data must have at least 2 rows (bars)");
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
for j in 1..n_assets {
|
for j in 1..n_assets {
|
||||||
assert!(
|
assert!(
|
||||||
data[j].len() == n_bars,
|
data[j].len() == n_bars,
|
||||||
@@ -190,6 +191,7 @@ pub fn correlation_matrix(data: &[Vec<f64>]) -> Vec<Vec<f64>> {
|
|||||||
|
|
||||||
// Build correlation matrix (exploit symmetry: compute each pair once)
|
// Build correlation matrix (exploit symmetry: compute each pair once)
|
||||||
let mut result = vec![vec![0.0_f64; n_assets]; n_assets];
|
let mut result = vec![vec![0.0_f64; n_assets]; n_assets];
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
for j1 in 0..n_assets {
|
for j1 in 0..n_assets {
|
||||||
result[j1][j1] = 1.0;
|
result[j1][j1] = 1.0;
|
||||||
for j2 in (j1 + 1)..n_assets {
|
for j2 in (j1 + 1)..n_assets {
|
||||||
@@ -332,6 +334,7 @@ pub fn compose_weighted(data: &[Vec<f64>], weights: &[f64]) -> Vec<f64> {
|
|||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
let n_bars = data[0].len();
|
let n_bars = data[0].len();
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
for j in 1..n_sigs {
|
for j in 1..n_sigs {
|
||||||
assert!(
|
assert!(
|
||||||
data[j].len() == n_bars,
|
data[j].len() == n_bars,
|
||||||
|
|||||||
+10
-11
@@ -147,8 +147,7 @@ pub fn sma_crossover_signals<'py>(
|
|||||||
validation::validate_timeperiod(fast, "fast", 1)?;
|
validation::validate_timeperiod(fast, "fast", 1)?;
|
||||||
validation::validate_timeperiod(slow, "slow", 1)?;
|
validation::validate_timeperiod(slow, "slow", 1)?;
|
||||||
let prices = close.as_slice()?;
|
let prices = close.as_slice()?;
|
||||||
let out =
|
let out = core_bt::sma_crossover_signals(prices, fast, slow).map_err(PyValueError::new_err)?;
|
||||||
core_bt::sma_crossover_signals(prices, fast, slow).map_err(|e| PyValueError::new_err(e))?;
|
|
||||||
Ok(out.into_pyarray(py))
|
Ok(out.into_pyarray(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +165,7 @@ pub fn macd_crossover_signals<'py>(
|
|||||||
validation::validate_timeperiod(signalperiod, "signalperiod", 1)?;
|
validation::validate_timeperiod(signalperiod, "signalperiod", 1)?;
|
||||||
let prices = close.as_slice()?;
|
let prices = close.as_slice()?;
|
||||||
let out = core_bt::macd_crossover_signals(prices, fastperiod, slowperiod, signalperiod)
|
let out = core_bt::macd_crossover_signals(prices, fastperiod, slowperiod, signalperiod)
|
||||||
.map_err(|e| PyValueError::new_err(e))?;
|
.map_err(PyValueError::new_err)?;
|
||||||
Ok(out.into_pyarray(py))
|
Ok(out.into_pyarray(py))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +209,7 @@ pub fn backtest_core<'py>(
|
|||||||
initial_capital,
|
initial_capital,
|
||||||
commission_per_trade,
|
commission_per_trade,
|
||||||
)
|
)
|
||||||
.map_err(|e| PyValueError::new_err(e))?;
|
.map_err(PyValueError::new_err)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
result.positions.into_pyarray(py),
|
result.positions.into_pyarray(py),
|
||||||
@@ -314,7 +313,7 @@ pub fn backtest_ohlcv_core<'py>(
|
|||||||
let lp_opt: Option<&[f64]> = limit_prices.as_ref().and_then(|lp| lp.as_slice().ok());
|
let lp_opt: Option<&[f64]> = limit_prices.as_ref().and_then(|lp| lp.as_slice().ok());
|
||||||
|
|
||||||
let result = core_bt::backtest_ohlcv_core(o, h, l, c, s, &config, lp_opt)
|
let result = core_bt::backtest_ohlcv_core(o, h, l, c, s, &config, lp_opt)
|
||||||
.map_err(|e| PyValueError::new_err(e))?;
|
.map_err(PyValueError::new_err)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
result.positions.into_pyarray(py),
|
result.positions.into_pyarray(py),
|
||||||
@@ -344,7 +343,7 @@ pub fn compute_performance_metrics<'py>(
|
|||||||
let br = benchmark_returns.as_ref().and_then(|b| b.as_slice().ok());
|
let br = benchmark_returns.as_ref().and_then(|b| b.as_slice().ok());
|
||||||
|
|
||||||
let metrics = core_bt::compute_performance_metrics(r, eq, periods_per_year, risk_free_rate, br)
|
let metrics = core_bt::compute_performance_metrics(r, eq, periods_per_year, risk_free_rate, br)
|
||||||
.map_err(|e| PyValueError::new_err(e))?;
|
.map_err(PyValueError::new_err)?;
|
||||||
|
|
||||||
let dict = PyDict::new(py);
|
let dict = PyDict::new(py);
|
||||||
dict.set_item("total_return", metrics.total_return)?;
|
dict.set_item("total_return", metrics.total_return)?;
|
||||||
@@ -441,8 +440,7 @@ pub fn extract_trades_ohlcv<'py>(
|
|||||||
(l.len(), "low"),
|
(l.len(), "low"),
|
||||||
])?;
|
])?;
|
||||||
|
|
||||||
let trades =
|
let trades = core_bt::extract_trades_ohlcv(pos, fp, h, l).map_err(PyValueError::new_err)?;
|
||||||
core_bt::extract_trades_ohlcv(pos, fp, h, l).map_err(|e| PyValueError::new_err(e))?;
|
|
||||||
|
|
||||||
let mut entry_bars: Vec<i64> = Vec::with_capacity(trades.len());
|
let mut entry_bars: Vec<i64> = Vec::with_capacity(trades.len());
|
||||||
let mut exit_bars: Vec<i64> = Vec::with_capacity(trades.len());
|
let mut exit_bars: Vec<i64> = Vec::with_capacity(trades.len());
|
||||||
@@ -535,6 +533,7 @@ pub fn backtest_multi_asset_core<'py>(
|
|||||||
// Apply portfolio constraints first via the core function's logic.
|
// Apply portfolio constraints first via the core function's logic.
|
||||||
|
|
||||||
// Apply constraints
|
// Apply constraints
|
||||||
|
#[allow(clippy::needless_range_loop)]
|
||||||
if max_asset_weight != 1.0 || max_gross_exposure > 0.0 || max_net_exposure > 0.0 {
|
if max_asset_weight != 1.0 || max_gross_exposure > 0.0 || max_net_exposure > 0.0 {
|
||||||
for i in 0..n_bars {
|
for i in 0..n_bars {
|
||||||
if max_asset_weight < f64::INFINITY && max_asset_weight > 0.0 {
|
if max_asset_weight < f64::INFINITY && max_asset_weight > 0.0 {
|
||||||
@@ -703,7 +702,7 @@ pub fn walk_forward_indices<'py>(
|
|||||||
step_bars: usize,
|
step_bars: usize,
|
||||||
) -> PyResult<Bound<'py, PyArray2<i64>>> {
|
) -> PyResult<Bound<'py, PyArray2<i64>>> {
|
||||||
let folds = core_bt::walk_forward_indices(n_bars, train_bars, test_bars, anchored, step_bars)
|
let folds = core_bt::walk_forward_indices(n_bars, train_bars, test_bars, anchored, step_bars)
|
||||||
.map_err(|e| PyValueError::new_err(e))?;
|
.map_err(PyValueError::new_err)?;
|
||||||
|
|
||||||
let n_folds = folds.len();
|
let n_folds = folds.len();
|
||||||
let mut arr = Array2::<i64>::zeros((n_folds, 4));
|
let mut arr = Array2::<i64>::zeros((n_folds, 4));
|
||||||
@@ -722,12 +721,12 @@ pub fn walk_forward_indices<'py>(
|
|||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
pub fn kelly_fraction(win_rate: f64, avg_win: f64, avg_loss: f64) -> PyResult<f64> {
|
pub fn kelly_fraction(win_rate: f64, avg_win: f64, avg_loss: f64) -> PyResult<f64> {
|
||||||
core_bt::kelly_fraction(win_rate, avg_win, avg_loss).map_err(|e| PyValueError::new_err(e))
|
core_bt::kelly_fraction(win_rate, avg_win, avg_loss).map_err(PyValueError::new_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pyfunction]
|
#[pyfunction]
|
||||||
pub fn half_kelly_fraction(win_rate: f64, avg_win: f64, avg_loss: f64) -> PyResult<f64> {
|
pub fn half_kelly_fraction(win_rate: f64, avg_win: f64, avg_loss: f64) -> PyResult<f64> {
|
||||||
core_bt::half_kelly_fraction(win_rate, avg_win, avg_loss).map_err(|e| PyValueError::new_err(e))
|
core_bt::half_kelly_fraction(win_rate, avg_win, avg_loss).map_err(PyValueError::new_err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -298,13 +298,19 @@ pub struct StreamingVWAP {
|
|||||||
inner: core::StreamingVWAP,
|
inner: core::StreamingVWAP,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for StreamingVWAP {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
inner: core::StreamingVWAP::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
impl StreamingVWAP {
|
impl StreamingVWAP {
|
||||||
#[new]
|
#[new]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self::default()
|
||||||
inner: core::StreamingVWAP::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new bar (high, low, close, volume) and return cumulative VWAP.
|
/// Add a new bar (high, low, close, volume) and return cumulative VWAP.
|
||||||
|
|||||||
Reference in New Issue
Block a user