Optimize d in inverse space
@@ -1756,9 +1756,12 @@ def solveRiskyContribRebStage(solution_next,
# Get post-rebalancing assets the m_tilde, n_tilde.
m_tilde, n_tilde = rebalanceAssets(d_tiled, mNrm_tiled, nNrm_tiled, tau)
- # Now the marginals
- dvdm = dvdmFuncAdj_next(m_tilde, n_tilde)
- dvdn = dvdnFuncAdj_next(m_tilde, n_tilde)
+ # Now the marginals, in inverse space
+ dvdmNvrs = dvdmFuncAdj_next.cFunc(m_tilde, n_tilde)
+ dvdnNvrs = dvdnFuncAdj_next.cFunc(m_tilde, n_tilde)
+
+ # Pre-evaluate the inverse of (1+tau)
+ taxNvrs = uPinv(1+tau)
# Initialize
dOpt = np.ones_like(mNrm_tiled[0])*np.nan
@@ -1771,28 +1774,34 @@ def solveRiskyContribRebStage(solution_next,
# First check if dvdm(d=-1) > dvdn(d=-1). If so, withdrawing
# everything is optimal
- if dvdm[0,mInd,nInd] > (1+tau)*dvdn[0,mInd,nInd]:
+ # uPinv is a decreasing transformation so the inequality flips
+ if dvdmNvrs[0,mInd,nInd] < taxNvrs*dvdnNvrs[0,mInd,nInd]:
dOpt[mInd,nInd] = -1.
else:
# Next, check what happens at d == 0. This will determine which
# of d<0, d==0, d>0 is optimal.
- if (1+tau)*dvdn[zeroind,mInd,nInd] >= dvdm[zeroind,mInd,nInd] and dvdm[zeroind,mInd,nInd] >= dvdn[zeroind,mInd,nInd]:
+
+ # If dvdm passes through the wedge in dvdn generated by the
+ # tax, d==0 is optimal
+ if taxNvrs*dvdnNvrs[zeroind,mInd,nInd] <= dvdmNvrs[zeroind,mInd,nInd] and dvdmNvrs[zeroind,mInd,nInd] <= dvdnNvrs[zeroind,mInd,nInd]:
dOpt[mInd,nInd] = 0.
else:
- if dvdm[zeroind,mInd,nInd] > (1+tau)*dvdn[zeroind,mInd,nInd]:
+
+ # If dvdm(d=0) > dvdn(d=0) then withdrawing is optimal
+ if dvdmNvrs[zeroind,mInd,nInd] < taxNvrs*dvdnNvrs[zeroind,mInd,nInd]:
# The optimal d is negative
dinds = np.arange(0,zeroind+1)
- FOC = (1+tau)*dvdn[dinds, mInd, nInd] - dvdm[dinds, mInd, nInd]
+ FOC = taxNvrs*dvdnNvrs[dinds, mInd, nInd] - dvdmNvrs[dinds, mInd, nInd]
else:
# The optimal d is positive
dinds = np.arange(zeroind, d_N)
- FOC = dvdn[dinds, mInd, nInd] - dvdm[dinds, mInd, nInd]
+ FOC = dvdnNvrs[dinds, mInd, nInd] - dvdmNvrs[dinds, mInd, nInd]
- # Find first index at which FOC turns negative
- pos1 = np.argmax(FOC<0)
+ # Find first index at which FOC turns negative (inverse positive)
+ pos1 = np.argmax(FOC>0)
ind1 = dinds[pos1]
# Linearly approximate where the FOC crosses 0
