-
Notifications
You must be signed in to change notification settings - Fork 29
Closed
Labels
priority-lowNice-to-have improvementsNice-to-have improvementstestingTesting improvementsTesting improvements
Description
Issue #12: Add property-based testing
Title
test: Add property-based testing for mathematical invariants
Labels
testingqualitypriority-low
Description
Add property-based testing using proptest to validate mathematical invariants like Put-Call Parity and Greeks bounds.
Current State
- Tests use specific example values
- Mathematical invariants not systematically tested
- Edge cases may be missed
Target State
- Property-based tests cover key mathematical invariants
- Tests run as part of the test suite
- Higher confidence in mathematical correctness
Tasks
- Add
proptestas a dev dependency - Add property tests for Put-Call Parity:
C - P = S - K * e^(-rT)
- Add property tests for Greeks bounds:
0 ≤ delta ≤ 1for calls-1 ≤ delta ≤ 0for putsgamma ≥ 0for all options
- Add property tests for arbitrage-free pricing:
C ≥ max(0, S - K * e^(-rT))P ≥ max(0, K * e^(-rT) - S)
- Add property tests for Positive type invariants:
- Value is always > 0
- Operations preserve positivity where expected
- Add property tests for strategy invariants:
- Break-even points are within valid range
- Max profit/loss are consistent
- Run
make lint-fixandmake pre-pushto verify
Acceptance Criteria
- Property tests cover key mathematical invariants
- Tests run as part of the test suite
- No false positives in normal operation
- Edge cases are properly handled
Technical Notes
Put-Call Parity Test
use proptest::prelude::*;
proptest! {
#[test]
fn test_put_call_parity(
s in 10.0f64..1000.0,
k in 10.0f64..1000.0,
r in 0.0f64..0.2,
sigma in 0.05f64..1.0,
t in 0.01f64..2.0,
) {
let s = pos!(s);
let k = pos!(k);
let sigma = pos!(sigma);
let t = pos!(t);
let call = black_scholes_call(s, k, r, sigma, t);
let put = black_scholes_put(s, k, r, sigma, t);
let parity_lhs = call - put;
let parity_rhs = s.to_dec() - k.to_dec() * (-r * t.to_dec()).exp();
prop_assert!((parity_lhs - parity_rhs).abs() < dec!(0.0001));
}
}Greeks Bounds Test
proptest! {
#[test]
fn test_call_delta_bounds(
s in 10.0f64..1000.0,
k in 10.0f64..1000.0,
sigma in 0.05f64..1.0,
t in 0.01f64..2.0,
) {
let option = create_call_option(s, k, sigma, t);
let delta = option.delta().unwrap();
prop_assert!(delta >= dec!(0.0));
prop_assert!(delta <= dec!(1.0));
}
#[test]
fn test_gamma_non_negative(
s in 10.0f64..1000.0,
k in 10.0f64..1000.0,
sigma in 0.05f64..1.0,
t in 0.01f64..2.0,
) {
let option = create_call_option(s, k, sigma, t);
let gamma = option.gamma().unwrap();
prop_assert!(gamma >= dec!(0.0));
}
}Files to Create/Update
Cargo.toml(add proptest dependency)tests/property/mod.rstests/property/put_call_parity_test.rstests/property/greeks_bounds_test.rstests/property/positive_invariants_test.rs
Estimated Effort
Medium (4-6 hours)
Dependencies
None
Related Issues
- Issue Feature/positive f64 #11: Add benchmarks for critical paths
Metadata
Metadata
Assignees
Labels
priority-lowNice-to-have improvementsNice-to-have improvementstestingTesting improvementsTesting improvements