"""R630:同日同额新资金,两种真实资金路径;不把入金算收益。""" from math import isfinite,isclose def run(mode): if mode not in {'new_cash','full'}:raise ValueError('unknown contribution policy') shares={'A':8.,'B':2.};cash=0.;fees=0.;sales=0.;market_gain=0.;ledger=[] previous={'A':100.,'B':100.} for session,prices,deposit in [(0,{'A':100.,'B':100.},100.),(1,{'A':120.,'B':100.},100.)]: if not isfinite(deposit) or deposit<0:raise ValueError('invalid contribution') market_gain+=sum(shares[s]*(prices[s]-previous[s]) for s in shares) before=cash+sum(shares[s]*prices[s] for s in shares);cash+=deposit;funded=before+deposit if mode=='new_cash': gaps={s:max(0,funded*.5-shares[s]*prices[s]) for s in shares} invested=cash/1.001 if sum(gaps.values()) else 0. buys={s:invested*gaps[s]/sum(gaps.values()) if sum(gaps.values()) else 0 for s in shares} fee=.001*sum(buys.values());cash-=sum(buys.values())+fee for s in shares:shares[s]+=buys[s]/prices[s] sold=0. else: old={s:shares[s]*prices[s] for s in shares};lo,hi=0.,funded for _ in range(100): mid=(lo+hi)/2;cost=.001*sum(abs(mid*.5-old[s]) for s in shares) if mid+cost>funded:hi=mid else:lo=mid invested=(lo+hi)/2;target={s:invested*.5/prices[s] for s in shares} sold=sum(max(0,shares[s]-target[s])*prices[s] for s in shares) amount=sum(abs(target[s]-shares[s])*prices[s] for s in shares);fee=.001*amount cash=funded-sum(target[s]*prices[s] for s in shares)-fee;shares=target fees+=fee;sales+=sold ending=cash+sum(shares[s]*prices[s] for s in shares) assert cash>=-1e-8 and isclose(ending,funded-fee,rel_tol=0,abs_tol=1e-8) ledger.append({'session':session,'deposit':deposit,'before':before,'ending':ending,'cash':cash,'fee':fee,'sold':sold,'A_weight':shares['A']*prices['A']/ending}) previous=prices assert isclose(ending,1000+200+market_gain-fees,rel_tol=0,abs_tol=1e-8) return {'ending':ending,'gain_excluding_contributions':ending-1200,'fees':fees,'sold':sales,'ledger':ledger} buy_only=run('new_cash');full=run('full') assert isclose(buy_only['ending'],1359.800200,rel_tol=0,abs_tol=1e-6) assert isclose(full['ending'],1309.230060,rel_tol=0,abs_tol=1e-6) assert isclose(buy_only['fees'],.199800,rel_tol=0,abs_tol=1e-6) assert isclose(full['fees'],.709940,rel_tol=0,abs_tol=1e-6) assert buy_only['sold']==0 and full['sold']>0 assert buy_only['ledger'][-1]['A_weight']>.7 assert isclose(full['ledger'][-1]['A_weight'],.5,rel_tol=0,abs_tol=1e-8) for label,result in [('new_cash',buy_only),('full',full)]: print(label+' ending='+format(result['ending'],'.6f')+' gain_excluding_200_contributions='+format(result['gain_excluding_contributions'],'.6f')+' fees='+format(result['fees'],'.6f')+' sold='+format(result['sold'],'.6f')) print(label+' A_weights='+str([round(r['A_weight'],6) for r in result['ledger']])+' deposits=[100,100]')