-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Improve implementation, validations and testing for Rust instruments #2723
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
crates/model/src/instruments/mod.rs
Outdated
} else { | ||
// Use standard rounding behavior (banker's rounding) | ||
Quantity::new(value, self.size_precision()) | ||
let factor = 10f64.powi(self.size_precision() as i32); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is all this additional code to ensure half-even rounding?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concern / Feature | “Before” – simple f64 version |
“After” – rust_decimal + guards |
Why the extra code? |
---|---|---|---|
Numeric type used | Pure f64 maths. |
Decimal (base-10 exact) → then back to f64 . |
Avoids binary-decimal drift. |
Rounding when round_down = Some(true) |
floor() toward −∞. |
RoundingStrategy::ToZero (truncate toward 0). |
Symmetric for neg & pos sizes; aligns with most exchange “round-down” rules. |
Default rounding (None / false ) |
No rounding at all (just passes value ). |
MidpointNearestEven (half-even, “banker’s”). |
Yes, half-even rounding is now explicit instead of implicit/absent. |
Half-even support on midpoint ties | ❌ (relies on Quantity::new or IEEE default). |
✅ Guaranteed via MidpointNearestEven . |
Adds determinism and auditability. |
Handling NaN / ∞ | Whatever Quantity::new does (implicit). |
from_f64_retain + expect("non-finite") – explicit panic. |
Fail fast & loud. |
Guard against sub-tick quantities | None. | Panics if positive input would round to < 10 % of one tick. | Prevents zero-size orders. |
Cross-platform determinism | Dependent on IEEE-754 quirks / FP env. | Pure integer math inside Decimal → deterministic. |
Reproducible replays. |
Performance | Minimal ops (cheap). | Extra Decimal ops; still cheap but slower in tight loops. |
Usually negligible outside ultra-low-latency paths. |
Lines of code / readability | Short, easy to scan. | Longer, self-documenting; comments explain invariants. | Clarity & safety trade-off. |
Primary reason for the added code? | — | Not just half-even rounding; also precision-safe conversion, non-finite guard, sub-tick guard, deterministic behaviour. | Half-even is one piece of the puzzle. |
Is all this additional code only to ensure half-even rounding?
No. Ensuring midpoint-nearest-even rounding is an important part, but the extra lines also:
- Eliminate binary floating-point drift by moving to exact base-10 arithmetic during rounding.
- Fail fast on NaN/∞ instead of relying on downstream checks.
- Guarantee deterministic behaviour across platforms and compiler flags.
- Prevent “rounded-to-zero” sizes that would be rejected by exchanges.
So half-even rounding is necessary but not sufficient—the additional safeguards and determinism are equally valuable in a trading context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let me know if there are any actions I need to take here ☝️
crates/model/src/instruments/mod.rs
Outdated
scheme.next_bid_price(value, n, self.price_precision())? | ||
} else { | ||
let inc = self.price_increment().as_f64(); | ||
if inc <= 0.0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prices can potentially be negative (options, spreads, commodities etc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
adjusted, thx
Instrument
symbol
(property)symbol(&self) -> &str
&str
).venue
(property)venue(&self) -> &str
get_cost_currency()
cost_currency(&self) -> &Currency
make_price(value)
make_price(&self, value: f64)
make_qty(value, round_down=False)
make_qty(&self, value: f64, round_down: bool)
notional_value(qty, price, use_quote)
notional_value(&self, qty, price, use_quote_for_inverse: bool)
calculate_base_quantity(qty, last_px)
calculate_base_quantity(&self, qty, last_px)