"""规则到实际数据/模拟器能力逐项裁决,拒绝不支持要求而非隐藏替换。""" import json from math import isfinite capabilities = {'frequency': '1d', 'fields': {'open', 'high', 'low', 'close', 'volume'}, 'short': False, 'same_day_resale': False, 'queue_replay': False, 'historical_fundamentals': False} def adjudicate(requirements, actual=capabilities): table = [] for rule in requirements: if rule == 'close_above_trailing_mean': supported = actual['frequency'] == '1d' and 'close' in actual['fields'] status = 'supported_in_fixture' if supported else 'requires_external_data' evidence = 'daily close and trailing calculation required' elif rule == 'next_open_long': supported = actual['frequency'] == '1d' and 'open' in actual['fields'] status = 'supported_in_fixture' if supported else 'requires_external_data' evidence = 'daily open plus implemented cash-long fixture matcher required' elif rule == 'intraday_same_day_roundtrip': status, evidence = 'reject', '1d bars lack intraday order; cash-stock resale capability false' elif rule == 'short_without_inventory': status, evidence = 'reject', 'short capability false; no borrow/inventory model' elif rule == 'queue_fill_at_limit': status, evidence = 'requires_model_and_data', 'no order-book history or queue replay' elif rule == 'point_in_time_earnings': status, evidence = 'requires_external_data', 'no historical fundamentals or availability fields' else: status, evidence = 'reject', 'unknown rule' table.append({'rule': rule, 'status': status, 'evidence': evidence}) return table requested = ['close_above_trailing_mean', 'next_open_long', 'intraday_same_day_roundtrip', 'short_without_inventory', 'queue_fill_at_limit', 'point_in_time_earnings'] report = adjudicate(requested) assert [r['status'] for r in report] == ['supported_in_fixture', 'supported_in_fixture', 'reject', 'reject', 'requires_model_and_data', 'requires_external_data'] revised = ['close_above_trailing_mean', 'next_open_long'] assert all(r['status'] == 'supported_in_fixture' for r in adjudicate(revised)) assert not all(r['status'] == 'supported_in_fixture' for r in report) assert adjudicate(['unknown_feature'])[0]['status'] == 'reject' assert adjudicate(['next_open_long'], dict(capabilities, fields={'close'}))[0]['status'] == 'requires_external_data' class FixtureMatcher: def __init__(self): self.cash, self.quantity, self.entry_session = 1000, 0, None def execute(self, side, quantity, price, session, mode='next_open'): if mode != 'next_open': raise ValueError('unsupported_execution_mode') if side not in ('buy', 'sell') or type(quantity) is not int or quantity <= 0: raise ValueError('invalid_order') if (type(price) not in (int, float) or not isfinite(price) or price <= 0 or type(session) is not int or session < 0): raise ValueError('invalid_price_or_session') if side == 'sell' and quantity > self.quantity: raise ValueError('short_or_missing_inventory') if side == 'sell' and session == self.entry_session: raise ValueError('same_session_resale_blocked') if side == 'buy': if quantity * price + 1 > self.cash: raise ValueError('cash') self.cash -= quantity * price + 1 self.quantity += quantity self.entry_session = session else: self.cash += quantity * price - 1 self.quantity -= quantity matcher = FixtureMatcher() matcher.execute('buy', 40, 10, 0) assert matcher.cash == 599 and matcher.quantity == 40 rejections = [] for args in [('sell', 40, 10, 0), ('sell', 50, 10, 1), ('buy', 1, 10, 1, 'queue_replay')]: before = (matcher.cash, matcher.quantity) try: matcher.execute(*args) except ValueError as error: rejections.append(str(error)) else: raise AssertionError('不支持执行要求必须实际拒绝') assert (matcher.cash, matcher.quantity) == before assert len(rejections) == 3 for args in [('BUY', 1, 10, 1), ('buy', 0, 10, 1), ('buy', True, 10, 1), ('buy', 1, float('nan'), 1), ('buy', 1, float('inf'), 1), ('buy', 1, 0, 1)]: before = (matcher.cash, matcher.quantity) try: matcher.execute(*args) except ValueError: pass else: raise AssertionError('非法订单不得改变账户') assert (matcher.cash, matcher.quantity) == before closes = [10, 10, 12] signal = int(closes[-1] > sum(closes)/3) assert signal == 1 print(json.dumps({'capabilities': {**capabilities, 'fields': sorted(capabilities['fields'])}, 'requested_decisions': report, 'revised_named_spec': 'daily_cash_long_next_open_only', 'revised_rules': revised, 'revised_sample_signal': signal, 'actual_matcher_rejections': rejections, 'fixture_cash': matcher.cash, 'fixture_quantity': matcher.quantity, 'original_request_fully_supported': False, 'product_verified': False}))