Files
ferro-ta/src/options/american.rs
T
Pratik BhadaneandGitHub 3e0f289d51 chore: update ferro-ta version to 1.1.3 (#8)
- Bumped version numbers across Cargo.toml, Cargo.lock, pyproject.toml, and conda/meta.yaml to 1.1.3.
- Added new features including American option pricing, digital options, extended Greeks, and historical volatility estimators.
- Enhanced documentation and tests for new functionalities.
- Updated CHANGELOG.md to reflect changes for version 1.1.3.
2026-04-02 16:38:32 +05:30

128 lines
3.8 KiB
Rust

use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};
use pyo3::prelude::*;
use ferro_ta_core::options::american::{
american_price_baw as core_american_price,
early_exercise_premium as core_early_exercise_premium,
};
#[pyfunction]
#[pyo3(signature = (underlying, strike, rate, time_to_expiry, volatility, option_type = "call", carry = 0.0))]
#[allow(clippy::too_many_arguments)]
pub fn american_price(
underlying: f64,
strike: f64,
rate: f64,
time_to_expiry: f64,
volatility: f64,
option_type: &str,
carry: f64,
) -> PyResult<f64> {
let kind = super::parse_option_kind(option_type)?;
Ok(core_american_price(
underlying,
strike,
rate,
carry,
time_to_expiry,
volatility,
kind,
))
}
#[pyfunction]
#[pyo3(signature = (underlying, strike, rate, time_to_expiry, volatility, option_type = "call", carry = None))]
#[allow(clippy::too_many_arguments)]
pub fn american_price_batch<'py>(
py: Python<'py>,
underlying: PyReadonlyArray1<'py, f64>,
strike: PyReadonlyArray1<'py, f64>,
rate: PyReadonlyArray1<'py, f64>,
time_to_expiry: PyReadonlyArray1<'py, f64>,
volatility: PyReadonlyArray1<'py, f64>,
option_type: &str,
carry: Option<PyReadonlyArray1<'py, f64>>,
) -> PyResult<Bound<'py, PyArray1<f64>>> {
let kind = super::parse_option_kind(option_type)?;
let underlying = underlying.as_slice()?;
let strike = strike.as_slice()?;
let rate = rate.as_slice()?;
let tte = time_to_expiry.as_slice()?;
let vol = volatility.as_slice()?;
let n = underlying.len();
let carry_vec = match carry {
Some(arr) => arr.as_slice()?.to_vec(),
None => vec![0.0; n],
};
let out: Vec<f64> = underlying
.iter()
.zip(strike.iter())
.zip(rate.iter())
.zip(tte.iter())
.zip(vol.iter())
.zip(carry_vec.iter())
.map(|(((((&u, &k), &r), &t), &v), &c)| core_american_price(u, k, r, c, t, v, kind))
.collect();
Ok(out.into_pyarray(py))
}
#[pyfunction]
#[pyo3(signature = (underlying, strike, rate, time_to_expiry, volatility, option_type = "call", carry = 0.0))]
#[allow(clippy::too_many_arguments)]
pub fn early_exercise_premium(
underlying: f64,
strike: f64,
rate: f64,
time_to_expiry: f64,
volatility: f64,
option_type: &str,
carry: f64,
) -> PyResult<f64> {
let kind = super::parse_option_kind(option_type)?;
Ok(core_early_exercise_premium(
underlying,
strike,
rate,
carry,
time_to_expiry,
volatility,
kind,
))
}
#[pyfunction]
#[pyo3(signature = (underlying, strike, rate, time_to_expiry, volatility, option_type = "call", carry = None))]
#[allow(clippy::too_many_arguments)]
pub fn early_exercise_premium_batch<'py>(
py: Python<'py>,
underlying: PyReadonlyArray1<'py, f64>,
strike: PyReadonlyArray1<'py, f64>,
rate: PyReadonlyArray1<'py, f64>,
time_to_expiry: PyReadonlyArray1<'py, f64>,
volatility: PyReadonlyArray1<'py, f64>,
option_type: &str,
carry: Option<PyReadonlyArray1<'py, f64>>,
) -> PyResult<Bound<'py, PyArray1<f64>>> {
let kind = super::parse_option_kind(option_type)?;
let underlying = underlying.as_slice()?;
let strike = strike.as_slice()?;
let rate = rate.as_slice()?;
let tte = time_to_expiry.as_slice()?;
let vol = volatility.as_slice()?;
let n = underlying.len();
let carry_vec = match carry {
Some(arr) => arr.as_slice()?.to_vec(),
None => vec![0.0; n],
};
let out: Vec<f64> = underlying
.iter()
.zip(strike.iter())
.zip(rate.iter())
.zip(tte.iter())
.zip(vol.iter())
.zip(carry_vec.iter())
.map(|(((((&u, &k), &r), &t), &v), &c)| core_early_exercise_premium(u, k, r, c, t, v, kind))
.collect();
Ok(out.into_pyarray(py))
}