Skip to content

Commit 0d05ec2

Browse files
committed
Add rebalancer.py
1 parent 1d15a0a commit 0d05ec2

File tree

3 files changed

+120
-4
lines changed

3 files changed

+120
-4
lines changed

README.rst

+18-2
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,28 @@ portfolio_rebalance
3434
===================
3535

3636

37-
Add a short description here!
37+
Understand how to rebalance your UK Vanguard portfolio using switch procedures.
3838

3939

40-
A longer description of your project goes here...
40+
This file performs portfolio rebalancing calculations, presenting the results
41+
confluent with Vanguard Switch procedures. It _does not_ interact directly with
42+
your Vanguard account. For example, if you hold
43+
assets "A", "B", and "C" on Vanguard, each with total values in your
44+
portfolio of 2000, 3000, and 4000, respectively. By running:
45+
`rebalance A 2000 B 3000 C 4000`
46+
You will be presented with:
47+
`{'A': 1.0, 'B': 0.0, 'C': -0.25}`,
48+
indicating that you should sell 25% of "C", placing 100% of the sale
49+
into "A" and 0% into "B".
4150

4251

52+
Install and run
53+
===============
54+
55+
1. Ensure you have `pip` installed
56+
2. `pip install .`
57+
3. `rebalance <Asset A> <Total value of asset A in your portfolio> ... <Asset Z> <Total value of asset Z in your portfolio>
58+
4359
.. _pyscaffold-notes:
4460

4561
Note

setup.cfg

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ testing =
7272
# console_scripts =
7373
# script_name = portfolio_rebalance.module:function
7474
# For example:
75-
# console_scripts =
76-
# fibonacci = portfolio_rebalance.skeleton:run
75+
console_scripts =
76+
rebalance = portfolio_rebalance.rebalance:run
7777
# And any other entry points, for example:
7878
# pyscaffold.cli =
7979
# awesome = pyscaffoldext.awesome.extension:AwesomeExtension

src/portfolio_rebalance/rebalance.py

+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
This file performs portfolio rebalancing, presenting the results
3+
confluent with Vanguard Switch procedures. For example, if you hold
4+
assets "A", "B", and "C" on Vanguard, each with total values in your
5+
portfolio of 2000, 3000, and 4000, respectively. By running:
6+
`rebalance A 2000 B 3000 C 4000`
7+
You will be presented with:
8+
`{'A': 1.0, 'B': 0.0, 'C': -0.25}`,
9+
indicating that you should sell 25% of "C", placing 100% of the sale
10+
into "A" and 0% into "B".
11+
"""
12+
13+
import sys
14+
15+
from portfolio_rebalance import __version__
16+
17+
__author__ = "David Simmons"
18+
__copyright__ = "David Simmons"
19+
__license__ = "MIT"
20+
21+
22+
def rebalance(dict):
23+
"""Portfolio rebalancer
24+
25+
Args:
26+
kwargs (Dict): Dictionary of assets and total portfolio value
27+
28+
Returns:
29+
Dict: Dictionary of assets and percentage to be sold/bought
30+
"""
31+
total = 0.0
32+
for key, value in dict.items():
33+
total += value
34+
35+
rebalanced_asset_value = total / len(dict)
36+
rebalanced_assets = {}
37+
38+
for key, value in dict.items():
39+
rebalanced_assets[key] = rebalanced_asset_value / dict[key] - 1
40+
41+
value_of_buys = 0
42+
for key, value in rebalanced_assets.items():
43+
if value > 0:
44+
value_of_buys += value
45+
else:
46+
pass
47+
48+
for key, value in rebalanced_assets.items():
49+
if value > 0:
50+
print(value)
51+
rebalanced_assets[key] /= value_of_buys
52+
else:
53+
pass
54+
55+
return rebalanced_assets
56+
57+
def parse_args(args):
58+
"""Parse command line parameters
59+
60+
Args:
61+
args (List[str]): command line parameters as list of strings
62+
(for example ``["--help"]``).
63+
64+
Returns:
65+
:obj:`argparse.Namespace`: command line parameters namespace
66+
"""
67+
keys = []
68+
values = []
69+
for asset in args:
70+
try:
71+
is_float = float(asset)
72+
except ValueError:
73+
is_float = False
74+
if isinstance(asset, str) and not is_float:
75+
keys.append(asset)
76+
elif is_float:
77+
values.append(float(asset))
78+
else:
79+
raise Exception()
80+
if len(keys) != len(values):
81+
raise Exception()
82+
83+
assets = {}
84+
for idx, el in enumerate(keys):
85+
assets[el] = values[idx]
86+
87+
return assets
88+
89+
90+
def main(args):
91+
kwargs = parse_args(args)
92+
print(rebalance(kwargs))
93+
94+
95+
def run():
96+
main(sys.argv[1:])
97+
98+
99+
if __name__ == "__main__":
100+
run()

0 commit comments

Comments
 (0)