What will we cover in this tutorial?
- How to build a financial trading algorithm in Python.
- Where and how to get time series data on your favorite stock.
- Understand the data available and how to enrich it.
- How to visualize the data in Python.
- Building a trading algorithm.
- Test how the algorithm performs.
- Also, see the tutorial on how to make a Machine Learning trading bot in Python.
Step 1: Get time series data on your favorite stock
To build a financial trading algorithm in Python, it needs to be fed with data. Hence, the first step you need to master is how to collect time series data on your favorite stock. Sounds like it is difficult, right?
Luckily, someone made an awesome library pandas-datareader, which does all the hard word you for you. Let’s take a look on how easy it is.
import datetime as dt
import pandas_datareader as pdr
import matplotlib.pyplot as plt
from dateutil.relativedelta import relativedelta
# A Danish jewellery manufacturer and retailer
stock = 'PNDORA.CO'
end = dt.datetime.now()
start = end - relativedelta(years=10)
pndora = pdr.get_data_yahoo(stock, start, end)
pndora['Close'].plot()
plt.show()
Which results in a time series of the closing price as shown here.

The stock is probably quite unknown, considering it is a Danish company. But to prove a point that you can get data, including for Pandora.
In the code you see that you send a start and end date to the call fetching the data. Here we have taken the last 10 years. The object returned integrates well with the matplotlib library to make the plot.
To understand the data better, we need to explore further.
Step 2: Understand the data available
Let us explore the data object returned by the call (pndora).
To get an overview you should run the following code using the iloc-call to a the Dataframe object (pndora returned by pandas_datareader).
pndora.iloc[-1]
This will show what the last item of the object looks like.
High 365.000000
Low 355.600006
Open 360.000000
Close 356.500000
Volume 446004.000000
Adj Close 356.500000
Name: 2020-06-26 00:00:00, dtype: float64
Where you have the following items.
- High: The highest price traded during that day.
- Low: The lowest price traded during that day.
- Open: The opening price that day.
- Close: The closing price that day, that is the price of the last trade that day.
- Volume: The number of shares that exchange hands for the stock that day.
- Adj Close: It accurately reflect the stock’s value after accounting for any corporate actions. It is considered to be the true price of that stock and is often used when examining historical returns.
That means, it would be natural to use Adj Close in our calculations. Hence, for each day we have the above information available.
Step 3: Learning how to enrich the data (Pandas)
Pandas? Yes, you read correct. But not a Panda like this the picture.

There is an awesome library Pandas in Python to make data analysis easy.
Let us explore some useful things we can do.
import datetime as dt
import pandas_datareader as pdr
import matplotlib.pyplot as plt
from dateutil.relativedelta import relativedelta
# A Danish jewellery manufacturer and retailer
stock = 'PNDORA.CO'
end = dt.datetime.now()
start = end - relativedelta(years=10)
pndora = pdr.get_data_yahoo(stock, start, end)
pndora['Short'] = pndora['Adj Close'].rolling(window=20).mean()
pndora['Long'] = pndora['Adj Close'].rolling(window=100).mean()
pndora[['Adj Close', 'Short', 'Long']].plot()
plt.show()
Which will result in the following graph.

If you inspect the code above, you see, that you easily added to two new columns (Short and Long) and computed them to be the mean value of the previous 20 and 100 days, respectively.
Further, you can add the daily percentage change for the various entries.
import datetime as dt
import pandas_datareader as pdr
import matplotlib.pyplot as plt
from dateutil.relativedelta import relativedelta
# A Danish jewellery manufacturer and retailer
stock = 'PNDORA.CO'
end = dt.datetime.now()
start = end - relativedelta(years=10)
pndora = pdr.get_data_yahoo(stock, start, end)
pndora['Short'] = pndora['Adj Close'].rolling(window=20).mean()
pndora['Long'] = pndora['Adj Close'].rolling(window=100).mean()
pndora['Pct Change'] = pndora['Adj Close'].pct_change()
pndora['Pct Short'] = pndora['Short'].pct_change()
pndora['Pct Long'] = pndora['Long'].pct_change()
pndora[['Pct Change', 'Pct Short', 'Pct Long']].loc['2020'].plot()
plt.show()
Which will result in this graph.

Again you can see how easy it is to add new columns in the Dataframe object provided by Pandas library.
Step 4: Building your strategy to buy and sell stocks
For the example we will keep it simple and only focus on one stock. The strategy we will use is called the dual moving average crossover.
Simply explained, you want to buy stocks when the short mean average is higher than the long mean average value.

In the figure above, it is translates to.
- Buy when the yellow crosses above the green line.
- Sell when the yellow crosses below the green line.
To implement the simplest version of that it would be as follows.
import datetime as dt
import pandas_datareader as pdr
import matplotlib.pyplot as plt
import numpy as np
from dateutil.relativedelta import relativedelta
# A Danish jewellery manufacturer and retailer
stock = 'PNDORA.CO'
end = dt.datetime.now()
start = end - relativedelta(years=10)
pndora = pdr.get_data_yahoo(stock, start, end)
short_window = 20
long_window = 100
pndora['Short'] = pndora['Adj Close'].rolling(window=short_window).mean()
pndora['Long'] = pndora['Adj Close'].rolling(window=long_window).mean()
# Let us create some signals
pndora['signal'] = 0.0
pndora['signal'][short_window:] = np.where(pndora['Short'][short_window:] > pndora['Long'][short_window:], 1.0, 0.0)
pndora['positions'] = pndora['signal'].diff()
To visually see where to buy and sell you can use the following code afterwards on pndora.
fig = plt.figure()
ax1 = fig.add_subplot(111, ylabel='Price')
pndora[['Adj Close', 'Short', 'Long']].plot(ax=ax1)
ax1.plot(pndora.loc[pndora.positions == 1.0].index,
pndora.Short[pndora.positions == 1.0],
'^', markersize=10, color='m')
ax1.plot(pndora.loc[pndora.positions == -1.0].index,
pndora.Short[pndora.positions == -1.0],
'v', markersize=10, color='k')
plt.show()
Which would result in the following graph.

Finally, you need to see how your algorithm performs.
Step 5: Testing you trading algorithm
There are many ways to test an algorithm. Here we go all in each cycle. We buy as much as we can and sell them all when we sell.
import datetime as dt
import pandas_datareader as pdr
import matplotlib.pyplot as plt
import numpy as np
from dateutil.relativedelta import relativedelta
# A Danish jewellery manufacturer and retailer
stock = 'PNDORA.CO'
end = dt.datetime.now()
start = end - relativedelta(years=10)
pndora = pdr.get_data_yahoo(stock, start, end)
short_window = 20
long_window = 100
pndora['Short'] = pndora['Adj Close'].rolling(window=short_window).mean()
pndora['Long'] = pndora['Adj Close'].rolling(window=long_window).mean()
# Let us create some signals
pndora['signal'] = 0.0
pndora['signal'][short_window:] = np.where(pndora['Short'][short_window:] > pndora['Long'][short_window:], 1.0, 0.0)
pndora['positions'] = pndora['signal'].diff()
cash = 1000000
stocks = 0
for index, row in pndora.iterrows():
if row['positions'] == 1.0:
stocks = int(cash//row['Adj Close'])
cash -= stocks*row['Adj Close']
elif row['positions'] == -1.0:
cash += stocks*row['Adj Close']
stocks = 0
print("Total:", cash + stocks*pndora.iloc[-1]['Adj Close'])
Which results in.
Total: 2034433.8826065063
That is a double in 10 years, which is less than 8% per year. Not so good.
As this is one specific stock, it is not fair to judge the algorithm being poor, it can be the stock which was not performing good, or the variables can be further adjusted.
If compared with the scenario where you bought the stocks at day one and sold them on the last day, your earnings would be 1,876,232. Hence, the algorithm beats that.
Conclusion and further work
This is a simple financial trading algorithm in Python and there are variables that can be adjusted. The algorithm was performing better than the naive strategy to buy on day one and sell on the last day.
It could be interesting to add more data into the decision in the algorithm, which might be some future work to do. Also, can it be combined with some Machine Learning?
Python Circle
Do you know what the 5 key success factors every programmer must have?
How is it possible that some people become programmer so fast?
While others struggle for years and still fail.
Not only do they learn python 10 times faster they solve complex problems with ease.
What separates them from the rest?
I identified these 5 success factors that every programmer must have to succeed:
- Collaboration: sharing your work with others and receiving help with any questions or challenges you may have.
- Networking: the ability to connect with the right people and leverage their knowledge, experience, and resources.
- Support: receive feedback on your work and ask questions without feeling intimidated or judged.
- Accountability: stay motivated and accountable to your learning goals by surrounding yourself with others who are also committed to learning Python.
- Feedback from the instructor: receiving feedback and support from an instructor with years of experience in the field.
I know how important these success factors are for growth and progress in mastering Python.
That is why I want to make them available to anyone struggling to learn or who just wants to improve faster.
With the Python Circle community, you can take advantage of 5 key success factors every programmer must have.

Be part of something bigger and join the Python Circle community.