[gw2] darwin -- Python 3.12.12 /Users/cao/.pyenv/versions/3.12.12/bin/python3.12
tests/cli/test_sector_momentum_filter.py:2680: in test_batch_function_called_once_regardless_of_pick_count
    result = apply_filter(
        BuySafety  = <enum 'BuySafety'>
        SectorState = <enum 'SectorState'>
        apply_filter = <function apply_sector_momentum_filter at 0x122537600>
        date       = <class 'datetime.date'>
        mock_batch = <MagicMock name='calculate_all_sector_trend_stats_objects' id='4960426496'>
        mock_safe_stats = <MagicMock id='4959085840'>
        picks      = [{'_trend_state': 'Confirmed Trend', 'filter_reason': 'OK: XLV Safe', 'momentum_final_score': 0.05, 'sector': 'Healthc....}, {'_trend_state': 'Confirmed Trend', 'momentum_final_score': 0.08, 'sector': 'Consumer Cyclical', 'symbol': 'AMZN'}]
        self       = <test_sector_momentum_filter.TestTrendStatsIntegration object at 0x121e13e00>
rtrader/cli/trader_eod_core/services/log_formatting_service.py:1670: in apply_sector_momentum_filter
    assignment = resolve_sector_etf_with_assignment(symbol, trading_day, snapshot_dir=snap_dir)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        BuySafety  = <enum 'BuySafety'>
        CAUTION_WORSENING_BLOCK = True
        CHANNEL_REGIME_FILTER_ENABLED = False
        EXHAUSTION_FILTER_ENABLED = False
        INSTITUTIONAL_DISTRIBUTION_FILTER_ENABLED = True
        NEGATIVE_MOMENTUM_FILTER_ENABLED = False
        NEGATIVE_SCORE_FILTER_ENABLED = False
        OK_WORSENING_FILTER_ENABLED = False
        OPTIONS_BEARISH_THRESHOLD = 1.0
        OPTIONS_BULLISH_THRESHOLD = 1.0
        OPTIONS_SENTIMENT_ENABLED = True
        OVERHEATED_SECTOR_FILTER_ENABLED = False
        SECTOR_BREAKOUT_EXCEPTION_ENABLED = False
        SECTOR_BREAKOUT_LOOKBACK_DAYS = 1
        SECTOR_BREAKOUT_MIN_BREAKOUT_CONF = 1.0
        SECTOR_BREAKOUT_MIN_CORRELATION = 1.0
        SECTOR_BREAKOUT_MIN_MEMBERSHIP_CONF = 1.0
        SYMBOL_CROSS_CHECK_THRESHOLD = 1.0
        SectorState = <enum 'SectorState'>
        TREND_STATE_FILTER_ENABLED = True
        WEAK_SECTOR_EIS_OVERRIDE = 0.2
        _P13       = <class 'pathlib.Path'>
        _bearish_broad = ''
        _bearish_cp = None
        _capitulation = False
        _display_etf = 'XLY'
        _etf_trend_display = <MagicMock id='4959085840'>
        _in_bearish_family = False
        _load_sector_channel = <function apply_sector_momentum_filter.<locals>._load_sector_channel at 0x127907060>
        _market_defensive = False
        _nfs_base_r13 = '/tmp/nonexistent_nfs'
        _sector_channel_cache = {}
        _spy_dvr   = 0.0
        _spy_momentum_guard_enabled = True
        _spy_regime = ''
        _spy_ret10d = 0.0
        _spy_ret10d_threshold = 1.0
        _spy_rsi   = 50.0
        _spy_rsi_threshold = 1.0
        _spy_slope = 0.0
        _spy_snapshot_row = None
        _symbol_options_bearish = <function apply_sector_momentum_filter.<locals>._symbol_options_bearish at 0x127907880>
        assignment = SectorAssignment(etf='XLV', score=0.00, confidence=0.6, pass=3, hard='XLV')
        bearish_families = set()
        broad_etf  = 'XLV'
        calculate_all_sector_trend_stats_objects = <MagicMock name='calculate_all_sector_trend_stats_objects' id='4960426496'>
        cfg        = <MagicMock id='4960369504'>
        eis_value  = None
        etf_trend  = <MagicMock id='4959085840'>
        exempt_symbols = None
        json       = <module 'json' from '/Users/cao/.pyenv/versions/3.12.12/lib/python3.12/json/__init__.py'>
        market_stress_level = None
        matched_etf = 'XLV'
        pick       = {'_trend_state': 'Confirmed Trend', 'momentum_final_score': 0.08, 'sector': 'Consumer Cyclical', 'symbol': 'AMZN'}
        picks      = [{'_trend_state': 'Confirmed Trend', 'filter_reason': 'OK: XLV Safe', 'momentum_final_score': 0.05, 'sector': 'Healthc....}, {'_trend_state': 'Confirmed Trend', 'momentum_final_score': 0.08, 'sector': 'Consumer Cyclical', 'symbol': 'AMZN'}]
        primary_etf_for_filter = None
        resolve_sector_etf_with_assignment = <function resolve_sector_etf_with_assignment at 0x1225b8d60>
        result     = SectorMomentumFilterResult(filtered_picks=[{'symbol': 'JNJ', 'momentum_final_score': 0.05, 'sector': 'Healthcare', '_t...stribution=[], filtered_out_by_channel_regime={}, market_defensive=False, spy_momentum_guard=False, spy_regime_info='')
        sector_direction = None
        sector_momentum_data = None
        sector_options_sentiment = None
        snap_dir   = 'snapshots/2026-01-30'
        snap_dir_r13 = 'snapshots/2026-01-30'
        snap_path  = PosixPath('/tmp/nonexistent_nfs/minio-mirror/data/snapshots/2026-01-30/AMZN.json')
        snapshot_dir = None
        symbol     = 'AMZN'
        symbol_momentum = 0.08
        symbol_options_sentiment = None
        symbol_sectors = {'AMZN': 'Consumer Cyclical', 'JNJ': 'Healthcare', 'PFE': 'Healthcare'}
        trading_day = datetime.date(2026, 1, 30)
        trend_stats_cache = {'XLV': <MagicMock id='4959085840'>, 'XLY': <MagicMock id='4959085840'>}
        weak_sectors = set()
rtrader/services/soft_sector_service.py:1973: in resolve_sector_etf_with_assignment
    soft_sectors = _load_soft_sectors_from_snapshot(symbol, trading_day, snapshot_dir)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        AILabelRepository = <class 'rtrader.utils.ai_labeler.AILabelRepository'>
        age_days   = 89
        ai_label   = SectorAILabel(symbol='AMZN', labeled_etf='FDN', sector_name='Internet Index', reasoning="Amazon is primarily an online...ai', model_used='minimax/MiniMax-M2.1', confidence=0.85, labeled_at=datetime.datetime(2026, 2, 10, 14, 15, 49, 505000))
        broad_etf  = 'XLY'
        label_at   = datetime.datetime(2026, 2, 10, 14, 15, 49, 505000, tzinfo=datetime.timezone.utc)
        label_is_fresh = False
        max_age_days = 60
        snapshot_dir = 'snapshots/2026-01-30'
        symbol     = 'AMZN'
        trading_day = datetime.date(2026, 1, 30)
rtrader/services/soft_sector_service.py:1901: in _load_soft_sectors_from_snapshot
    status, text = read_text_with_status(snapshot_path)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        NFS_SNAPSHOTS_PATH = PosixPath('/Users/cao/mnt/silverssd/minio-mirror/data/snapshots')
        NfsReadStatus = <enum 'NfsReadStatus'>
        json       = <module 'json' from '/Users/cao/.pyenv/versions/3.12.12/lib/python3.12/json/__init__.py'>
        read_text_with_status = <function read_text_with_status at 0x122a956c0>
        snapshot_dir = 'snapshots/2026-01-30'
        snapshot_path = PosixPath('/Users/cao/mnt/silverssd/minio-mirror/data/snapshots/2026-01-30/AMZN.json')
        symbol     = 'AMZN'
        trading_day = datetime.date(2026, 1, 30)
rtrader/utils/nfs.py:271: in read_text_with_status
    minio_text = _read_from_minio(s3key)
                 ^^^^^^^^^^^^^^^^^^^^^^^
        path       = PosixPath('/Users/cao/mnt/silverssd/minio-mirror/data/snapshots/2026-01-30/AMZN.json')
        s3key      = 'snapshots/2026-01-30/AMZN.json'
        timeout    = 2.0
rtrader/utils/nfs.py:232: in _read_from_minio
    response = client.get_object(bucket_name="data", object_name=s3key)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        _is_minio_reachable = <function _is_minio_reachable at 0x1220b22a0>
        client     = <minio.api.Minio object at 0x12794bbc0>
        minio_client = <function minio_client at 0x1220b2660>
        s3key      = 'snapshots/2026-01-30/AMZN.json'
../.pyenv/versions/3.12.12/lib/python3.12/site-packages/minio/api.py:1257: in get_object
    return self._execute(
        bucket_name = 'data'
        extra_query_params = None
        headers    = {}
        length     = 0
        object_name = 'snapshots/2026-01-30/AMZN.json'
        offset     = 0
        request_headers = None
        self       = <minio.api.Minio object at 0x12794bbc0>
        ssec       = None
        version_id = None
../.pyenv/versions/3.12.12/lib/python3.12/site-packages/minio/api.py:444: in _execute
    return self._url_open(
        body       = None
        bucket_name = 'data'
        headers    = {}
        method     = 'GET'
        no_body_trace = False
        object_name = 'snapshots/2026-01-30/AMZN.json'
        preload_content = False
        query_params = None
        region     = 'us-east-1'
        self       = <minio.api.Minio object at 0x12794bbc0>
../.pyenv/versions/3.12.12/lib/python3.12/site-packages/minio/api.py:306: in _url_open
    response = self._http.urlopen(
        body       = None
        bucket_name = 'data'
        creds      = Credentials(access_key='minioadmin', secret_key='minioadmin', session_token=None, expiration=None)
        date       = datetime.datetime(2026, 5, 11, 4, 30, 35, 628641, tzinfo=datetime.timezone.utc)
        headers    = {'Authorization': 'AWS4-HMAC-SHA256 Credential=minioadmin/20260511/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz...m64) minio-py/7.2.20', 'x-amz-content-sha256': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', ...}
        http_headers = HTTPHeaderDict({'Host': 'testbox001:9000', 'User-Agent': 'MinIO (Darwin; arm64) minio-py/7.2.20', 'x-amz-content-sha25...ers=host;x-amz-content-sha256;x-amz-date, Signature=07347af4baf08e296994abb538ffe55a7c13180db7ab3bbd7275fc313da9d0cb'})
        key        = 'Authorization'
        method     = 'GET'
        no_body_trace = False
        object_name = 'snapshots/2026-01-30/AMZN.json'
        preload_content = False
        query_params = None
        region     = 'us-east-1'
        self       = <minio.api.Minio object at 0x12794bbc0>
        url        = SplitResult(scheme='http', netloc='testbox001:9000', path='/data/snapshots/2026-01-30/AMZN.json', query='', fragment='')
        value      = 'AWS4-HMAC-SHA256 Credential=minioadmin/20260511/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date, Signature=07347af4baf08e296994abb538ffe55a7c13180db7ab3bbd7275fc313da9d0cb'
../.pyenv/versions/3.12.12/lib/python3.12/site-packages/urllib3/poolmanager.py:457: in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        conn       = <urllib3.connectionpool.HTTPConnectionPool object at 0x12794bb00>
        kw         = {'assert_same_host': False, 'body': None, 'headers': HTTPHeaderDict({'Host': 'testbox001:9000', 'User-Agent': 'MinIO (...amz-date, Signature=07347af4baf08e296994abb538ffe55a7c13180db7ab3bbd7275fc313da9d0cb'}), 'preload_content': False, ...}
        method     = 'GET'
        redirect   = True
        self       = <urllib3.poolmanager.PoolManager object at 0x12794b8c0>
        u          = Url(scheme='http', auth=None, host='testbox001', port=9000, path='/data/snapshots/2026-01-30/AMZN.json', query=None, fragment=None)
        url        = 'http://testbox001:9000/data/snapshots/2026-01-30/AMZN.json'
../.pyenv/versions/3.12.12/lib/python3.12/site-packages/urllib3/connectionpool.py:787: in urlopen
    response = self._make_request(
        assert_same_host = False
        body       = None
        body_pos   = None
        chunked    = False
        clean_exit = False
        conn       = None
        decode_content = True
        destination_scheme = None
        err        = None
        headers    = HTTPHeaderDict({'Host': 'testbox001:9000', 'User-Agent': 'MinIO (Darwin; arm64) minio-py/7.2.20', 'x-amz-content-sha25...ers=host;x-amz-content-sha256;x-amz-date, Signature=07347af4baf08e296994abb538ffe55a7c13180db7ab3bbd7275fc313da9d0cb'})
        http_tunnel_required = False
        method     = 'GET'
        parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/data/snapshots/2026-01-30/AMZN.json', query=None, fragment=None)
        pool_timeout = None
        preload_content = False
        redirect   = False
        release_conn = False
        release_this_conn = True
        response_conn = <HTTPConnection(host='testbox001', port=9000) at 0x12794ae10>
        response_kw = {}
        retries    = Retry(total=10, connect=None, read=None, redirect=None, status=None)
        self       = <urllib3.connectionpool.HTTPConnectionPool object at 0x12794bb00>
        timeout    = <_TYPE_DEFAULT.token: -1>
        timeout_obj = Timeout(connect=10.0, read=60.0, total=120.0)
        url        = '/data/snapshots/2026-01-30/AMZN.json'
../.pyenv/versions/3.12.12/lib/python3.12/site-packages/urllib3/connectionpool.py:534: in _make_request
    response = conn.getresponse()
               ^^^^^^^^^^^^^^^^^^
        body       = None
        chunked    = False
        conn       = <HTTPConnection(host='testbox001', port=9000) at 0x12794ae10>
        decode_content = True
        enforce_content_length = True
        headers    = HTTPHeaderDict({'Host': 'testbox001:9000', 'User-Agent': 'MinIO (Darwin; arm64) minio-py/7.2.20', 'x-amz-content-sha25...ers=host;x-amz-content-sha256;x-amz-date, Signature=07347af4baf08e296994abb538ffe55a7c13180db7ab3bbd7275fc313da9d0cb'})
        method     = 'GET'
        preload_content = False
        read_timeout = 60.0
        response_conn = <HTTPConnection(host='testbox001', port=9000) at 0x12794ae10>
        retries    = Retry(total=10, connect=None, read=None, redirect=None, status=None)
        self       = <urllib3.connectionpool.HTTPConnectionPool object at 0x12794bb00>
        timeout    = Timeout(connect=10.0, read=60.0, total=120.0)
        timeout_obj = Timeout(connect=10.0, read=60.0, total=120.0)
        url        = '/data/snapshots/2026-01-30/AMZN.json'
../.pyenv/versions/3.12.12/lib/python3.12/site-packages/urllib3/connection.py:571: in getresponse
    httplib_response = super().getresponse()
                       ^^^^^^^^^^^^^^^^^^^^^
        HTTPResponse = <class 'urllib3.response.HTTPResponse'>
        __class__  = <class 'urllib3.connection.HTTPConnection'>
        _shutdown  = <built-in method shutdown of socket object at 0x127950bb0>
        resp_options = _ResponseOptions(request_method='GET', request_url='/data/snapshots/2026-01-30/AMZN.json', preload_content=False, decode_content=True, enforce_content_length=True)
        self       = <HTTPConnection(host='testbox001', port=9000) at 0x12794ae10>
../.pyenv/versions/3.12.12/lib/python3.12/http/client.py:1430: in getresponse
    response.begin()
        response   = <http.client.HTTPResponse object at 0x127a90550>
        self       = <HTTPConnection(host='testbox001', port=9000) at 0x12794ae10>
../.pyenv/versions/3.12.12/lib/python3.12/http/client.py:331: in begin
    version, status, reason = self._read_status()
                              ^^^^^^^^^^^^^^^^^^^
        self       = <http.client.HTTPResponse object at 0x127a90550>
../.pyenv/versions/3.12.12/lib/python3.12/http/client.py:292: in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        self       = <http.client.HTTPResponse object at 0x127a90550>
../.pyenv/versions/3.12.12/lib/python3.12/socket.py:720: in readinto
    return self._sock.recv_into(b)
           ^^^^^^^^^^^^^^^^^^^^^^^
E   Failed: Timeout (>60.0s) from pytest-timeout.
        b          = <memory at 0x1277bfe80>
        self       = <socket.SocketIO object at 0x127a7d6c0>
