Portfolio Rebalace Notifier

A place to talk about speculative investing ideas for the optional Variable Portfolio

Moderator: Global Moderator

Post Reply
User avatar
MWKXJ
Senior Member
Senior Member
Posts: 126
Joined: Fri Jun 15, 2012 4:33 pm

Portfolio Rebalace Notifier

Post by MWKXJ » Wed Aug 02, 2017 7:57 pm

For any who may be interested, below is a Rube Goldberg solution to the "problem" of receiving rebalance e-mail and text notifications.

1. Create a "MetaARPA" account at SDF.org. (go for it; it's useful for accessing elinks at work via Putty in any case).
2. Create a "~/bin" folder and change directories to it.
3. Using vi, create the following script, naming it "roth_rebalancer.ksh93" (or "401k_", "457b_", etc.):

Code: Select all

#!/usr/pkg/bin/ksh93

DEBUG=false
STARTIN=/sdf/arpa/<PATHTOYOURHOMEDIR>/bin
PORTFOLIO=$STARTIN/roth.portfolio
UPPER_REBALANCE_BAND=1.3
LOWER_REBALANCE_BAND=0.7
CURL=/usr/pkg/bin/curl
SRC="http://download.finance.yahoo.com/d/quotes.csv"
MUTT=/usr/pkg/bin/mutt
NOTIFICATION_EMAIL1=<YOURPHONENUMBER>@vtext.com
NOTIFICATION_EMAIL2=<YOURWORKEMAIL>
NOTIFICATION_EMAIL3=<YOURHOMEEMAIL>

function get_query {
        typeset -n ticker="$1"
        print -rn "$SRC?s=$(print -rn $ticker)&f=l1&e=.csv"
}

function get_quote {
        typeset -n ticker="$1"
        print -rn $($CURL -X GET -s $(get_query ticker))
}

body=''

# First pass, sum the portfolio value.
total=0.0
while read ticker shares; do
        quote=$(get_quote ticker)
        let total=$total+$quote*$shares
done <$PORTFOLIO

body=$body'--------------------------------------------
'
body=$body"Total Portfolio Value: $total
"

# Second pass, calculate whether any position is outside of balancing bands.
notify=false
while read ticker shares target; do
        quote=$(get_quote ticker)
        let value=$quote*$shares
        let target_value=$total*$target
        let lower_bound=$LOWER_REBALANCE_BAND*$target_value
        let upper_bound=$UPPER_REBALANCE_BAND*$target_value
        body=$body'--------------------------------------------
'
        body=$body"Ticker: $ticker
"
        body=$body"Value: $value
"
        body=$body"Target: $target_value
"
        body=$body"Lower Band: $lower_bound
"
        body=$body"Upper Band: $upper_bound
"
        let pct_of_port=$value/$total
        body=$body"Cur Pct of Port: $pct_of_port
"
        body=$body"Tgt Pct of Port: $target
"
        if ((value <= lower_bound || value >= upper_bound)); then
                notify=true
                body=$body"Value outside of range.
"
                if $DEBUG; then
                        print -u2 "$body"
                fi
        else
                # TODO: Periodically collect statistics.
                body=$body"Value within range.
"
                if $DEBUG; then
                        print -u2 "$body"
                fi
        fi
done <$PORTFOLIO

if $notify; then
        # TODO: Attach trendline report using troff's 'grap' package.
        if $DEBUG; then
                print -u2 "Sending e-mail notification."
        fi
        $MUTT -s 'Portfolio Rebalance' $NOTIFICATION_EMAIL1 <<EOF
$body
EOF
        $MUTT -s 'Portfolio Rebalance' $NOTIFICATION_EMAIL2 <<EOF
$body
EOF
        $MUTT -s 'Portfolio Rebalance' $NOTIFICATION_EMAIL3 <<EOF
$body
EOF
fi
...note the upper and lower rebalance band are set to +30% and -30%, respectively. Edit the "UPPER_REBALANCE_BAND" and "LOWER_REBALANCE_BAND" variables to taste.

4. Make the script executable with the following command: "chmod 700 roth_rebalancer.ksh93"
5. Using vi, create the following file, naming it "roth.portfolio" (or "401k." "457b.", etc.):

Code: Select all

QLENX   3920    0.5
AUENX   1467    0.25
TMF     1077    0.205
TQQQ    44      0.045
...the fields should be separated by tab and represent 1) the ticker, 2) the shares held, and 3) the target allocation.

6. Run "mkcron".
7. Type "edit".
8. Enter the following:

Code: Select all

1:5,35 13-21 * * 1-5 /sdf/arpa/<PATHTOYOURHOMEDIR>/bin/roth_rebalancer.ksh93
...note that without specifying a timezone in the crontab file the hours will be relative to the server, which is UTC. In the preceding example notices are run at 5 and 35 minutes past the hour, 1:00 through 9:00 p.m. UTC (9:00 a.m. through 5:00 p.m. Eastern), Monday through Friday.

9. Type "sync".
10. Type "quit".

Provided everything is working correctly, notification will be sent twice an hour if any of the positions are outside of their rebalance bands. Debug the script with "DEBUG=true". Force a notification by playing with the targets in the ".portfolio" file. Below is a sample of the notification body:
--------------------------------------------
Total Portfolio Value: 108890.73000000001
--------------------------------------------
Ticker: QLENX
Value: 55115.2000000000044
Target: 27222.682499999999
Lower Band: 19055.8777499999997
Upper Band: 35389.4872499999983
Cur Pct of Port: 0.506151441908783273
Tgt Pct of Port: 0.25
Value outside of range.
--------------------------------------------
Ticker: AUENX
Value: 26361.989999999998
Target: 54445.364999999998
Lower Band: 38111.7554999999993
Upper Band: 70778.9744999999966
Cur Pct of Port: 0.242095814767703388
Tgt Pct of Port: 0.50
Value outside of range.
--------------------------------------------
Ticker: TMF
Value: 22509.2999999999993
Target: 22322.5996499999965
Lower Band: 15625.8197549999968
Upper Band: 29019.3795449999961
Cur Pct of Port: 0.206714566060857541
Tgt Pct of Port: 0.205
Value within range.
--------------------------------------------
Ticker: TQQQ
Value: 4904.23999999999978
Target: 4900.08284999999978
Lower Band: 3430.05799499999966
Upper Band: 6370.10770500000035
Cur Pct of Port: 0.0450381772626558785
Tgt Pct of Port: 0.045
Value within range.
Update the ".portfolio" input as dividends are reinvested, purchases are made, etc. Improve the script, or, use one myriad of other languages available on sdf.org to craft your own.

Good luck.
User avatar
Kriegsspiel
Executive Member
Executive Member
Posts: 4052
Joined: Sun Sep 16, 2012 5:28 pm

Re: Portfolio Rebalace Notifier

Post by Kriegsspiel » Thu Aug 03, 2017 6:49 am

Holy shit I don't know how to use computers.
User avatar
dualstow
Executive Member
Executive Member
Posts: 14225
Joined: Wed Oct 27, 2010 10:18 am
Location: synagogue of Satan
Contact:

Re: Portfolio Rebalace Notifier

Post by dualstow » Thu Aug 03, 2017 12:19 pm

Neat!
RIP Marcello Gandini
User avatar
MWKXJ
Senior Member
Senior Member
Posts: 126
Joined: Fri Jun 15, 2012 4:33 pm

Re: Portfolio Rebalace Notifier

Post by MWKXJ » Thu Aug 03, 2017 3:26 pm

Below is a variation of the script which employs Swedroe's 5/25 rule to calculate rebalancing bands (assuming I understood the rule correctly):

Code: Select all

#!/usr/pkg/bin/ksh93

DEBUG=false
STARTIN=/sdf/arpa/<PATHTOYOURHOMEDIR>/bin
PORTFOLIO=$STARTIN/roth.portfolio
SWEDROE_THRESHOLD=.2
SWEDROE_RELATIVE_UPPER_REBALANCE_BAND=1.05
SWEDROE_RELATIVE_LOWER_REBALANCE_BAND=0.95
SWEDROE_ABSOLUTE_UPPER_REBALANCE_BAND=1.25
SWEDROE_ABSOLUTE_LOWER_REBALANCE_BAND=0.75
CURL=/usr/pkg/bin/curl
MUTT=/usr/pkg/bin/mutt
YAHOO="http://download.finance.yahoo.com/d/quotes.csv"
NOTIFICATION_EMAIL1=<YOURPHONENUMBER>@vtext.com
NOTIFICATION_EMAIL2=<YOURWORKEMAIL>
NOTIFICATION_EMAIL3=<YOURHOEMEMAIL>

function get_query {
	typeset -n ticker="$1"
	print -rn "$YAHOO?s=$(print -rn $ticker)&f=l1&e=.csv"
}

function get_quote {
	typeset -n ticker="$1"
	print -rn $($CURL -X GET -s $(get_query ticker))
}

body=''

# First pass, sum the portfolio value.
total=0.0
while read ticker shares; do
	quote=$(get_quote ticker)
	let total=$total+$quote*$shares
done <$PORTFOLIO

body=$body'--------------------------------------------
'
body=$body"Total Portfolio Value: $total
"

# Second pass, calculate whether any position is outside of balancing bands.
notify=false
while read ticker shares target; do
	body=$body'--------------------------------------------
'
	body=$body"Ticker: $ticker
"
	quote=$(get_quote ticker)
	let value=$quote*$shares
	let target_value=$total*$target
	body=$body"Current Value: $value
"
	body=$body"Current Shares: $shares
"
	body=$body"Target Value: $target_value
"
	let target_shares="int(target_value/quote)"
	body=$body"Target Shares: $target_shares
"
	# Follow Swedroe's 5/25 rule.
	if ((target >= $SWEDROE_THRESHOLD)); then
	# Use smaller percentage per Swedroe.
		# Note: The reported band percentage assumes that the upper and lower 
		#       are the same.
		let band_pct="int((SWEDROE_RELATIVE_UPPER_REBALANCE_BAND-1)*100)"
		body=$body"Using Swedroe $band_pct% rebalance band:
"
		let lower_bound=$SWEDROE_RELATIVE_LOWER_REBALANCE_BAND*$target_value
		let upper_bound=$SWEDROE_RELATIVE_UPPER_REBALANCE_BAND*$target_value
	else
		# Use larger percentage per Swedroe.
		# Note: The reported band percentage assumes that the upper and lower 
		#       band are the same.
		let band_pct="int((SWEDROE_ABSOLUTE_UPPER_REBALANCE_BAND-1)*100)"
		body=$body"Using Swedroe $band_pct% rebalance band:
"
		let lower_bound=$SWEDROE_ABSOLUTE_LOWER_REBALANCE_BAND*$target_value
		let upper_bound=$SWEDROE_ABSOLUTE_UPPER_REBALANCE_BAND*$target_value
	fi
	body=$body"Lower Band: $lower_bound
"
	body=$body"Upper Band: $upper_bound
"
	let pct_of_port=$value/$total
	body=$body"Cur Pct of Port: $pct_of_port
"
	body=$body"Tgt Pct of Port: $target
"
	if ((value <= lower_bound || value >= upper_bound)); then
		notify=true
		body=$body"Value outside of range.
"
		if $DEBUG; then
			print -u2 "$body"
		fi
	else
		# TODO: Periodically collect statistics.
		body=$body"Value within range.
"
		if $DEBUG; then
			print -u2 "$body"
		fi
	fi
done <$PORTFOLIO

if $notify; then
	# TODO: Attach trendline report using troff's 'grap' package
	#       and collected statistics.
	if $DEBUG; then
		print -u2 "Sending e-mail notification."
	fi
	$MUTT -s 'Portfolio Rebalance' $NOTIFICATION_EMAIL1 <<EOF
$body
EOF
	$MUTT -s 'Portfolio Rebalance' $NOTIFICATION_EMAIL2 <<EOF
$body
EOF
	$MUTT -s 'Portfolio Rebalance' $NOTIFICATION_EMAIL3 <<EOF
$body
EOF
fi
Sample notification e-mail:
--------------------------------------------
Total Portfolio Value: 109561.279999999999
--------------------------------------------
Ticker: QLENX
Current Value: 55115.2000000000044
Current Shares: 3920
Target Value: 54780.6399999999994
Target Shares: 3896
Using Swedroe 5% rebalance band:
Lower Band: 52041.6080000000002
Upper Band: 57519.6719999999987
Cur Pct of Port: 0.50305363354645003
Tgt Pct of Port: 0.5
Value within range.
--------------------------------------------
Ticker: AUENX
Current Value: 26361.989999999998
Current Shares: 1467
Target Value: 27390.3199999999997
Target Shares: 1524
Using Swedroe 5% rebalance band:
Lower Band: 26020.8040000000001
Upper Band: 28759.8359999999993
Cur Pct of Port: 0.240614111116628093
Tgt Pct of Port: 0.25
Value within range.
--------------------------------------------
Ticker: TMF
Current Value: 23230.8899999999994
Current Shares: 1077
Target Value: 22460.0623999999989
Target Shares: 1041
Using Swedroe 5% rebalance band:
Lower Band: 21337.0592799999977
Upper Band: 23583.0655200000001
Cur Pct of Port: 0.212035584104165276
Tgt Pct of Port: 0.205
Value within range.
--------------------------------------------
Ticker: TQQQ
Current Value: 4853.19999999999982
Current Shares: 44
Target Value: 4930.25759999999991
Target Shares: 44
Using Swedroe 25% rebalance band:
Lower Band: 3697.69319999999971
Upper Band: 6162.82200000000012
Cur Pct of Port: 0.0442966712327566814
Tgt Pct of Port: 0.045
Value within range.
User avatar
foglifter
Executive Member
Executive Member
Posts: 634
Joined: Tue Apr 27, 2010 5:37 pm
Location: The Golden State

Re: Portfolio Rebalace Notifier

Post by foglifter » Thu Aug 03, 2017 3:42 pm

I feel like I'm missing something here... why do we need to mess with Linux?

I have my Google sheets with conditional formatting, so I know I need to rebalance if the cell turns red. I could add a script that would run daily/hourly/whatever and send me rebalancing alerts, but so far rebalancing hasn't been such a frequent event.
User avatar
dualstow
Executive Member
Executive Member
Posts: 14225
Joined: Wed Oct 27, 2010 10:18 am
Location: synagogue of Satan
Contact:

Re: Portfolio Rebalace Notifier

Post by dualstow » Thu Aug 03, 2017 3:46 pm

foglifter wrote:I feel like I'm missing something here... why do we need to mess with Linux?
I think it's so you really don't have to look. You don't even have to check to see if the cells turn red.
Plus, it's a pretty cool exercise.
RIP Marcello Gandini
User avatar
foglifter
Executive Member
Executive Member
Posts: 634
Joined: Tue Apr 27, 2010 5:37 pm
Location: The Golden State

Re: Portfolio Rebalace Notifier

Post by foglifter » Thu Aug 03, 2017 3:57 pm

dualstow wrote:
foglifter wrote:I feel like I'm missing something here... why do we need to mess with Linux?
I think it's so you really don't have to look. You don't even have to check to see if the cells turn red.
Plus, it's a pretty cool exercise.
Certainly agree on the coolness factor. I must be too tired of dealing with computers professionally every day. :D
User avatar
MWKXJ
Senior Member
Senior Member
Posts: 126
Joined: Fri Jun 15, 2012 4:33 pm

Re: Portfolio Rebalace Notifier

Post by MWKXJ » Thu Aug 03, 2017 3:59 pm

foglifter wrote:I feel like I'm missing something here... why do we need to mess with Linux?

I have my Google sheets with conditional formatting, so I know I need to rebalance if the cell turns red. I could add a script that would run daily/hourly/whatever and send me rebalancing alerts, but so far rebalancing hasn't been such a frequent event.
I know, I know. It was mentioned at the outset that this is a Rube Goldberg approach. Personally, I'm attempting to send rebalance notifications with as little active spreadsheet or brokerage account monitoring as possible (though having to manually adjust for dividend reivestments and contributions diminishes its advantage here). Also, I just enjoy the thought of a BSD cron job on a timesharing system handling such a job.

To each their own, but Godspeed if any here end up using it or a variation.
User avatar
foglifter
Executive Member
Executive Member
Posts: 634
Joined: Tue Apr 27, 2010 5:37 pm
Location: The Golden State

Re: Portfolio Rebalace Notifier

Post by foglifter » Thu Aug 03, 2017 4:07 pm

MWKXJ wrote:
foglifter wrote:I feel like I'm missing something here... why do we need to mess with Linux?

I have my Google sheets with conditional formatting, so I know I need to rebalance if the cell turns red. I could add a script that would run daily/hourly/whatever and send me rebalancing alerts, but so far rebalancing hasn't been such a frequent event.
I know, I know. It was mentioned at the outset that this is a Rube Goldberg approach.
Ah, now I know what "Rube Goldberg machine" is. Thanks to your post I learned something new! :)
Gabe
Full Member
Full Member
Posts: 54
Joined: Tue Aug 23, 2011 12:46 pm

Re: Portfolio Rebalace Notifier

Post by Gabe » Fri Sep 22, 2017 11:06 am

This reminds me of something that's been on my to-do list for awhile... I've been sitting on the lazyfol.io and lazyfolio.com domains for a couple years now. If I were to throw together a slick-looking web app that let you define a custom portfolio with custom rebalancing bands that pinged you when they triggered and also conveniently calculated how many shares to buy/sell - would y'all sign up? It'd probably be free for awhile, but if a bunch of people started using it and/or I added SMS notifications I might start charging new users a small amount to at least cover the costs (even if I were only charging like $1/user/month, it'd help me get up to speed on Stripe integration which is something I've been wanting to learn).
Dmilligan
Junior Member
Junior Member
Posts: 14
Joined: Wed Dec 19, 2012 7:49 am

Re: Portfolio Rebalace Notifier

Post by Dmilligan » Fri Sep 22, 2017 11:48 am

would y'all sign up?
Yes. I would definitely be interested in something like this. In fact, I periodically search for notification tools like this and have never found one that would work satisfactorily with a Permanent Portfolio/Golden Butterfly. I would be willing to pay a small subscription fee for SMS functionality.
Post Reply