Dollar cost averaging is designed to invest by reducing the risk of market timing. Use etrader and AWS to automatically invest a set amount on each trading day.
Dollar cost averaging (DCA) is a form of investing that attempts to reduce the risk of market timing. If someone has $10,000 to invest, they may be concerned the market is “ripe for a correction” or “may pullback over the next two years”. You always have someone predicting the next recession, including me. This can cause paralysis and prevent people from investing, keeping their positions in cash.
In my article about historical market performance, I discuss how important each year becomes over an investment timeline. Even investing on the eve of the Great Depression would have been a great investment over 30 years. That being said, it can be intimidating and nerve racking to put a large sum of money into the market at one time. Additionally, it does always feel like there is a recession coming right around the corner.
I personally fell victim to this from 2010 - 2014, which were great years to be in the market. By waiting on the sidelines, I limited my ability to capture the incredible power of compound interest. Dollar cost averaging is a great way to avoid the stress of deciding when to invest, because you invest incremental amounts over time. Over 30 years, the total impact might be relatively small, but if it prevents you from sitting on the sidelines then it’s value cannot be overstated.
Most brokerage firms offer automatic investing plans with Mutual Funds, fractional share trading is starting to grow in popularity, and robo advisors make it easy to invest when cash is deposited. All of these strategies are designed to help someone incrementally buy into the stock market. The one downside is that many of these programs have minimums that must be met, or spread out purchases by 2 or more weeks.
I personally wanted something better. Is there a way to perfect dollar cost averaging so that I could buy into the market every single day? Of course this could be done manually, but then I am left spending time everyday making decisions and entering trades. I wanted to find a way to automatically buy into the stock market every day. On down days, I am getting a deal and on up days, my previous day investment was already positive. Again, the impact over 30 years will be minimal, but the elimination of stress is priceless when leveraging a true “set it and forget it” investment strategy.
The ETRADE developer API offers a perfect solution to this problem, hence why I created the etrader package for R. While there are many trading APIs available, specifically through R (RobinHood, Alpaca, TD Ameritrade, Interactive Brokers), ETRADE offers the trifecta needed for the perfect trading API:
Unfortunately, nothing is truly perfect. Fully automating a trading
strategy with etrader
is much more difficult than the
others (see below for detailed instructions). Additionally, fractional
shares only exists for Mutual Funds, but ETRADE offers a large menu of
no transaction fee active and passive Mutual Funds that give more than
enough options to build a comprehensive portfolio to align with your
investment strategy.
Note: It is possible that after Schwab fully acquires TD
Ameritrade and rolls out fractional share trading more widely, then
rameritrade
would be a viable option if the API is
integrated. This outcome is still unknown as of 2020-11-22.
Before jumping into a fully
automated trading strategy, it is important to start with the basics
and get etrader
up and running. In my article on trading with
ramertrade, I cover the basics of the R programming language.
Assuming R is installed and you have an ETRADE brokerage account, the
steps below cover the process of registering for the API and logging
in.
ETRADE offers excellent documentation for the API, including a Getting Started Guide. A user will need to request keys to connect to the API. It is strongly advised to use both the sandbox and production keys. There are a few steps to obtain keys as shown in the documentation and below.
You will need to complete a couple questionnaires declaring your
intent. The etrader
package was built for an individual
user managing their own account, not a vendor, so the agreements should
not prevent someone from obtaining the necessary Key and Secret
tokens.
The etrader
package attempts to simplify the process for
logging onto ETRADE; however, the user will be required to enter their
user ID and password into a web browser to complete the authentication
process at least once a day.
The process below shows the log in process for a production token.
See the etrader
README guide
for instructions using the sandbox environment.
# Install and load etrader
install.packages('etrader')
# or
::install_github("exploringfinance/etrader")
devtoolslibrary(etrader)
# Retrieve ETRADE credentials from secure location
= readRDS('/home/rstudio/Secure/etrade_login.rds')
etkeys
# Enter the Key and Secret into etrader
= etrd_auth_credentials(etkeys$prod_key, etkeys$prod_secret)
etrade_cred
# Credentials are stored into R options locally on your computer, so are not required to be passed
# The next function will generate a URL for logging into ETRADE
etrd_auth_login_url()
This will automatically generate a pop up window for entering ETRADE
credentials. If already logged into, ETRADE you should go straight to
the screen below. Sometimes after logging in, the user is directed back
to the main ETRADE site where it says “Getting Started”. If this occurs,
use the link generated by etrd_auth_login_url()
to continue
the authentication process. The user will see a screen similar to the
one below. Press ‘Accept’ to generate a verification code.
Once the verification code has been generated. Pass it into
etrd_auth_access_token
as shown below. This will complete
the authentication process and enable the remaining etrader
functions. You only have about 5 minutes to complete the entire process.
It shouldn’t take more than a minute, but if it takes longer, you will
need to regenerate a login URL.
= etrd_auth_access_token(verif_code = 'XX123')
access_tok # Successful authorization. etrader functions are now enabled.
# Access tokens are saved by default into options so they don't have to be passed to each function.
# Save tokens for future use if needed
# This will be important during the automation step
saveRDS(access_tok, '/home/rstudio/Secure/etrade_access.rds')
# Confirm access by checking account list
etrd_account_list()
Congratulations! You can now begin using etrader
.
The options here are nearly limitless. In this example, we will assume investing for a retirement account. The current annual contribution limit on IRAs is $6,000. Assuming ~250 trading days a year (52*5 - 10 holidays), that allows for $24 a day to be invested.
Below will be a full script that also uses fmpcloudr to verify the current day market hours. This script can be run directly from a CRON job assuming the ETRADE access tokens are valid for the trading day. This can be automated using RSelenium and Docker as detailed in the next section.
Note: I am using SWTSX for all investments for simplicity. I am not recommending SWTSX as an investment. Ideally the user would select 10 or more mutual funds to invest in. Some can be duplicated across multiple days if you have a position with an allocation larger than 10% or that you want spread out.
###########################
# File: etrader_example.R
# Description: Invest $24 a day into mutual funds on ETRADE
# Date: 11/21/2020
# Author: Exploring Finance
# Notes: requires access tokens to be generated with an automated script
###########################
# Load libraries
library(etrader)
library(fmpcloudr)
# Check FMP for trading hours
fmpc_set_token(readRDS('/home/rstudio/Secure/fmp.rds'))
= fmpc_market_hours()
MH = MH$marketHours$isTheStockMarketOpen
trading_day
# If the market is a trading day then run script
if (trading_day) {
# Read in Access Tokens and renew them in case 2 hours have elapsed since last API call
# These tokens are created using the docker/selenium script below
= readRDS('/home/rstudio/Secure/etrade_access.rds')
access_tokens
# Load ETRADE Credentials
= readRDS('/home/rstudio/Secure/etrade_login.rds')
etkeys = etrd_auth_credentials(etkeys$prod_key, etkeys$prod_secret)
etrade_cred
# Activate Access Tokens in case two hours have elapsed
etrd_auth_manage_token(access_tokens = access_tokens, etrade_cred = etrade_cred)
# Create data frame of investments
# This can be as complex or robust as you desire.
# I am not recommending SWTSX as an investment
= data.frame(funds = rep('SWTSX',10),
investments amount = rep(12,10),
day = rep(1:5,2))
# Read in a day counter file - this allows the app to run through each investment
# Create this using: saveRDS(1, '/home/rstudio/counter.rds')
= readRDS('/home/rstudio/counter.rds')
trade_day
# Get trade details based on the trade day counter
= investments$funds[investments$day == trade_day]
symbols_to_buy = investments$amount[investments$day == trade_day]
amount_to_buy
# Get account - assuming this is the desired account
= etrd_account_list()
actlist = actlist$accountIdKey[1]
account
# Enter both trades for execution
# First trade
etrd_place_mf_order(account = account,
symbol = symbols_to_buy[1],
quantityType = 'DOLLAR',
quantity = amount_to_buy[1],
mfTransaction = 'buy',
previewOrder = 'none')
# Second Trade
etrd_place_mf_order(account = account,
symbol = symbols_to_buy[2],
quantityType = 'DOLLAR',
quantity = amount_to_buy[2],
mfTransaction = 'buy',
previewOrder = 'none')
# Update and save trade counter
= ifelse(trade_day == 5, 1, trade_day + 1)
trade_day saveRDS(trade_day, '/home/rstudio/counter.rds')
# Not shown here, but you can use gmailr to automate sending trade confirmations
# https://cran.r-project.org/web/packages/gmailr/gmailr.pdf
}
And that’s it! The trade script will buy $12 of two funds on each day
the market is open once it has been deployed. In this article
I go into detail about setting up a server and deploying a
rameritrade
script. The same steps can be used to deploy
this script, with the one exception on generating access tokens. The
next section will detail how to automate the process of generating
access tokens using Docker and RSelenium.
As mentioned multiple times, the ETRADE API log in process requires a daily manual step of entering a username and password on the website. To fully automate the trading process on AWS, there are a handful of extra steps. This will assume an AWS server has been set up following the steps in this article.
To run the web-scraping script below, a Docker container needs to be set up to run selenium. First, install Docker for Linux. Docker is a very popular software that allows someone to run containers designed for specific tasks. In this example, we want to download/pull a specific docker image for running Selenium with chrome.
ETRADE has an additional layer of security that does not allow user login from unknown locations. To get around this, you will need to provide the IP address of your server to ETRADE so that you can complete the log in process. Whenever you start and stop the AWS server, a new IP address will be assigned. This can avoided by setting up a static IP Address on AWS.
After getting the static IP, contact ETRADE through chat support. Currently wait times are quite long unfortunately. Once connected with someone, reference ‘status code of 942’ and indicate you need to whitelist a server IP address. Provide the static IP address and wait about 10 minutes before proceeding to the next step of completing the log in process.
Update: It appears the whitelist by default only lasts for 14 days. To get around this, either request a permanent whitelist, or request a whitelist cookie and add it to the script as shown below.
With the proper software installed and a whitelisted IP address. The following script can now be run to generate an access token and save them into a designated location.
# Load libraries and read in ETRADE keys
# This assumes ETRADE login details have ben saved as a list to the secure location below
library(etrader)
library(RSelenium)
= readRDS('/home/rstudio/Secure/etrade_login.rds')
etkeys
# Set credentials - this is a list containing API tokens, sudo password, and ETRADE login details
= etrd_auth_credentials(etkeys$prod_key, etkeys$prod_secret)
etrade_cred
# For the first execution launch a docker container using the script below
# system(paste0('echo ',etkeys$sd,' | sudo -S docker run -d -p 4444:4444 selenium/standalone-chrome:latest'))
# Once the docker container exists, start the container with the docker ID
system(paste0('echo ',etkeys$sd,' | sudo -S docker start DOCKER_ID'))
<- list(chromeOptions = list(args = c('--no-sandbox','--disable-dev-shm-usage')))
eCaps <- remoteDriver(port = 4444L, browser = 'chrome',extraCapabilities = eCaps)
remDr
# Open container - force time lag to give docker time to open
Sys.sleep(5)
$open()
remDrSys.sleep(5)
### Navigate to ETrade Login
$navigate('https://us.etrade.com/e/t/user/login')
remDrSys.sleep(5)
# If whitelisting the server IP does not work, use the add cookie feature instead
# remDr$addCookie(name = 'SWH',
# value = 'OBTAIN VALUE FROM ETRADE',
# domain = '.etrade.com',
# secure = TRUE,
# httpOnly = TRUE)
# When testing, the code below will show the webpage
# remDr$screenshot(display = TRUE)
# Enter user credentials
$findElement("xpath",'//*[@id="user_orig"]')$sendKeysToElement(list(etkeys$un))
remDr$findElement("xpath",'//*[@id="log-on-form"]/div[1]/div[2]/div/input')$sendKeysToElement(list(etkeys$pwd))
remDr$findElement("xpath",'//*[@id="logon_button"]')$clickElement()
remDr
# Go to login URL screen and accept terms
Sys.sleep(5)
= etrd_auth_login_url(etrade_cred = etrade_cred, auto_open = FALSE)
loginURL $navigate(loginURL$loginURL)
remDrSys.sleep(5)
# Press Accept button
$findElement("xpath",'/html/body/div[2]/div/div[2]/form/input[3]')$clickElement()
remDr
# Get verification code and logout
= remDr$findElement('xpath','/html/body/div[2]/div/div/input')$getElementAttribute('value')[[1]]
verifcode $navigate('https://us.etrade.com/e/t/user/logout')
remDr
# Get access token and save down
= etrd_auth_access_token(verif_code = verifcode)
access_tokens saveRDS(access_tokens, paste0('/home/rstudio/Secure/etrd_acctok.rds'))
# Shut down docker container
system(paste0('echo ',etkeys$sd,' | sudo -S docker stop DOCKER_ID'))
Once this script is written, it can then be scheduled to run everyday at 9 am Eastern to generate tokens on a daily basis going forward.
In this article, we covered the benefits of dollar cost averaging,
the different trade APIs available, and an example of automating
investment using etrader
. The automated log in process for
etrader
is more labor intensive to set up than the other
trade APIs, but once the process is complete, a fully automated dollar
cost averaging strategy can be implemented.
Disclosure: This article is not intended to be financial advice.
Anyone using the etrader
package does so at their own risk
and should understand the trades they are making. It is strongly
recommended to use the sandbox environment or make trends in off market
hours first to ensure the order entry is correct.
For attribution, please cite this work as
Trevisan (2022, Nov. 21). ALT Analytics: The Ultimate Dollar Cost Averaging Strategy. Retrieved from https://www.altanalyticsllc.com/posts/2022-11-21-the-ultimate-dollar-cost-averaging-strategy/
BibTeX citation
@misc{trevisan2022the, author = {Trevisan, Tony}, title = {ALT Analytics: The Ultimate Dollar Cost Averaging Strategy}, url = {https://www.altanalyticsllc.com/posts/2022-11-21-the-ultimate-dollar-cost-averaging-strategy/}, year = {2022} }