Created
March 6, 2017 16:43
-
-
Save synapticarbors/67e3a60032ba1c90c7f32cd3f00c4919 to your computer and use it in GitHub Desktop.
Example of allocating contribution to 3 funds based on desired target percents
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np\n", | |
"import scipy.optimize" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 42, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# Current investments\n", | |
"S = 9500.00 # US Stocks Indx Fund\n", | |
"F = 3250.00 # Foreign Stocks Indx Fund\n", | |
"B = 2250.00 # US Bond Indx Fund\n", | |
"\n", | |
"T = S + F + B # Total investment\n", | |
"\n", | |
"# Target percent allocations\n", | |
"P_S = 0.6375\n", | |
"P_F = 0.2125\n", | |
"P_B = 0.15\n", | |
"\n", | |
"T_d = 500.0 # Today's deposit" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 43, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"b = np.array([P_S*T - S, P_F*T - F, P_B*T - B])\n", | |
"A = np.array([[1 - P_S, -P_S, -P_S],\n", | |
" [-P_F, 1 - P_F, -P_F],\n", | |
" [-P_B, -P_B, 1 - P_B]])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 44, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"def f(x):\n", | |
" y = np.dot(A, x) - b\n", | |
" p1 = np.dot(y,y)\n", | |
" p2 = x.sum()\n", | |
" return p1\n", | |
"\n", | |
"# Constraint to ensure that all of the money is allocated\n", | |
"def scons(x):\n", | |
" return T_d - x.sum()\n", | |
"\n", | |
"cons = [{'type': 'eq', 'fun': scons}]\n", | |
"bnds = [(0, T_d), (0, T_d), (0, T_d)]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 45, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Current Allocations v Desired\n", | |
"US Stocks : 0.633 0.637\n", | |
"Foreign Stocks : 0.217 0.212\n", | |
"Bonds : 0.150 0.150\n" | |
] | |
} | |
], | |
"source": [ | |
"fmt_str = '{:20}: {:5.3f} {:5.3f}'\n", | |
"print 'Current Allocations v Desired'\n", | |
"print fmt_str.format('US Stocks', S / T, P_S)\n", | |
"print fmt_str.format('Foreign Stocks', F / T, P_F)\n", | |
"print fmt_str.format('Bonds', B / T, P_B)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 46, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Optimization terminated successfully. (Exit mode 0)\n", | |
" Current function value: 4.31773141557e-17\n", | |
" Iterations: 6\n", | |
" Function evaluations: 31\n", | |
" Gradient evaluations: 6\n" | |
] | |
} | |
], | |
"source": [ | |
"init_x = T_d * np.array([P_S, P_F, P_B])\n", | |
"\n", | |
"res = scipy.optimize.minimize(f, init_x, method='SLSQP', constraints=cons, \n", | |
" bounds=bnds, options={'disp': True, 'ftol': 1.0E-10,})\n", | |
"\n", | |
"# Amount to allocate for each indx fund\n", | |
"S_d = res.x[0]\n", | |
"F_d = res.x[1]\n", | |
"B_d = res.x[2]\n", | |
"\n", | |
"# Today's total investment\n", | |
"T_da = S_d + F_d + B_d" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 47, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Investments - init: optimized \n", | |
"US Stocks : 318.750 381.250\n", | |
"Foreign Stocks : 106.250 43.750\n", | |
"Bonds : 75.000 75.000\n", | |
"\n", | |
"Total new investment: 500.00 / 500.0\n", | |
"New total: 15500.0\n" | |
] | |
} | |
], | |
"source": [ | |
"fmt_str = '{:20}: {:>7.3f} {:>7.3f}'\n", | |
"\n", | |
"print 'Investments - init: optimized '\n", | |
"print fmt_str.format('US Stocks', init_x[0], S_d)\n", | |
"print fmt_str.format('Foreign Stocks', init_x[1], F_d)\n", | |
"print fmt_str.format('Bonds', init_x[2], B_d)\n", | |
"\n", | |
"print\n", | |
"print 'Total new investment: {:.2f} / {}'.format(T_da, T_d)\n", | |
"print 'New total: {}'.format(T + T_da)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 48, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"New Allocations v Desired\n", | |
"US Stocks : 0.6375 0.6375\n", | |
"Foreign Stocks : 0.2125 0.2125\n", | |
"Bonds : 0.1500 0.1500\n" | |
] | |
} | |
], | |
"source": [ | |
"fmt_str = '{:20}: {:5.4f} {:5.4f}'\n", | |
"print 'New Allocations v Desired'\n", | |
"print fmt_str.format('US Stocks', (S + S_d) / (T + T_da), P_S)\n", | |
"print fmt_str.format('Foreign Stocks', (F + F_d) / (T + T_da), P_F)\n", | |
"print fmt_str.format('Bonds', (B + B_d) / (T + T_da), P_B)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"anaconda-cloud": {}, | |
"kernelspec": { | |
"display_name": "Python [conda env:main]", | |
"language": "python", | |
"name": "conda-env-main-py" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.13" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment