perf(backtest): reduce Databento API calls on input changes

- on_form_change: Only update cost estimate, skip expensive derive_entry_spot
- Only call derive_entry_spot on date changes (start/end inputs)
- Other inputs (template, units, loan, LTV) just mark results stale
- This reduces lag from constant API polling
This commit is contained in:
Bu5hm4nn
2026-03-30 20:58:36 +02:00
parent aa22766ae3
commit c650cec159

View File

@@ -803,21 +803,13 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
mark_results_stale() mark_results_stale()
def on_form_change() -> None: def on_form_change() -> None:
"""Handle form changes with minimal API calls."""
validation_label.set_text("") validation_label.set_text("")
entry_spot, entry_error = derive_entry_spot() # Only update cost estimate, don't derive entry spot on every change
# Entry spot derivation is expensive (Databento API call)
update_cost_estimate() update_cost_estimate()
render_seeded_summary(entry_spot=entry_spot, entry_spot_error=entry_error) # Keep existing entry spot, don't re-derive
if entry_error: mark_results_stale()
entry_spot_hint.set_text("Entry spot unavailable until the scenario dates are valid.")
validation_label.set_text(entry_error)
render_result_state("Scenario validation failed", entry_error, tone="warning")
return
validation_error = validate_current_scenario(entry_spot=entry_spot)
if validation_error:
validation_label.set_text(validation_error)
render_result_state("Scenario validation failed", validation_error, tone="warning")
else:
mark_results_stale()
def run_backtest() -> None: def run_backtest() -> None:
validation_label.set_text("") validation_label.set_text("")
@@ -924,17 +916,19 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
render_result(result) render_result(result)
# Wire up event handlers # Wire up event handlers
# Only call expensive derive_entry_spot on date changes
data_source_select.on_value_change(lambda e: on_form_change()) data_source_select.on_value_change(lambda e: on_form_change())
dataset_select.on_value_change(lambda e: on_form_change()) dataset_select.on_value_change(lambda e: (update_date_range_hint(), on_form_change()))
schema_select.on_value_change(lambda e: on_form_change()) schema_select.on_value_change(lambda e: on_form_change())
symbol_select.on_value_change(lambda e: (update_date_range_hint(), on_form_change())) symbol_select.on_value_change(lambda e: update_date_range_hint())
start_input.on_value_change(lambda e: refresh_workspace_seeded_units()) start_input.on_value_change(lambda e: refresh_workspace_seeded_units())
end_input.on_value_change(lambda e: refresh_workspace_seeded_units()) end_input.on_value_change(lambda e: refresh_workspace_seeded_units())
start_price_input.on_value_change(lambda e: on_form_change()) # Don't trigger API calls on these changes
template_select.on_value_change(lambda e: on_form_change()) start_price_input.on_value_change(lambda e: mark_results_stale())
units_input.on_value_change(lambda e: on_form_change()) template_select.on_value_change(lambda e: mark_results_stale())
loan_input.on_value_change(lambda e: on_form_change()) units_input.on_value_change(lambda e: mark_results_stale())
ltv_input.on_value_change(lambda e: on_form_change()) loan_input.on_value_change(lambda e: mark_results_stale())
ltv_input.on_value_change(lambda e: mark_results_stale())
run_button.on_click(lambda: run_backtest()) run_button.on_click(lambda: run_backtest())
# Initial render # Initial render