"""R616:只替换冻结策略函数,控制输入与执行器,追踪首次分支和路径差异。""" from copy import deepcopy from difflib import unified_diff from inspect import getsource PRICES = [100, 100, 101, 99] CONTROLS = {'data': PRICES, 'config': {'initial_cash': 1000, 'target_qty': 1}, 'engine': 'synthetic-next-price-v1'} def signal_v1(current, previous): return current >= previous def signal_v2(current, previous): return current > previous def check_controls(left, right): if left != right: raise ValueError('non-code controls changed') def run(strategy): cash, shares = CONTROLS['config']['initial_cash'], 0 signals, targets, fills = {}, [], [] for t in [1, 2]: signal = int(strategy(PRICES[t], PRICES[t-1])) signals[(t, 'S')] = signal target = signal * CONTROLS['config']['target_qty'] weight = target * PRICES[t] / (cash + shares * PRICES[t]) targets.append((t, target, weight)) qty = target - shares if qty: fills.append((t+1, qty, PRICES[t+1])) cash -= qty * PRICES[t+1] shares = target return {'signals': signals, 'targets': targets, 'fills': fills, 'equity': cash + shares * PRICES[-1]} def first_signal_difference(left, right): for key in sorted(left.keys() | right.keys()): if key not in left or key not in right: return {'status': 'missing_record', 'key': key} if left[key] != right[key]: return {'status': 'changed', 'key': key, 'old': left[key], 'new': right[key]} return None check_controls(CONTROLS, deepcopy(CONTROLS)) a, b = run(signal_v1), run(signal_v2) first = first_signal_difference(a['signals'], b['signals']) assert first == {'status': 'changed', 'key': (1, 'S'), 'old': 1, 'new': 0} assert a['fills'] == [(2, 1, 101)] and b['fills'] == [(3, 1, 99)] assert a['equity'] == 998 and b['equity'] == 1000 assert a['targets'][0][2] == .1 and b['targets'][0][2] == 0 assert a['signals'][(2,'S')] == b['signals'][(2,'S')] == 1 patch = ''.join(unified_diff(getsource(signal_v1).splitlines(True), getsource(signal_v2).splitlines(True), fromfile='v1', tofile='v2')) assert '- return current >= previous' in patch assert '+ return current > previous' in patch reordered = dict(reversed(list(a['signals'].items()))) assert first_signal_difference(a['signals'], reordered) is None missing = dict(a['signals']); del missing[(2,'S')] assert first_signal_difference(a['signals'], missing)['status'] == 'missing_record' changed = deepcopy(CONTROLS); changed['config']['target_qty'] = 2 try: check_controls(CONTROLS, changed) except ValueError: pass else: raise AssertionError('mixed configuration accepted') print('first_signal_session=1 security=S branch=equality old=1 new=0') print('first_target_weight=0.1,0.0 old_fills=' + str(a['fills']) + ' new_fills=' + str(b['fills'])) print('final_equity=' + str((a['equity'],b['equity'])) + ' later_fill_difference=position_path') print('row_reorder=equal missing_record=explicit mixed_controls=rejected')