{"record":{"id":"3f9a3f7bcc61cc70","repo":"nautechsystems/nautilus_trader","slug":"continuous-future-ratio-adjustment-requires-positi","errorCode":null,"errorMessage":"Continuous future ratio adjustment requires positive prices, was {row_value}","messagePattern":"Continuous future ratio adjustment requires positive prices, was (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/data/src/engine/requests.rs","lineNumber":573,"sourceCode":"                \"Continuous future segment venue mismatch for {target_bar_type}: target venue {target_venue}, segment venues pre={}, post={}\",\n                pre_instrument_id.venue,\n                post_instrument_id.venue,\n            );\n        }\n\n        if let Some(previous) = previous_post_instrument_id\n            && pre_instrument_id != previous\n        {\n            anyhow::bail!(\n                \"Continuous future chain discontinuity for {target_bar_type}: previous post {previous} != current pre {pre_instrument_id}\",\n            );\n        }\n        previous_post_instrument_id = Some(post_instrument_id);\n\n        let pre_price = parse_transition_price(row.get(\"pre_price\"), row_value, \"pre_price\")?;\n        let post_price = parse_transition_price(row.get(\"post_price\"), row_value, \"post_price\")?;\n        if is_ratio && (pre_price <= Decimal::ZERO || post_price <= Decimal::ZERO) {\n            anyhow::bail!(\n                \"Continuous future ratio adjustment requires positive prices, was {row_value}\"\n            );\n        }\n\n        transitions.push(ContinuousFutureTransition {\n            transition_time_ns,\n            pre_instrument_id,\n            post_instrument_id,\n            pre_price,\n            post_price,\n        });\n    }\n\n    Ok(transitions)\n}\n\nfn parse_transition_instrument_id(\n    value: Option<&Value>,","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/data/src/engine/requests.rs#L555-L591","documentation":"Ratio-style adjustment (BackwardRatio/ForwardRatio) computes price ratios between the pre and post contracts at each transition, which is undefined for non-positive prices. When a ratio adjustment mode is selected, every transition's pre_price and post_price must be strictly positive.","triggerScenarios":"parse_transitions receives a transition row with pre_price <= 0 or post_price <= 0 while the request's adjustment mode is a ratio type — e.g. zero, negative, or placeholder prices in the roll table.","commonSituations":"Using 0 as a placeholder for an unknown transition price; signed/adjusted price series that dip at or below zero (e.g. negative oil futures); building rows from spreads rather than outright contract prices.","solutions":["Provide real positive outright contract prices for pre_price and post_price in every transition row.","If the underlying contract can trade at or below zero, use a spread adjustment mode (BackwardSpread/ForwardSpread) instead of ratio.","Validate all transition prices > 0 before issuing the request when using ratio adjustment."],"exampleFix":"// before\n{\"pre_price\": 0, \"post_price\": 21.5} // ratio mode\n// after\n{\"pre_price\": 20.75, \"post_price\": 21.5} // or switch to adjustment_mode 1 (spread)","handlingStrategy":"validation","validationCode":"if is_ratio {\n    for t in &transitions {\n        assert!(t.pre_price > Decimal::ZERO && t.post_price > Decimal::ZERO);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use 0 as a placeholder transition price","Prefer spread adjustment for products that can trade at or below zero","Validate prices > 0 whenever ratio mode is selected"],"tags":["validation","prices","continuous-futures"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}