Algorithmic Trading with Python
There are 3 projects:
S&P 500 fund
Momentum strategy
Quantitative value screener, selecting stocks that are attractive based on value method.
Algorithmic trading means using computers to make investment decisions. There are different types of algorithmic trading, and their main difference is their speed and execution. The main players of the trading landscape.
AQR has 61 billion dollars in management. Their name is the IBM of investment funds. The last is citadel securities, which is a much more high frequency firm, in the market making space. You can tell there are lots of jobs.
Python is the most popular programming language for algorithmic trading. However, it is slow, and used as a "glue language" to trigger code that runs in other languages. A common example is the NumPy library, which is the most popular library. It is most popular for the data structure called the NumPy array. The core underlying functionality is written in C, which is much faster performing.
There are steps:
1. Collect Data
2. Develop a hypothesis for a strategy
3. Backtest that strategy
4. Implement that strategy in production.
Start trading that strategy with real money in real accounts.
We'll be using random data which will be a "sandbox api" token, which is random data but also free. We will not be executing trades. There is an excel document, which is generating order sheets to send to imaginary traders later down the line.
We learn about IEX cloud. API is an Application Programming Interface, which is a
Here is a code snippet:
symbol = 'AAPL'
api_rul = f'url'
data = request.get(api_url).json
We are only going to be using GET requests to gather data from an API. A POST request allows you to push data to the API, and the PUT request allows you to add and overwrite data in the database exposed by the API, and DELETE deletes data in the API.
Now we want to build an equal weight SNP 500 fund. The S&P 500 is the popular index, and many investments are benchmarked to the S&P 500 seeking to replicate the performance of an index. It broadly covers the 500 largest companies in the United States, and it is market capitalization weighted, which means that it is a large company, which means the larger companies have a larger weight in the S&P 500 index. We want to assign the same weight to the S&P 500 index.
Momentum investing is investing in prices that increases the most. If Apple went up 35% and Microsoft went up 25%, it would suggest AAPL because of its higher price return.
Value investing is investing in stocks that are trading below their perceived intrinsic value, such as buying a dollar for 75 cents. Multiples are a way that investors use how valuable a company is, by dividing a company stock price by the worth. We determine the price-to-earnings ratio, price-to-book-value, and price-to-free-cash-flow ratio. Each of these multiples has its pros and cons. One way to minimize the impact is to use a composite, which is an average of many different valuation strategies. With all that under way, it's time to dig into the first project. The first thing is to install dependencies, which are numPy, pandas and XLSS. The S&P has > 500 stocks because it has multiple stocks. This is known as the ticker SPY, with 250 billion dollars in it.
The first thing is that we import numpy, when you call a python function in numpy, it executes the program in C, it is used to sum up basic functions. Pandas is a program code for panal data, which makes it easier to use tabular data in Python. This is most widely used for the data structure called the pandas dataframe. Pandas.dataframe instantiates the dataframe object.
Requests is a popular Python library that is the gold standard for the HTTP request. Import xlsxwriter, is for excel documents.
import numpy as np
import pandas as pd
import requests
import xlsxwriter
import math
pd.DataFrame()
math is just the basic mathematical operations. The next thing to do is to import list of stocks, which is around 400 stocks. There are a list of 500 stocks in the S&P, and move this file into the starter files folder so they can be accessed by the files in that directory.
Now that's done, we need to save the stocks as a pandas dataframe named stocks. type(stocks) shows the pandas dataframe and typing stocks will print the stock shares. These APIs require authentication before pulling data from it. Now, we should look for sandbox mode which will have randomized financial data, and do this before we use the API and incur data usage as well.
secrets.py would have API tokens, and would be centralized repository, so we should include it in the .gitignore. Sometimes, you have to restart the kernel, which now it reported correctly.
import numpy as np
import pandas as pd
import requests
import xlsxwriter
import math
from secrets import IEX_CLOUD_API_TOKEN
pd.DataFrame()
stocks = pd.read_csv('sp_500_stocks.csv')
type(stocks)
stocks
Now we're going to make our first API call, which many APIs has really bad documentations. We need the market capitalization for each stock and the price of each stock. We loop over every stock in the API and run this. To start, we do an API call for each stock and then loop over every stock in the Pandas API and run the same API call using a Python for loop. To find the API url go to the iex cloud documentation, a massive documentation for the API, and they have good documentation. Some APIs get certain data to retrieve things faster. The base url of the api is https://cloud.iexapis.com/ and we are using sandbox mode, and it's free and it's still a good way to learn how database works in general. Then we do ctrl + f for sandbox.
The base url for the sandbox is https://sandbox.iexapis.com/. The next thing to do is to figure out which endpoint we need, and we ideally need to find one that provides both market capitalization and stock price. We want an endpoint with both price and market cap, and the /quote/ endpoint gets both of them. Every endpoint description starts to execute on how to execute a request. For this, there is a GET request with stock and symbol attributes.
symbol = 'AAPL'
api_url = 'https://sandbox.iexapis.com/stock/{symbol}/quote/'
And we want to get an s string, changing the values within a string to change an external variable.
What we do is add an f in front, and subsequently try to print the api url string. The last thing we need to do is to add an appendage to the API url and say that "this user has the permission to access this API endpoint" and then have a token equivalent. We define an api url after that.
import numpy as np
import pandas as pd
import requests
import xlsxwriter
import math
from secrets import IEX_CLOUD_API_TOKEN
pd.DataFrame()
stocks = pd.read_csv('sp_500_stocks.csv')
symbol = 'AAPL'
api_url = f'https://sandbox.iexapis.com/stock/{symbol}/quote/?token={IEX_CLOUD_API_TOKEN}'
print(api_url)
Request is very good at standard parsing. A 404 status code indicates that something is missing, an additional suffix that needs to be add in the IEX cloud endpoint. stable is the stable API, but you can access the latest api in beta. Now the status is now a 200 code.
symbol = 'AAPL'
api_url = f'https://sandbox.iexapis.com/stable/stock/{symbol}/quote/?token={IEX_CLOUD_API_TOKEN}'
data = requests.get(api_url)
print(data.status_code)
Now we transform the data of the http request into a json object, which will give us a long JSON type python dictionary object that we can now use to parse data.
{'symbol': 'AAPL', 'companyName': 'Apple Inc', 'primaryExchange': 'OGQARMEE S(LKA/TA ELNBDGTLNS A)CS', 'calculationPrice': 'previousclose', 'open': 135.3, 'openTime': 1654821233241, 'openSource': 'liifofca', 'close': 128.99, 'closeTime': 1652293646102, 'closeSource': 'iclffioa', 'high': 133.155, 'highTime': 1630692847789, 'highSource': 'ceytr d neeiudpmiel5a 1', 'low': 133, 'lowTime': 1630118211551, 'lowSource': ' rmXlErtc eeeIapii', 'latestPrice': 127.48, 'latestSource': 'Previous close', 'latestTime': 'January 15, 2021', 'latestUpdate': 1622571440166, 'latestVolume': 116550836, 'iexRealtimePrice': None, 'iexRealtimeSize': None, 'iexLastUpdated': None, 'delayedPrice': 129.6, 'delayedPriceTime': 1673248130250, 'oddLotDelayedPrice': 128.3, 'oddLotDelayedPriceTime': 1616598601138, 'extendedPrice': 129.53, 'extendedChange': -0.33, 'extendedChangePercent': -0.0026, 'extendedPriceTime': 1625944290448, 'previousClose': 130.74, 'previousVolume': 116283517, 'change': 0, 'changePercent': 0, 'volume': 113798651, 'iexMarketPercent': None, 'iexVolume': None, 'avgTotalVolume': 110269011, 'iexBidPrice': None, 'iexBidSize': None, 'iexAskPrice': None, 'iexAskSize': None, 'iexOpen': 130.7, 'iexOpenTime': 1624130077744, 'iexClose': 132.78, 'iexCloseTime': 1617998833086, 'marketCap': 2204433462057, 'peRatio': 39.43, 'week52High': 138.59, 'week52Low': 56.81, 'ytdChange': -0.04191313680829339, 'lastTradeTime': 1659840314711, 'isUSMarketOpen': False}
price = data['latestPrice'] or extended change. The extended change refers to the price change between the extended price and latest price. You can look up the mean of different datapoints in the IEX cloud docs. We want to store all of the reponses to the pandas dataframe later to an excel file. There is going to be a ticker, stock price, market capitalization, and the price of each stock. We can make a dataframe, and subsequently get it to an excel spreadsheet, and now we want to append data points to pandas dataframe. To do this, we use the append() method, and utilize the pandas series call to append everything into the dataframe. We create a panda series that accepts a python list, which adds the name of the stock we are adding as evidenced by symbol, then the corresponding variables. We get the ignore_index= True, which is what we should do when we add stuff to a pandas dataframe. We created a dataframe then we created a panda series with all the dataframe, and then we specified which columns to add the column to, and then ignore the index. Looping through stocks is really slow, and executing the HTTP request in Python is really slow, but she should do a batch API request instead. so then we recreate the append statement we did earlier, and create another panda series with the python list, basically just repeating stuff out.
import numpy as np
import pandas as pd
import requests
import xlsxwriter
import math
from secrets import IEX_CLOUD_API_TOKEN
pd.DataFrame()
stocks = pd.read_csv('sp_500_stocks.csv')
symbol = 'AAPL'
api_url = f'https://sandbox.iexapis.com/stable/stock/{symbol}/quote/?token={IEX_CLOUD_API_TOKEN}'
data = requests.get(api_url).json()
price = data['latestPrice']
market_cap = data['marketCap']
my_columns = ['Ticker', 'Stock Price', 'Market Capitalization', 'Number of Shares to Buy']
final_dataframe = pd.DataFrame(columns = my_columns)
final_dataframe.append(
pd.Series([
symbol, price, market_cap, 'N/A'
], index = my_columns), ignore_index=True
)
final_dataframe = pd.DataFrame(columns = my_columns)
for stock in stocks['Ticker']:
api_url = f'https://sandbox.iexapis.com/stable/stock/{stock}/quote/?token={IEX_CLOUD_API_TOKEN}'
data = requests.get(api_url).json()
final_dataframe = final_dataframe.append(
pd.Series([stock, data['latestPrice'], data['marketCap'], 'N/A'],
index = my_columns),
ignore_index = True
)
Doing[:5] renews index data for each stock. We have to assign the new stock to the .append() method in order to get the new method. It's generally a good practice to use batch API calls in a script. We need to find some way to split our list of tickers up into sublists of length 100, which can be in a google link. We want to split our panda series into chunks of size N. We use this chunks function to create a list of lists, where every list is no longer than 100.
And then we want to use the for loop to append information of stock in the batch list to every element in the API. We need to transform a stock to a string and this string will be passed into an URL through an HTTP request. So the following line of code creates an array of multiple symbol strings.
A,AAL,AAP,AAPL,ABBV,ABC,ABMD,ABT,ACN,ADBE,ADI,ADM,ADP,ADSK,AEE,AEP,AES,AFL,AIG,AIV,AIZ,AJG,AKAM,ALB,ALGN,ALK,ALL,ALLE,ALXN,AMAT,AMCR,AMD,AME,AMGN,AMP,AMT,AMZN,ANET,ANSS,ANTM,AON,AOS,APA,APD,APH,APTV,ARE,ATO,ATVI,AVB,AVGO,AVY,AWK,AXP,AZO,BA,BAC,BAX,BBY,BDX,BEN,BF.B,BIIB,BIO,BK,BKNG,BKR,BLK,BLL,BMY,BR,BRK.B,BSX,BWA,BXP,C,CAG,CAH,CARR,CAT,CB,CBOE,CBRE,CCI,CCL,CDNS,CDW,CE,CERN,CF,CFG,CHD,CHRW,CHTR,CI,CINF,CL,CLX,CMA,CMCSA
CME,CMG,CMI,CMS,CNC,CNP,COF,COG,COO,COP,COST,COTY,CPB,CPRT,CRM,CSCO,CSX,CTAS,CTL,CTSH,CTVA,CTXS,CVS,CVX,CXO,D,DAL,DD,DE,DFS,DG,DGX,DHI,DHR,DIS,DISCA,DISCK,DISH,DLR,DLTR,DOV,DOW,DPZ,DRE,DRI,DTE,DUK,DVA,DVN,DXC,DXCM,EA,EBAY,ECL,ED,EFX,EIX,EL,EMN,EMR,EOG,EQIX,EQR,ES,ESS,ETFC,ETN,ETR,EVRG,EW,EXC,EXPD,EXPE,EXR,F,FANG,FAST,FB,FBHS,FCX,FDX,FE,FFIV,FIS,FISV,FITB,FLIR,FLS,FLT,FMC,FOX,FOXA,FRC,FRT,FTI,FTNT,FTV,GD,GE,GILD
GIS,GL,GLW,GM,GOOG,GOOGL,GPC,GPN,GPS,GRMN,GS,GWW,HAL,HAS,HBAN,HBI,HCA,HD,HES,HFC,HIG,HII,HLT,HOLX,HON,HPE,HPQ,HRB,HRL,HSIC,HST,HSY,HUM,HWM,IBM,ICE,IDXX,IEX,IFF,ILMN,INCY,INFO,INTC,INTU,IP,IPG,IPGP,IQV,IR,IRM,ISRG,IT,ITW,IVZ,J,JBHT,JCI,JKHY,JNJ,JNPR,JPM,K,KEY,KEYS,KHC,KIM,KLAC,KMB,KMI,KMX,KO,KR,KSS,KSU,L,LB,LDOS,LEG,LEN,LH,LHX,LIN,LKQ,LLY,LMT,LNC,LNT,LOW,LRCX,LUV,LVS,LW,LYB,LYV,MA,MAA,MAR,MAS,MCD,MCHP
MCK,MCO,MDLZ,MDT,MET,MGM,MHK,MKC,MKTX,MLM,MMC,MMM,MNST,MO,MOS,MPC,MRK,MRO,MS,MSCI,MSFT,MSI,MTB,MTD,MU,MXIM,MYL,NBL,NCLH,NDAQ,NEE,NEM,NFLX,NI,NKE,NLOK,NLSN,NOC,NOV,NOW,NRG,NSC,NTAP,NTRS,NUE,NVDA,NVR,NWL,NWS,NWSA,O,ODFL,OKE,OMC,ORCL,ORLY,OTIS,OXY,PAYC,PAYX,PBCT,PCAR,PEAK,PEG,PEP,PFE,PFG,PG,PGR,PH,PHM,PKG,PKI,PLD,PM,PNC,PNR,PNW,PPG,PPL,PRGO,PRU,PSA,PSX,PVH,PWR,PXD,PYPL,QCOM,QRVO,RCL,RE,REG,REGN,RF,RHI,RJF,RL,RMD,ROK
ROL,ROP,ROST,RSG,RTX,SBAC,SBUX,SCHW,SEE,SHW,SIVB,SJM,SLB,SLG,SNA,SNPS,SO,SPG,SPGI,SRE,STE,STT,STX,STZ,SWK,SWKS,SYF,SYK,SYY,T,TAP,TDG,TDY,TEL,TFC,TFX,TGT,TIF,TJX,TMO,TMUS,TPR,TROW,TRV,TSCO,TSN,TT,TTWO,TWTR,TXN,TXT,TYL,UA,UAA,UAL,UDR,UHS,ULTA,UNH,UNM,UNP,UPS,URI,USB,V,VAR,VFC,VIAC,VLO,VMC,VNO,VRSK,VRSN,VRTX,VTR,VZ,WAB,WAT,WBA,WDC,WEC,WELL,WFC,WHR,WLTW,WM,WMB,WMT,WRB,WRK,WST,WU,WY,WYNN,XEL,XLNX,XOM,XRAY,XRX,XYL
YUM,ZBH,ZBRA,ZION,ZTS
Now all the stocks are separated into batches successfully. Here now we overwrite the dataframe and overwrite everything with the columns, and print them out to make sure that they look okay.
For the symbol string, we want to get a batch API call URL, in order to get data from 100 stocks back. For batch requests in the IEX cloud, what it says is that we want to use a market to query method.
A problem is than when you pass on characters, every successive character needs to be an & sign.
Here is an example link of a JSON that will reply positively to the API request:
https://sandbox.iexapis.com/stable/stock/market/batch?symbols=A,AAL,AAP,AAPL,ABBV,ABC,ABMD,ABT,ACN,ADBE,ADI,ADM,ADP,ADSK,AEE,AEP,AES,AFL,AIG,AIV,AIZ,AJG,AKAM,ALB,ALGN,ALK,ALL,ALLE,ALXN,AMAT,AMCR,AMD,AME,AMGN,AMP,AMT,AMZN,ANET,ANSS,ANTM,AON,AOS,APA,APD,APH,APTV,ARE,ATO,ATVI,AVB,AVGO,AVY,AWK,AXP,AZO,BA,BAC,BAX,BBY,BDX,BEN,BF.B,BIIB,BIO,BK,BKNG,BKR,BLK,BLL,BMY,BR,BRK.B,BSX,BWA,BXP,C,CAG,CAH,CARR,CAT,CB,CBOE,CBRE,CCI,CCL,CDNS,CDW,CE,CERN,CF,CFG,CHD,CHRW,CHTR,CI,CINF,CL,CLX,CMA,CMCSA&types=quote&token=Tpk_059b97af715d417d9f49f50b51b1c448
Now we need to get the call.json method, but not until we print the data status code first. This parallelism made it way, way faster than individual parallel commands. So we're ready to proceed to calculate the number of shares to buy.
Finally, we want to get the python portfolio on how long the portfolio is, and gets the Python input question with a string. We need to create a try-except statement in the case that the user doesn't enter the string. We basically want to say "try to do this" and if this doesn't work it will do whatever is specified.The next thing we do is to handle the input as a float variable, and create it as a val, and try to take a variable size and force it to be a float. We have to perform some exception integers, and then ask to enter the value of the portfolio. Since each stock is equal weight, each stock will have the same position size, which will be the amount of money you invest in the stock. Now we need to calculate how many pieces of position size we need. Math.floor rounds down. This is the module intuition on how to do this. Now, we loop through everything in the pandas dataframe, and we do this for the number of shares to buy in each column in each dataframe.
.loc locates a function in an array using Python. We want the one that has the higher stock price be recommended to buy more than the one that has the lower stock price, which that we need to buy many more shares in order to reach to the target position.
import numpy as np
import pandas as pd
import requests
import xlsxwriter
import math
from secrets import IEX_CLOUD_API_TOKEN
pd.DataFrame()
stocks = pd.read_csv('sp_500_stocks.csv')
symbol = 'AAPL'
api_url = f'https://sandbox.iexapis.com/stable/stock/{symbol}/quote/?token={IEX_CLOUD_API_TOKEN}'
data = requests.get(api_url).json()
price = data['latestPrice']
market_cap = data['marketCap']
my_columns = ['Ticker', 'Stock Price', 'Market Capitalization', 'Number of Shares to Buy']
final_dataframe = pd.DataFrame(columns = my_columns)
final_dataframe.append(
pd.Series([
symbol, price, market_cap, 'N/A'
], index = my_columns), ignore_index=True
)
final_dataframe = pd.DataFrame(columns = my_columns)
for stock in stocks['Ticker'][:5]:
api_url = f'https://sandbox.iexapis.com/stable/stock/{stock}/quote/?token={IEX_CLOUD_API_TOKEN}'
data = requests.get(api_url).json()
final_dataframe = final_dataframe.append(
pd.Series([stock, data['latestPrice'], data['marketCap'], 'N/A'],
index = my_columns),
ignore_index = True
)
final_dataframe
def chunks(lst, n):
for i in range(0, len(lst), n):
yield lst[i:i+n]
symbol_groups = list(chunks(stocks['Ticker'], 100))
symbol_strings = []
for i in range(0, len(symbol_groups)):
symbol_strings.append(','.join(symbol_groups[i]))
# print(symbol_strings[i])
final_dataframe = pd.DataFrame(columns = my_columns)
for symbol_string in symbol_strings:
batch_api_call_url = f'https://sandbox.iexapis.com/stable/stock/market/batch?symbols={symbol_string}&types=quote&token={IEX_CLOUD_API_TOKEN}'
data = requests.get(batch_api_call_url).json()
for symbol in symbol_string.split(','):
#print(symbol)
final_dataframe = final_dataframe.append(pd.Series([symbol,
data[symbol]['quote']['latestPrice'],
data[symbol]['quote']['marketCap'],
'N/A'], index = my_columns),
ignore_index=True
)
portfolio_size = input('Enter the value of your portfio: ')
try:
val = float(portfolio_size)
print(val)
except ValueError:
print("That's not a number! \n Please Try again:")
portfolio_size = input('Enter the value of your portfolio:')
val = float(portfolio_size)
position_size = val/len(final_dataframe.index)
number_of_apple_shares = position_size/500
#print(Math.floor(number_of_apple_shares))
for i in range(0, len(final_dataframe.index)):
final_dataframe.loc[i, 'Number of Shares to Buy'] = math.floor(position_size/final_dataframe.loc[i, 'Stock Price'])
final_dataframe
The last section of the project is to save the project in the excel document. We did all the work in the Python script, and we should buy and sell stocks in response to the input. At the start, many lines of code go, and we need to use it to save our dataframe as an excel file.
The first thing we need to do is to initialize the writer object. Use python here, and specify to work in excel. Then we want to pass our pandas dataframe into this object, and we pass in the writer object, and the tab that we want to save to, and an index = false document.
Formatting excel files with .xlsx writer can be extremely complicated. We create 2 variables to specify the color scheme for this, a background color variable and the font color variable.


Comments
Post a Comment