============================= test session starts ==============================
platform linux -- Python 3.13.5, pytest-9.0.2, pluggy-1.6.0 -- /home/pi/.venv/bin/python3
cachedir: .pytest_cache
rootdir: /home/pi/fastbt
configfile: setup.cfg
plugins: time-machine-3.2.0, anyio-4.12.1
collecting ... collected 244 items

tests/backtest/test_context.py::TestDayStartContext::test_get_spot_returns_first_bar PASSED [  0%]
tests/backtest/test_context.py::TestDayStartContext::test_get_spot_empty_cache_returns_none PASSED [  0%]
tests/backtest/test_context.py::TestDayStartContext::test_get_atm_from_spot PASSED [  1%]
tests/backtest/test_context.py::TestDayStartContext::test_get_atm_step_100 PASSED [  1%]
tests/backtest/test_context.py::TestDayStartContext::test_prefetch_loads_into_cache PASSED [  2%]
tests/backtest/test_context.py::TestDayStartContext::test_prefetch_is_noop_on_cache_hit PASSED [  2%]
tests/backtest/test_context.py::TestDayStartContext::test_trade_date_accessible PASSED [  2%]
tests/backtest/test_context.py::TestBarContextAdvance::test_tick_and_index_update PASSED [  3%]
tests/backtest/test_context.py::TestBarContextAdvance::test_advance_updates_each_iteration PASSED [  3%]
tests/backtest/test_context.py::TestBarContextGetSpot::test_exact_tick_live PASSED [  4%]
tests/backtest/test_context.py::TestBarContextGetSpot::test_spot_at_different_tick PASSED [  4%]
tests/backtest/test_context.py::TestBarContextGetSpot::test_missing_spot_tick_fill_forward PASSED [  4%]
tests/backtest/test_context.py::TestBarContextGetSpot::test_no_spot_data_returns_none PASSED [  5%]
tests/backtest/test_context.py::TestBarContextGetPrice::test_exact_tick_live PASSED [  5%]
tests/backtest/test_context.py::TestBarContextGetPrice::test_fill_forward_on_missing_tick PASSED [  6%]
tests/backtest/test_context.py::TestBarContextGetPrice::test_data_available_after_gap PASSED [  6%]
tests/backtest/test_context.py::TestBarContextGetPrice::test_instrument_not_in_cache_triggers_lazy_fetch PASSED [  6%]
tests/backtest/test_context.py::TestBarContextGetPrice::test_lazy_fetch_only_called_once PASSED [  7%]
tests/backtest/test_context.py::TestBarContextGetPrice::test_unknown_instrument_returns_none PASSED [  7%]
tests/backtest/test_context.py::TestBarContextGetBar::test_returns_ohlcv_dict PASSED [  8%]
tests/backtest/test_context.py::TestBarContextGetBar::test_bar_fill_forward_on_missing_tick PASSED [  8%]
tests/backtest/test_context.py::TestBarContextGetBar::test_none_on_missing_instrument PASSED [  9%]
tests/backtest/test_context.py::TestBarContextGetAtm::test_atm_from_current_spot PASSED [  9%]
tests/backtest/test_context.py::TestBarContextGetAtm::test_atm_updates_with_spot PASSED [  9%]
tests/backtest/test_context.py::TestBarContextPrefetch::test_prefetch_loads_into_cache PASSED [ 10%]
tests/backtest/test_context.py::TestBarContextPrefetch::test_prefetch_noop_on_hit PASSED [ 10%]
tests/backtest/test_context.py::TestBarContextHelperProperties::test_trade_date_property PASSED [ 11%]
tests/backtest/test_context.py::TestBarContextHelperProperties::test_total_ticks PASSED [ 11%]
tests/backtest/test_context.py::TestBarContextHelperProperties::test_is_last_tick_false_on_first PASSED [ 11%]
tests/backtest/test_context.py::TestBarContextHelperProperties::test_is_last_tick_true_on_last PASSED [ 12%]
tests/backtest/test_context.py::TestBarContextHelperProperties::test_ticks_remaining_decrements PASSED [ 12%]
tests/backtest/test_context.py::TestAddToCache::test_day_start_add_to_cache PASSED [ 13%]
tests/backtest/test_context.py::TestAddToCache::test_bar_ctx_add_to_cache PASSED [ 13%]
tests/backtest/test_context.py::TestAddToCache::test_get_price_flat_scalar_live PASSED [ 13%]
tests/backtest/test_context.py::TestAddToCache::test_get_price_flat_fill_forward PASSED [ 14%]
tests/backtest/test_context.py::TestAddToCache::test_get_price_custom_no_lazy_fetch PASSED [ 14%]
tests/backtest/test_data.py::TestDataSourceProtocol::test_is_abstract PASSED [ 15%]
tests/backtest/test_data.py::TestDataSourceProtocol::test_get_instrument_data_has_no_start_time PASSED [ 15%]
tests/backtest/test_data.py::TestDataSourceProtocol::test_duckdb_loader_is_concrete PASSED [ 15%]
tests/backtest/test_data.py::TestGetUnderlyingData::test_returns_dict PASSED [ 16%]
tests/backtest/test_data.py::TestGetUnderlyingData::test_keys_are_strings PASSED [ 16%]
tests/backtest/test_data.py::TestGetUnderlyingData::test_values_are_floats PASSED [ 17%]
tests/backtest/test_data.py::TestGetUnderlyingData::test_all_ticks_present PASSED [ 17%]
tests/backtest/test_data.py::TestGetUnderlyingData::test_sorted_by_time PASSED [ 18%]
tests/backtest/test_data.py::TestGetUnderlyingData::test_bad_date_returns_empty PASSED [ 18%]
tests/backtest/test_data.py::TestGetInstrumentData::test_returns_nested_dict PASSED [ 18%]
tests/backtest/test_data.py::TestGetInstrumentData::test_ohlcv_keys_present PASSED [ 19%]
tests/backtest/test_data.py::TestGetInstrumentData::test_full_day_all_ticks_present PASSED [ 19%]
tests/backtest/test_data.py::TestGetInstrumentData::test_earliest_tick_present PASSED [ 20%]
tests/backtest/test_data.py::TestGetInstrumentData::test_values_are_floats PASSED [ 20%]
tests/backtest/test_data.py::TestGetInstrumentData::test_bad_strike_returns_empty PASSED [ 20%]
tests/backtest/test_data.py::TestGetInstrumentData::test_bad_date_returns_empty PASSED [ 21%]
tests/backtest/test_data.py::TestGetInstrumentData::test_pe_option PASSED [ 21%]
tests/backtest/test_data.py::TestGetAvailableDates::test_returns_list_of_strings PASSED [ 22%]
tests/backtest/test_data.py::TestGetAvailableDates::test_contains_fixture_dates PASSED [ 22%]
tests/backtest/test_data.py::TestGetAvailableDates::test_sorted PASSED   [ 22%]
tests/backtest/test_data.py::TestStaticHelpers::test_atm_exact PASSED    [ 23%]
tests/backtest/test_data.py::TestStaticHelpers::test_atm_rounds_up PASSED [ 23%]
tests/backtest/test_data.py::TestStaticHelpers::test_atm_rounds_down PASSED [ 24%]
tests/backtest/test_data.py::TestStaticHelpers::test_get_strike_zero_distance PASSED [ 24%]
tests/backtest/test_data.py::TestStaticHelpers::test_get_strike_positive PASSED [ 25%]
tests/backtest/test_data.py::TestStaticHelpers::test_get_strike_negative PASSED [ 25%]
tests/backtest/test_data.py::TestRealDataIntegration::test_real_available_dates PASSED [ 25%]
tests/backtest/test_data.py::TestRealDataIntegration::test_real_underlying_data PASSED [ 26%]
tests/backtest/test_data.py::TestRealDataIntegration::test_real_instrument_full_day PASSED [ 26%]
tests/backtest/test_engine.py::TestEngineInit::test_default_transaction_cost PASSED [ 27%]
tests/backtest/test_engine.py::TestEngineInit::test_custom_transaction_cost PASSED [ 27%]
tests/backtest/test_engine.py::TestEngineInit::test_default_max_cycles PASSED [ 27%]
tests/backtest/test_engine.py::TestEngineInit::test_custom_max_cycles PASSED [ 28%]
tests/backtest/test_engine.py::TestEngineInit::test_no_strategy_initially PASSED [ 28%]
tests/backtest/test_engine.py::TestAddStrategy::test_engine_injected_into_strategy PASSED [ 29%]
tests/backtest/test_engine.py::TestAddStrategy::test_max_cycles_injected_into_strategy PASSED [ 29%]
tests/backtest/test_engine.py::TestAddStrategy::test_strategy_stored PASSED [ 29%]
tests/backtest/test_engine.py::TestPerDayFlow::test_on_day_start_called_per_day PASSED [ 30%]
tests/backtest/test_engine.py::TestPerDayFlow::test_on_day_start_called_with_correct_dates PASSED [ 30%]
tests/backtest/test_engine.py::TestPerDayFlow::test_day_end_called_per_day PASSED [ 31%]
tests/backtest/test_engine.py::TestPerDayFlow::test_skip_day_when_on_day_start_returns_false PASSED [ 31%]
tests/backtest/test_engine.py::TestPerDayFlow::test_underlying_in_cache_when_on_day_start_fires PASSED [ 31%]
tests/backtest/test_engine.py::TestPerDayFlow::test_state_reset_each_day PASSED [ 32%]
tests/backtest/test_engine.py::TestClockBehaviour::test_auto_clock_from_underlying PASSED [ 32%]
tests/backtest/test_engine.py::TestClockBehaviour::test_user_clock_overrides_auto PASSED [ 33%]
tests/backtest/test_engine.py::TestClockBehaviour::test_tick_index_increments PASSED [ 33%]
tests/backtest/test_engine.py::TestClockBehaviour::test_tick_index_resets_each_day PASSED [ 34%]
tests/backtest/test_engine.py::TestEodForceClose::test_open_positions_closed_at_eod PASSED [ 34%]
tests/backtest/test_engine.py::TestEodForceClose::test_day_end_called_after_eod_close PASSED [ 34%]
tests/backtest/test_engine.py::TestEodForceClose::test_state_is_done_after_run PASSED [ 35%]
tests/backtest/test_engine.py::TestMultiDayAccumulation::test_closed_trades_accumulate_across_days PASSED [ 35%]
tests/backtest/test_engine.py::TestMultiDayAccumulation::test_date_range_filter PASSED [ 36%]
tests/backtest/test_engine.py::TestTransactionCostPropagation::test_cost_applied_to_closed_trades PASSED [ 36%]
tests/backtest/test_engine.py::TestTransactionCostPropagation::test_zero_cost_by_default PASSED [ 36%]
tests/backtest/test_engine.py::TestNoStrategy::test_run_without_strategy_raises PASSED [ 37%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_runs_without_error PASSED [ 37%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_closed_trades_not_empty PASSED [ 38%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_no_open_positions_remaining PASSED [ 38%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_every_trade_has_exit_reason PASSED [ 38%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_entry_before_exit PASSED [ 39%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_entry_at_or_after_entry_window PASSED [ 39%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_pnl_is_finite PASSED [ 40%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_transaction_costs_applied PASSED [ 40%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_metrics_produce_valid_output PASSED [ 40%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_win_rate_in_valid_range PASSED [ 41%]
tests/backtest/test_integration.py::TestStraddleIntegration::test_trade_pairs_per_day PASSED [ 41%]
tests/backtest/test_metrics.py::TestInit::test_accepts_empty_list PASSED [ 42%]
tests/backtest/test_metrics.py::TestInit::test_accepts_list_of_trades PASSED [ 42%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_total_trades_count PASSED [ 43%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_total_trades_empty PASSED [ 43%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_total_pnl PASSED [ 43%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_total_pnl_empty PASSED [ 44%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_total_pnl_all_losers PASSED [ 44%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_winning_trades PASSED [ 45%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_losing_trades PASSED [ 45%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_win_rate_percent PASSED [ 45%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_win_rate_zero_when_all_losers PASSED [ 46%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_win_rate_hundred_when_all_winners PASSED [ 46%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_win_rate_none_when_empty PASSED [ 47%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_avg_profit PASSED [ 47%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_avg_loss PASSED [ 47%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_avg_profit_none_when_no_winners PASSED [ 48%]
tests/backtest/test_metrics.py::TestSummaryMetrics::test_avg_loss_none_when_no_losers PASSED [ 48%]
tests/backtest/test_metrics.py::TestMaxDrawdown::test_no_drawdown_all_profits PASSED [ 49%]
tests/backtest/test_metrics.py::TestMaxDrawdown::test_drawdown_single_loss PASSED [ 49%]
tests/backtest/test_metrics.py::TestMaxDrawdown::test_drawdown_recovers_then_drops PASSED [ 50%]
tests/backtest/test_metrics.py::TestMaxDrawdown::test_drawdown_empty_trades PASSED [ 50%]
tests/backtest/test_metrics.py::TestMaxDrawdown::test_drawdown_all_losers PASSED [ 50%]
tests/backtest/test_metrics.py::TestSharpeRatio::test_sharpe_empty_returns_none PASSED [ 51%]
tests/backtest/test_metrics.py::TestSharpeRatio::test_sharpe_single_trade_returns_none PASSED [ 51%]
tests/backtest/test_metrics.py::TestSharpeRatio::test_sharpe_zero_std_returns_none PASSED [ 52%]
tests/backtest/test_metrics.py::TestSharpeRatio::test_sharpe_positive_for_net_positive PASSED [ 52%]
tests/backtest/test_metrics.py::TestSharpeRatio::test_sharpe_negative_for_net_negative PASSED [ 52%]
tests/backtest/test_metrics.py::TestCalculateAllMetrics::test_returns_dict PASSED [ 53%]
tests/backtest/test_metrics.py::TestCalculateAllMetrics::test_all_keys_present PASSED [ 53%]
tests/backtest/test_metrics.py::TestCalculateAllMetrics::test_empty_trades_returns_zeros PASSED [ 54%]
tests/backtest/test_models.py::TestInstrument::test_key_ce PASSED        [ 54%]
tests/backtest/test_models.py::TestInstrument::test_key_pe PASSED        [ 54%]
tests/backtest/test_models.py::TestInstrument::test_key_different_strike PASSED [ 55%]
tests/backtest/test_models.py::TestInstrument::test_frozen_cannot_mutate PASSED [ 55%]
tests/backtest/test_models.py::TestInstrument::test_hashable_as_dict_key PASSED [ 56%]
tests/backtest/test_models.py::TestInstrument::test_equality PASSED      [ 56%]
tests/backtest/test_models.py::TestInstrument::test_inequality_strike PASSED [ 56%]
tests/backtest/test_models.py::TestInstrument::test_inequality_opt_type PASSED [ 57%]
tests/backtest/test_models.py::TestInstrument::test_repr PASSED          [ 57%]
tests/backtest/test_models.py::TestLeg::test_basic_creation PASSED       [ 58%]
tests/backtest/test_models.py::TestLeg::test_default_qty PASSED          [ 58%]
tests/backtest/test_models.py::TestLeg::test_buy_side PASSED             [ 59%]
tests/backtest/test_models.py::TestLeg::test_sell_side PASSED            [ 59%]
tests/backtest/test_models.py::TestTradeCreation::test_required_fields PASSED [ 59%]
tests/backtest/test_models.py::TestTradeCreation::test_exit_fields_default_none PASSED [ 60%]
tests/backtest/test_models.py::TestTradeCreation::test_pnl_defaults_zero PASSED [ 60%]
tests/backtest/test_models.py::TestTradeCreation::test_is_open_true_when_no_exit PASSED [ 61%]
tests/backtest/test_models.py::TestTradeCreation::test_metadata_default_empty_dict PASSED [ 61%]
tests/backtest/test_models.py::TestTradeCreation::test_metadata_not_shared_between_instances PASSED [ 61%]
tests/backtest/test_models.py::TestTradeCreation::test_cycle_field PASSED [ 62%]
tests/backtest/test_models.py::TestTradeCreation::test_entry_tick_any_type PASSED [ 62%]
tests/backtest/test_models.py::TestTradeClose::test_is_open_false_after_close PASSED [ 63%]
tests/backtest/test_models.py::TestTradeClose::test_exit_fields_populated PASSED [ 63%]
tests/backtest/test_models.py::TestTradeClose::test_sell_profit PASSED   [ 63%]
tests/backtest/test_models.py::TestTradeClose::test_sell_loss PASSED     [ 64%]
tests/backtest/test_models.py::TestTradeClose::test_sell_breakeven PASSED [ 64%]
tests/backtest/test_models.py::TestTradeClose::test_buy_profit PASSED    [ 65%]
tests/backtest/test_models.py::TestTradeClose::test_buy_loss PASSED      [ 65%]
tests/backtest/test_models.py::TestTradeClose::test_pnl_scales_with_qty PASSED [ 65%]
tests/backtest/test_models.py::TestTradeClose::test_no_transaction_cost_by_default PASSED [ 66%]
tests/backtest/test_models.py::TestTradeClose::test_transaction_cost_calculated PASSED [ 66%]
tests/backtest/test_models.py::TestTradeClose::test_net_pnl_equals_gross_minus_cost PASSED [ 67%]
tests/backtest/test_models.py::TestTradeClose::test_net_pnl_sell_profit_with_cost PASSED [ 67%]
tests/backtest/test_models.py::TestTradeClose::test_transaction_cost_scales_with_qty PASSED [ 68%]
tests/backtest/test_models.py::TestTradeClose::test_entry_exit_index_preserved PASSED [ 68%]
tests/backtest/test_models.py::TestTradeToDict::test_to_dict_has_required_keys PASSED [ 68%]
tests/backtest/test_models.py::TestTradeToDict::test_to_dict_values_correct PASSED [ 69%]
tests/backtest/test_models.py::TestTradeToDict::test_to_dict_includes_metadata PASSED [ 69%]
tests/backtest/test_models.py::TestTradeToDict::test_to_dict_open_trade PASSED [ 70%]
tests/backtest/test_strategy.py::TestStrategySAdd::test_returns_leg PASSED [ 70%]
tests/backtest/test_strategy.py::TestStrategySAdd::test_instrument_set_correctly PASSED [ 70%]
tests/backtest/test_strategy.py::TestStrategySAdd::test_side_and_qty PASSED [ 71%]
tests/backtest/test_strategy.py::TestStrategySAdd::test_default_qty_is_one PASSED [ 71%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_returns_dict_on_success PASSED [ 72%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_returns_none_when_any_leg_stale PASSED [ 72%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_returns_none_when_all_legs_stale PASSED [ 72%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_returns_none_when_no_price PASSED [ 73%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_trade_entry_price_set PASSED [ 73%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_trade_label_is_auto_key PASSED [ 74%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_trade_cycle_set_from_current_cycle PASSED [ 74%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_trade_tick_and_index_recorded PASSED [ 75%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_positions_populated PASSED [ 75%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_state_transitions_idle_to_active PASSED [ 75%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_state_stays_active_on_second_fill PASSED [ 76%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_no_state_change_on_failed_fill PASSED [ 76%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_duplicate_auto_key_raises_value_error PASSED [ 77%]
tests/backtest/test_strategy.py::TestTryFillListMode::test_key_collision_with_open_position_raises PASSED [ 77%]
tests/backtest/test_strategy.py::TestTryFillDictMode::test_user_keys_in_result PASSED [ 77%]
tests/backtest/test_strategy.py::TestTryFillDictMode::test_trade_label_matches_user_key PASSED [ 78%]
tests/backtest/test_strategy.py::TestTryFillDictMode::test_returns_none_when_any_stale PASSED [ 78%]
tests/backtest/test_strategy.py::TestTryFillDictMode::test_key_collision_with_position_raises PASSED [ 79%]
tests/backtest/test_strategy.py::TestTryFillDictMode::test_different_key_same_instrument_allowed_after_close PASSED [ 79%]
tests/backtest/test_strategy.py::TestOpenTrades::test_open_trades_empty_initially PASSED [ 79%]
tests/backtest/test_strategy.py::TestOpenTrades::test_open_trades_reflects_positions PASSED [ 80%]
tests/backtest/test_strategy.py::TestOpenTrades::test_open_trades_decreases_on_close PASSED [ 80%]
tests/backtest/test_strategy.py::TestCloseTrade::test_moves_to_closed_trades PASSED [ 81%]
tests/backtest/test_strategy.py::TestCloseTrade::test_removed_from_positions PASSED [ 81%]
tests/backtest/test_strategy.py::TestCloseTrade::test_trade_is_closed PASSED [ 81%]
tests/backtest/test_strategy.py::TestCloseTrade::test_exit_reason_set PASSED [ 82%]
tests/backtest/test_strategy.py::TestCloseTrade::test_returns_none_for_unknown_label PASSED [ 82%]
tests/backtest/test_strategy.py::TestCloseTrade::test_key_freed_after_close PASSED [ 83%]
tests/backtest/test_strategy.py::TestCloseAll::test_closes_all_positions PASSED [ 83%]
tests/backtest/test_strategy.py::TestCloseAll::test_all_moved_to_closed_trades PASSED [ 84%]
tests/backtest/test_strategy.py::TestCloseAll::test_noop_on_empty_positions PASSED [ 84%]
tests/backtest/test_strategy.py::TestCloseAll::test_reason_applied_to_all PASSED [ 84%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_done_state_is_noop PASSED [ 85%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_idle_with_can_enter_false_no_entry PASSED [ 85%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_idle_with_can_enter_true_calls_on_entry PASSED [ 86%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_successful_fill_transitions_to_active PASSED [ 86%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_failed_fill_stays_idle PASSED [ 86%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_failed_fill_retries_next_tick PASSED [ 87%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_active_state_calls_on_adjust PASSED [ 87%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_active_no_exit_signal PASSED [ 88%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_active_exit_condition_triggers_exit PASSED [ 88%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_exit_then_done_when_max_cycles_1 PASSED [ 88%]
tests/backtest/test_strategy.py::TestRunOneCycle::test_adjust_called_before_exit_check PASSED [ 89%]
tests/backtest/test_strategy.py::TestHandleCycleDone::test_single_cycle_marks_done PASSED [ 89%]
tests/backtest/test_strategy.py::TestHandleCycleDone::test_multi_cycle_resets_to_idle PASSED [ 90%]
tests/backtest/test_strategy.py::TestHandleCycleDone::test_last_cycle_marks_done PASSED [ 90%]
tests/backtest/test_strategy.py::TestHandleCycleDone::test_cycle_reset_clears_positions PASSED [ 90%]
tests/backtest/test_strategy.py::TestHandleCycleDone::test_cycle_reset_preserves_closed_trades PASSED [ 91%]
tests/backtest/test_strategy.py::TestEodForceClose::test_closes_all_open_positions PASSED [ 91%]
tests/backtest/test_strategy.py::TestEodForceClose::test_reason_is_eod_force PASSED [ 92%]
tests/backtest/test_strategy.py::TestEodForceClose::test_state_becomes_done PASSED [ 92%]
tests/backtest/test_strategy.py::TestEodForceClose::test_noop_on_empty_positions PASSED [ 93%]
tests/backtest/test_strategy.py::TestEodForceClose::test_force_close_from_any_state PASSED [ 93%]
tests/backtest/test_strategy.py::TestResetForNewDay::test_state_reset_to_idle PASSED [ 93%]
tests/backtest/test_strategy.py::TestResetForNewDay::test_cycle_reset_to_zero PASSED [ 94%]
tests/backtest/test_strategy.py::TestResetForNewDay::test_positions_cleared PASSED [ 94%]
tests/backtest/test_strategy.py::TestResetForNewDay::test_closed_trades_not_cleared PASSED [ 95%]
tests/backtest/test_strategy.py::TestLookupHelpers::test_get_closed_by_label PASSED [ 95%]
tests/backtest/test_strategy.py::TestLookupHelpers::test_get_closed_by_label_empty_if_none PASSED [ 95%]
tests/backtest/test_strategy.py::TestLookupHelpers::test_get_closed_by_instrument PASSED [ 96%]
tests/backtest/test_strategy.py::TestLookupHelpers::test_get_closed_by_instrument_multiple PASSED [ 96%]
tests/backtest/test_strategy.py::TestPositionSummary::test_empty_positions PASSED [ 97%]
tests/backtest/test_strategy.py::TestPositionSummary::test_sell_positions PASSED [ 97%]
tests/backtest/test_strategy.py::TestPositionSummary::test_qty_accumulates PASSED [ 97%]
tests/backtest/test_strategy.py::TestUnrealizedPnl::test_zero_when_no_positions PASSED [ 98%]
tests/backtest/test_strategy.py::TestUnrealizedPnl::test_sell_loss_when_price_rises PASSED [ 98%]
tests/backtest/test_strategy.py::TestUnrealizedPnl::test_sell_profit_when_price_falls PASSED [ 99%]
tests/backtest/test_strategy.py::TestUnrealizedPnl::test_buy_profit_when_price_rises PASSED [ 99%]
tests/backtest/test_strategy.py::TestUnrealizedPnl::test_fallback_to_entry_when_no_price PASSED [100%]

============================= 244 passed in 2.06s ==============================
