Improve Volume Weighted Average Price (VWAP) indicator parity with Cython #2661
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Restores feature-parity and behavioural equivalence between the Rust
VolumeWeightedAveragePrice
implementation and the canonical Python/Cython reference.1 · Why this matters — Context & Motivation
P ∿ L
.2 · What changed
floor(ts / 86 400)
guards day transitionsday: f64
prone to rounding driftday: i64
epoch-day with exact comparisonreset()
+ new-day seedvolume_total
could underflowvalue
&initialized
initialized
false-positive3 · Five practical ways to put VWAP to work
slip_bps = (fill - close.vwap()) / close * 10_000
upper = vwap * 1.01; lower = vwap * 0.99
size = risk_perc * equity / (atr * vol.vwap(30))
price − VWAP
spread flags trend strength.mom = (close - vwap) / vwap
stop = max(stop, vwap_today)
4 · Implementation notes
const SECONDS_PER_DAY: f64 = 86_400.0; epoch_day = (ts / SECONDS_PER_DAY).floor() as i64
— immune to FP drift and DST.timestamp < day
; seeds with current price/volume pair.vol == 0
; negative volumes offsetvolume_total
but never allow it < 0.test_first_input_zero_volume_does_not_divide_by_zero
.value
becomes NaN until explicitreset()
.VolumeWeightedAveragePrice
is !Send + !Sync; wrap inArc<Mutex<>>
for multi-threaded pipelines.5 · Tests added / updated
test_vwap_initialized
Display::fmt
sanity checktest_value_with_one_input
test_value_with_three_inputs_on_the_same_day
test_value_with_three_inputs_on_different_days
test_value_with_ten_inputs
test_reset
reset()
restores zero-statetest_reset_on_exact_day_boundary
test_no_reset_within_same_day
test_zero_volume_does_not_change_value
test_epoch_day_floor_rounding
test_reset_when_timestamp_goes_backwards
test_no_reset_for_same_epoch_day
test_reset_when_epoch_day_changes
test_first_input_zero_volume_does_not_divide_by_zero
test_zero_volume_day_rollover_resets_and_seeds
test_handle_bar_matches_update_raw
handle_bar()
≡ triplet of raw callstest_extreme_prices_and_volumes_do_not_overflow
negative_timestamp
huge_future_timestamp_saturates
negative_volume_changes_sign
nan_volume_propagates
zero_and_negative_price
nan_price_propagates
Related
#2507