Professional Documents
Culture Documents
"(2" L'%(A%0*%'#
G&7(/0H'(<(5*''(3'38'*$&"4:(A%&*2'A(4'5%(%/2A(3&"%/I
J2."(7)(5&*(K'#273(0"#(.'%(0"('E%*0(&"'
!"#$%"$&'()*($+$,-../
+-*"0)*(1$+2$3)4(1
%')1567$8/4*(0$95*:
;/*:"6
!"#$%&$'"#()*&+',%-(.'%(%/'(#0%01(%*02"(%/'(3&#'41()40,'(%/'
&*#'*1(.'%("&%252'#
3. At this point we’ll have the data and the prediction coming
from the algorithm, so we should be able to decide whether
to sell, buy or hold; we need to connect with our broker to
actually perform the action. We are going to use RobinHood
and Alpaca.
!"##$%&'#("')*#*
Getting the data is not easy. Some years ago there was an
o_cial Yahoo! Finance API, as well as alternatives like Google
Finance — sadly, both have been discontinued for years now.
But don’t worry, there’s still plenty of alternatives in the
market. My personal requirements were:
Sweet, good enough for me. How does it work? First we need to
install it:
import yfinance as yf
google = yf.Ticker(“GOOG”)
52WeekChange: 0.3531152
SandP52WeekChange: 0.17859101
address1: 1600 Amphitheatre Parkway
algorithm: None
annualHoldingsTurnover: None
annualReportExpenseRatio: None
ask: 1815
askSize: 1100
...
twoHundredDayAverage: 1553.0764
volume: 1320946
volume24Hr: None
volumeAllCurrencies: None
website: http://www.abc.xyz
yield: None
ytdReturn: None
zip: 94043
O0%05*03'(&5(L&&.4'(/2A%&*2,04(A%&,D()*2,'(P(Q30.'(8:(R7%/&*
We can see how it’s indexed by the datetime and every entry
has seven features: four Exed points of the stock price during
that minute (open, high, low and close) plus the volume,
dividends and stock splits. I’m going to use just the low, so let’s
keep that data:
df = google.history(period='1d', interval="1m")
df = df[['Low']]
df.head()
Q30.'(8:(R7%/&*
Finally, since we’re going to use the data just for the last day,
let’s reindex the dataframe to remove the date and timezone
components and keep just the time one:
df['date'] = pd.to_datetime(df.index).time
df.set_index('date', inplace=True)
df.head()
Q30.'(8:(R7%/&*
+))$%&'#("'+,
I said it before but I’ll say this again: don’t try this at home.
What I’m going to do here is Etting a VERY simple ARIMA
model to forecast the next value of the stock price; think of it as
a dummy model. If you want to use this for real trading, I’d
recommend to look for better and stronger models, but be
aware: if it were easy, everyone would do it.
First let’s split the dataframe into train and test, so we can use
the test set to validate the results of the dummy model — I’m
going to keep the last 10% of the data as the test set:
X = df.index.values
y = df['Low'].values
X_train = X[:-offset]
y_train = y[:-offset]
X_test = X[-offset:]
y_test = y[-offset:]
plt.plot(range(0,len(y_train)),y_train, label='Train')
plt.plot(range(len(y_train),len(y)),y_test,label='Test')
plt.legend()
plt.show()
Q30.'(8:(R7%/&*
Now let’s Et the model with the training data and get the
forecast. Note that the hyperparameters of the model are Exed
whereas in the real world you should use cross-validation to get
the optimal ones — check out this awesome tutorial about How
To Grid Search ARIMA Hyperparameters With Python. I’m
using a 5, 0, 1 conEguration and getting the forecast for the
moment immediately after the training data ends:
---
That’s not bad — we can work with it. With this info we can
deEne a set of rules based on whatever we want to do, like
holding if it’s going up or selling if it’s going down. I’m not
going to elaborate on this part because I don’t want y’all to sue
me saying you lost all your money, so please go ahead and
deEne your own set of rules :) In the meantime, I’m going to
explain the next part: connecting to the broker.
-.%%"/#$%&'#.'#("'01.2"1
As you probably have guessed, this part highly depends on the
broker you’re using. I’m covering here two brokers, RobinHood
and Alpaca; the reason is that both of them:
3.0$%4..)
There are several libraries that wrap the RobinHood API, but
sadly, as far as I know no one of them is o_cial. Sanko’s library
was the biggest one, with 1.5k stars in GitHub, but it has been
discontinued; LichAmnesia’s has continued Sanko’s path, but
has just 99 stars so far. I’m going to use robin_stocks library,
which has a little over 670 stars at the moment of writing this.
Let’s install it:
$ pip install robin_stocks
Not all actions require login, but most of them do, so it’s useful
to login before doing anything else. RobinHood requires MFA,
so it’s necessary to set it up: go to your account, turn on the two
factor authentication and select “other” when asked about the
app you want to use. You will be presented with an
alphanumeric code, which you will use in the code below:
import pyotp
import robin_stocks as robinhood
timed_otp = pyotp.TOTP(RH_MFA_CODE).now()
login = rh.login(RH_USER_EMAIL, RH_PASSWORD,
mfa_code=totp)
api = alpaca.REST(
ALPACA_KEY_ID, ALPACA_SECRET_KEY, base_url=BASE_URL)
7"65.8'*%)'9.%$#.1$%&
We are going to deploy everything in AWS Lambda. This
wouldn’t be the best option for a production system, obviously,
since Lambda does not have storage and we would want to
store the trained model somewhere, for instance in S3.
However, this will do for now — we’ll schedule the Lambda to
run daily, training the model every time with the data from the
current day. For monitoring purposes we’ll set up a Telegram
bot that will send a message with the action to be taken and its
outcome. Note that AWS Lambda is free up to a certain limit,
but be aware of the quotas in case you want to send lots of
messages.
The Erst thing on the to-do list is creating a bot. I followed the
o_cial instructions from Telegram:
import telegram
import sys
import os
CHAT_ID = XXXXXXXX
TOKEN = os.environ['TELEGRAM_TOKEN']
def do_everything():
# The previous code to get the data, train the model
# and send the order to the broker goes here.
return 'The action performed'
bot.sendMessage(chat_id=CHAT_ID,
text=action_performed)
org: your-organization-name
app: your-app-name
service: ai_trading_system
provider:
name: aws
runtime: python3.6
environment:
TELEGRAM_TOKEN: ${env:TELEGRAM_TOKEN}
# If using RobinHood
RH_USER_EMAIL: ${env:RH_USER_EMAIL}
RH_PASSWORD: ${env:RH_PASSWORD}
RH_MFA_CODE: ${env:RH_MFA_CODE}
# If using Alpaca
ALPACA_KEY_ID: ${env:ALPACA_KEY_ID}
ALPACA_SECRET_KEY: ${env:ALPACA_SECRET_KEY}
functions:
cron:
handler: handler.send_message
events:
# Invoke Lambda function at 21:00 UTC every day
- schedule: cron(00 21 * * ? *)
The only thing left is to get the AWS credentials and set them,
along with the token and the rest of variables, as environment
variables before deploying. Getting the credentials is fairly
easy:
Copy the Access Key ID and the Secret Access Key and store
them.
That’s it. Now, let’s export the AWS credentials and the
Telegram token. Open a terminal and write:
# If using Alpaca
$ export ALPACA_KEY_ID=[your key goes here]
$ export ALPACA_SECRET_KEY=[your key goes here]
We’re done! The bot will trade for us every day at 21:00 UTC
time and will message us with the action performed. Not bad
for a proof of concept — now I can tell my friend he can stop
frantically checking his phone to trade :)
Note that all the resources we’ve used through this tutorial
have their own documentation: I encourage y’all to go deeper
on whatever you think is interesting — remember that this is
just a toy system! However, as a toy system, I believe it is a good
starting point for a richer, more complex product. Happy
coding!
3":"1"%/";<
[1] P. Collins, Best Stock APIs and Industry Landscape in 2020
(2020), Medium
U0"#A$&"(*'04$=&*4#('E03)4'A1(*'A'0*,/1(%7%&*204A1(0"#(,7%%2".$'#.'
%',/"2V7'A(#'42H'*'#(K&"#0:(%&(T/7*A#0:I(K0D'(4'0*"2".(:&7*(#024:
*2%704I(T0D'(0(4&&D
G&7*('3024 L'%
%/2A
"'=A4'%%'*
S:(A2."2".(7)1(:&7(=244(,*'0%'(0(K'#273(0,,&7"%(25(:&7(#&"W%(04*'0#:(/0H'(&"'I(6'H2'=(&7*(C*2H0,:(C&42,:
5&*(3&*'(2"5&*30%2&"(08&7%(&7*()*2H0,:()*0,%2,'AI
T/0"DA(%&(!442&%(L7""I(