feat: defer entry spot derivation to backtest run (BT-005)
- Remove async refresh_workspace_seeded_units from date change handlers - Date changes now only call on_form_change() (updates cost estimates, marks results stale) - Entry spot is derived only when user clicks Run button - Form remains responsive during configuration - No more API errors when changing dates while configuring other fields
This commit is contained in:
@@ -5,7 +5,7 @@ from datetime import date, datetime
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from fastapi.responses import RedirectResponse
|
||||
from nicegui import run, ui
|
||||
from nicegui import ui
|
||||
|
||||
from app.domain.backtesting_math import asset_quantity_from_workspace_config
|
||||
from app.models.backtest import ProviderRef
|
||||
@@ -784,32 +784,6 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
logger.warning(f"Failed to save backtest settings for workspace {workspace_id}: {e}")
|
||||
return None
|
||||
|
||||
async def refresh_workspace_seeded_units() -> None:
|
||||
"""Derive entry spot asynchronously and update units when dates change."""
|
||||
validation_label.set_text("")
|
||||
progress_label.set_text("Fetching entry spot...")
|
||||
|
||||
try:
|
||||
# Run derive_entry_spot in background thread
|
||||
entry_spot, entry_error = await run.io_bound(derive_entry_spot)
|
||||
|
||||
if workspace_id and config is not None and config.gold_value is not None and entry_spot is not None:
|
||||
units_input.value = asset_quantity_from_workspace_config(
|
||||
config, entry_spot=entry_spot, symbol=get_symbol_from_dataset()
|
||||
)
|
||||
update_cost_estimate()
|
||||
render_seeded_summary(entry_spot=entry_spot, entry_spot_error=entry_error)
|
||||
if entry_error:
|
||||
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")
|
||||
finally:
|
||||
progress_label.set_text("")
|
||||
|
||||
def on_form_change() -> None:
|
||||
"""Handle form changes with minimal API calls."""
|
||||
validation_label.set_text("")
|
||||
@@ -1061,13 +1035,14 @@ def _render_backtests_page(workspace_id: str | None = None) -> None:
|
||||
update_cost_estimate()
|
||||
|
||||
# Wire up event handlers
|
||||
# Only call expensive derive_entry_spot on date changes
|
||||
# Date changes should NOT trigger expensive derive_entry_spot API call
|
||||
# Entry spot derivation happens when user clicks Run
|
||||
data_source_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())
|
||||
symbol_select.on_value_change(lambda e: update_date_range_hint())
|
||||
start_input.on_value_change(lambda e: refresh_workspace_seeded_units())
|
||||
end_input.on_value_change(lambda e: refresh_workspace_seeded_units())
|
||||
start_input.on_value_change(lambda e: on_form_change())
|
||||
end_input.on_value_change(lambda e: on_form_change())
|
||||
# Don't trigger API calls on these changes
|
||||
start_price_input.on_value_change(lambda e: mark_results_stale())
|
||||
template_select.on_value_change(lambda e: mark_results_stale())
|
||||
|
||||
Reference in New Issue
Block a user