"""R629:同初态、同价格的日历/阈值政策;触发与未成交分开。""" from math import isfinite,isclose PRICES={'A':[100,130,140,120,100,110],'B':[100]*6} def run(policy): if policy not in {'calendar','threshold'}:raise ValueError('unknown policy') cash=0.;shares={'A':5.,'B':5.};ledger=[];costs=0.;traded=0.;streak=longest=0 for t in range(1,6): p={s:PRICES[s][t] for s in shares} before=cash+sum(shares[s]*p[s] for s in shares) assert isfinite(before) and before>0 deviation=max(abs(shares[s]*p[s]/before-.5) for s in shares) trigger=t in [3,5] if policy=='calendar' else deviation>=.05 status='no_trigger' if trigger and t==1:status='blocked_market' elif trigger: old={s:shares[s]*p[s] for s in shares};lo,hi=0.,before for _ in range(100): mid=(lo+hi)/2;fee=.001*sum(abs(mid*.5-old[s]) for s in shares) if mid+fee>before:hi=mid else:lo=mid invested=(lo+hi)/2;target={s:invested*.5/p[s] for s in shares} amount=sum(abs(target[s]-shares[s])*p[s] for s in shares);fee=.001*amount cash=before-sum(target[s]*p[s] for s in shares)-fee;shares=target assert cash>=-1e-8 assert isclose(cash+sum(shares[s]*p[s] for s in shares),before-fee,rel_tol=0,abs_tol=1e-8) traded+=amount;costs+=fee;status='executed' after=cash+sum(shares[s]*p[s] for s in shares) post=max(abs(shares[s]*p[s]/after-.5) for s in shares) streak=streak+1 if post>=.05 else 0;longest=max(longest,streak) ledger.append({'session':t,'trigger':trigger,'status':status,'pre_deviation':deviation,'post_deviation':post,'equity':after}) return {'ending':ledger[-1]['equity'],'cost':costs,'turnover':traded/1000,'longest_post_breach':longest,'events':ledger} c=run('calendar');t=run('threshold') assert isclose(c['ending'],1054.025004,rel_tol=0,abs_tol=1e-6) assert isclose(t['ending'],1079.640030,rel_tol=0,abs_tol=1e-6) assert isclose(c['cost'],.145829,rel_tol=0,abs_tol=1e-6) assert isclose(t['cost'],.371400,rel_tol=0,abs_tol=1e-6) assert [r['session'] for r in c['events'] if r['status']=='executed']==[3,5] assert [r['session'] for r in t['events'] if r['status']=='executed']==[2,4] assert t['events'][0]['status']=='blocked_market' and t['events'][0]['trigger'] assert c['longest_post_breach']==2 and t['longest_post_breach']==1 for label,result in [('calendar',c),('threshold',t)]: print(label+' ending='+format(result['ending'],'.6f')+' cost='+format(result['cost'],'.6f')+' turnover='+format(result['turnover'],'.6f')+' longest_post_breach='+str(result['longest_post_breach'])) print(label+' statuses='+str([(r['session'],r['status']) for r in result['events']]))