Build a Stock Visualization Website in Python/Django

👍288
|
Share project link
Expert Instructor: Daniel Petrow (Alpha Vantage)
Keywords: web development, data visualization, HTML, Javascript/AJAX, server-side scripting, SQL, Python/Django


Data visualization is a must-have feature for more and more web, mobile, and IoT applications. This trend is even more salient in the domain of financial market data, where data visualization is often used for market intelligence, technical charting, and other key business and/or quantitative scenarios such as exploratory data analysis (EDA).

In this project, we will create an interactive stock visualization website (screenshot below) with Python/Django and Alpha Vantage APIs. We will cover key software engineering and web development concepts such as AJAX, server-side scripting, and database models - in fewer than 400 lines of code.

stock visualizer homepage mockup

The project is comprised of the following sections:

❚ Install dependencies and set up project

❚ Create database model

❚ Create frontend UI

❚ Create backend logic

❚ Set up Django URL routing

❚ Run the web application locally

To minimize your cognitive load, we have included all the necessary code scripts and command line prompts directly in this document. By the time you finish this tutorial, you will have a stock data visualization website with frontend, backend, and database all ready for prime time. Let's get started!


Install dependencies and set up project

We recommend Python 3.6 or higher. If you do not yet have Python installed, please follow the download instructions on the official python.org website.

Once you have Python installed in your environment, please use your command line interface to install the following Python libraries:

❚ Django: pip install django

❚ requests: pip install requests

The pip installer above should already be included in your system if you are using Python 3.6 or higher downloaded from python.org. If you are seeing a "pip not found" error message, please refer to the pip installation guide.

Please also obtain a free Alpha Vantage API key here. You will use this API key to query stock market data from our REST stock APIs as you develop this stock visualization web application.


Now, we are ready to create the Django project!

Open a new command line window and type in the following prompt:

(home) $ django-admin startproject alphaVantage

You have just created a blank Django project in a folder called alphaVantage.

Now, let's switch from your home directory to the alphaVantage project directory with the following command line prompt:

(home) $ cd alphaVantage

For the rest of this project, we will be operating inside the alphaVantage root directory.


Now, let's create a stockVisualizer app within the blank Django project:

(alphaVantage) $ python manage.py startapp stockVisualizer

We will also create an HTML file for our homepage. Enter the following 4 command line prompts in order:

Step 1: create a new folder called "templates"

(alphaVantage) $ mkdir templates

Step 2: go to the "templates" folder

(alphaVantage) $ cd templates

Step 3: create an empty home.html file inside the templates folder

If you are using Mac or Linux:
(templates) $ touch home.html

If you are using Windows:
(templates) $ type nul > home.html

Step 4: return to our alphaVantage root directory

(templates) $ cd ../


At this stage, the file structure of your Django project should look similar to the one below. You may want to import the project into an IDE such as PyCharm, Visual Studio, or Sublime Text to visualize the file structure more easily.


Let's take a closer look at some of the key files:

❚ manage.py: A command-line utility that lets you interact with this Django project in various ways. You can read all the details about manage.py in django-admin and manage.py.

❚ __init__.py: An empty file that tells Python that this directory should be considered a Python package. Please keep it empty!

❚ settings.py: Settings/configuration for this Django project.

❚ urls.py: The URL declarations for this Django project; a “table of contents” of your Django-powered site.

❚ models.py: this is the file you will use to define database objects and schema

❚ views.py: this is where all the backend logic gets implemented and relayed to the frontend (views)

❚ home.html: the HTML file that determines the look and behavior of the homepage


Specify the database model

Databases are essential components of most modern web and mobile applications. For our stock visualization website, we will create a simple (two-column) database model to store stock market data.

Before we create the database model, however, let's open the settings.py file and quickly modify the following 3 places in the script:

1. Near the top of settings.py, add import os


2. Inside the INSTALLED_APPS, add the stockVisualizer app:


3. Inside TEMPLATES, include the templates directory we've created earlier in this project:


Now, let's define a Django database model called StockData in models.py.

The model has two fields:

❚ a symbol field that stores the ticker string of the stock

❚ a data field that stores the historical prices and moving average values for a given ticker


With models.py updated, let's notify Django about the newly created database model with the following command line prompts:

(alphaVantage) $ python manage.py makemigrations

(alphaVantage) $ python manage.py migrate


At this stage, your file structure should look similar to the one below:


The db.sqlite3 file indicates that we have registered our StockData model in the local SQLite database. As its name suggests, SQLite is a lightweight SQL database frequently used for web development (especially in local test environment). SQLite is automatically included in Django/Python, so there is no need to install it separately :-)


There are now only two steps left before completing the website:

❚ Set up the homepage file (home.html) so that we can visualize stock prices and moving averagas of a given stock

❚ Create the backend server logic (views.py) so that we have the proper stock data to feed into the frontend UI

Let's proceed!


Create frontend UI

Before we dive into the code implementation, let's first summarize the expected behavior of our homepage (screenshots below) at a high level:

❚ Upon loading, the page will display the adjusted close prices and simple moving average (SMA) values of Apple (AAPL), covering the most recent 500 trading days.

❚ When the user enters a new stock ticker in the textbox and hits "submit", the existing chart on the page will be replaced with the adjusted close and SMA data of the new ticker.


When the homepage is first loaded:

stock visualizer homepage mockup

When the user enters a new symbol (such as GME):

stock visualizer homepage mockup with user input

With the above page layout and behavior defined, let's implement the homepage frontend accordingly.

Open the (empty) home.html and paste the following content into it:


This is a chunky block of code! Don't worry - let's break it down into the following 4 functional groups:

1. Load the Javascript dependencies

❚ https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.min.js is the powerful Chart.js library for data visualization

❚ https://code.jquery.com/jquery-3.6.0.min.js loads the jquery library that streamlines common frontend development tasks.


2. Define the page layout

❚ <input type="text" id="ticker-input"> is the input text box for a user to enter a new stock ticker

❚ <input type="button" value="submit" id="submit-btn"> is the submit button

❚ <canvas id="myChart"></canvas> is the canvas on which Chart.js will generate the beautiful graph for stock data visualization


3. Define the behavior upon page loading

The $(document).ready(function(){...} code block specifies the page behavior when it's first loaded:

❚ First, it will make an AJAX POST request to a Django backend function called get_stock_data to get the price and simple moving average data for AAPL. AJAX stands for Asynchronous JavaScript And XML, which is a popular Javascript design pattern that enables a developer to (1) update a web page without reloading the page, (2) request data from a backend server - after the page has loaded, (3) receive data from a backend server - after the page has loaded, among other benefits.

❚ Once AAPL's data is returned by the backend to the frontend (the data is stored in the res variable in success: function (res, status) {...}), it is parsed by several lines of Javascript codes into three lists: dates, daily_adjusted_close, and sma_data.

❚ These three lists are then truncated into size=500 (i.e., data for the trailing 500 trading days) to be visualized by Chart.js. Specifically, the values in dates are used for the X axis; values in daily_adjusted_close and sma_data are used for the Y axis.


4. Define the behavior for when a new ticker is submitted by the user

The $('#submit-btn').click(function(){...} code block specifies the page behavior when a user enters a new ticker symbol:

❚ First, it will make an AJAX POST request to a Django backend function called get_stock_data to get the price and simple moving average data for the ticker entered by the user. The line var tickerText = $('#ticker-input').val(); takes care of extracting the ticker string from the input textbox.

❚ Once the ticker's data is returned by the backend to the frontend (the data is again stored in the res variable in success: function (res, status) {...}), it is parsed by several lines of Javascript codes into three lists: dates, daily_adjusted_close, and sma_data.

❚ These three lists are then truncated into size=500 (i.e., data for the trailing 500 trading days) to be visualized by Chart.js. Specifically, the values in dates are used for the X axis; values in daily_adjusted_close and sma_data are used for the Y axis.


As you can see, the get_stock_data backend function is now the only missing piece in the frontend-backend communication loop. Let's implement it right away!


Create backend server logic (views.py)

Now, let's update views.py to the following. Don't forget to replace the my_alphav_api_key string with your actual Alpha Vantage API key.


Let's look at the above backend server-side code a bit closer.

The variable DATABASE_ACCESS = True means the get_stock_data function will first check if there is existing data in the local database before making API calls to Alpha Vantage. If you set DATABASE_ACCESS = False, the script will bypass any local database lookups and proceed directly to calling Alpha Vantage APIs when a new ticker is queried. We have included a paragraph titled Data Freshness vs. Speed Trade-off under the References section of this tutorial to discuss the nuances of getting data from local databases vs. querying an external API.

The function def home(request) is the standard way for a Django backend to render an HTML file (in our case, home.html).


The function def get_stock_data(request) takes an AJAX POST request from the home.html file and returns a JSON dictionary of stock data back to the AJAX loop. Let's unpack it here:

❚ The segment if request.is_ajax() makes sure the request is indeed an AJAX POST request from the frontend.

❚ ticker = request.POST.get('ticker', 'null') obtains the ticker string from the AJAX request. The ticker string is always AAPL when the page is first loaded, but will change to other strings based on user input at the frontend.

❚ The code block under if DATABASE_ACCESS == True checks if the data for a given ticker already exists in our local database. If yes, the get_stock_data function will simply get the data from the database and return it back to the AJAX loop. If not, the script continues to the next steps. (If you are familiar with SQL, the code StockData.objects.filter(symbol=ticker) is Django's way of saying SELECT * FROM StockData WHERE symbol = ticker.)


The part price_series = requests.get(f'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY_ADJUSTED&symbol={ticker}&apikey={APIKEY}&outputsize=full').json() queries Alpha Vantage's Daily Adjusted API and parse the data into a JSON dictionary through the .json() routine. Below is a sample JSON output from the daily adjusted API:

Please note that we are primarily interested the adjusted close field (5. adjusted close) of Alpha Vantage's daily adjusted API to remove any artificial price turbulences due to stock splits and dividend payout events. It is generally considered an industry best practice to use split/dividend-adjusted prices instead of raw close prices (4. close) to model stock price movements.

❚ The part sma_series = requests.get(f'https://www.alphavantage.co/query?function=SMA&symbol={ticker}&interval=daily&time_period=10&series_type=close&apikey={APIKEY}').json() queries Alpha Vantage's Simple Moving Average (SMA) API and parse the data into a JSON dictionary through the .json() routine. Below is a sample JSON output from the SMA API:


The remainder of the get_stock_data function (reproduced below) (1) packages up the adjusted close JSON data and the simple moving average JSON data into a single dictionary output_dictionary, (2) save the newly acquired stock data to database (so that we can recycle the data from the database next time without querying the Alpha Vantage APIs again), and (3) return the data back to the AJAX POST loop (via HttpResponse(json.dumps(output_dictionary), content_type='application/json')) for charting at the frontend.


This is it! We have implemented both the frontend (home.html) and the backend (views.py). These components can now "talk" to each other seamlessly and perform read/write interactions with the local SQLite database.


URL routing

Just one last thing: let's update urls.py with the latest URL routings for the views we just created in views.py:

❚ path("", stockVisualizer.views.home) makes sure the home function in views.py is called when a user visits the homepage in their web browser

❚ path('get_stock_data/', stockVisualizer.views.get_stock_data) makes sure the get_stock_data function in views.py is called when home.html makes an AJAX POST request to the /get_stock_data/ URL.


Running the website locally

Now we are ready to run the website in your local environment. Enter the following prompt in your command line window (please make sure you are still in the alphaVantage root directory):

(alphaVantage) $ python manage.py runserver


If you go to http://localhost:8000/ in your web browser (e.g., Chrome, Firefox, etc.), you should now see the website in full action!


👍288
|
Share project link


References

Project source code: link


Food for thought #1: richer data visualization

The current web application supports the visualization of adjusted close prices and simple moving average (SMA) values for a given stock. We will leave it to your creativitiy to enrich the visualization. For example, how about plotting cryptocurrency prices along with the stock prices? How about adding more technical indicators to the chart or enable users to draw support/resistance lines directly on the chart? We look forward to your creation!


Food for thought #2: data freshness vs. website speed trade-off

In the get_stock_data function of views.py, we first search the local database for existing data of a given ticker before querying the Alpha Vantage APIs. In general, accessing data via local databases or in-memory caches is often faster (and computationally cheaper) than querying an online API. On the other hand, querying the Alpha Vantage API will guarantee you the latest data for a given ticker, while data in the local database is static in nature and will gradually become outdated over time. The trade-off (fresh data but lower website speed vs. stale data but faster website speed) is a common dilemma faced by developers of data-intensitve applications. Can you find a way out of this dilemma? For example, write a cron job to refresh the database on a daily basis so that the local data won't get outdated? Overall, database optimization is one ofthe most challenging yet rewarding tasks in the software development process.



View other Alpha Academy projects →


If you are interested in translating this project into a language other than English, please let us know and we truly appreciate your help!

Wenn Sie daran interessiert sind, dieses Projekt ins Deutsche zu übersetzen, lassen Sie es uns bitte wissen und wir bedanken uns sehr für Ihre Hilfe!

Si está interesado en traducir este proyecto al español, háganoslo saber y realmente apreciamos tu ayuda.

Se você está interessado em traduzir este projeto para o português, por favor nos avise e nós realmente apreciamos sua ajuda!

如果您有兴趣把这篇文章翻译成中文, 请联系我们。我们非常感谢您的支持!

本プロジェクト和訳にご興味お持ちの方々、是非、お問い合わせください!ご連絡お待ちしております!

이 프로젝트를 한국어로 번역하는 데 관심이 있으시면 저희에게 알려주십시오. 도움을 주셔서 정말 감사합니다!


Disclaimer: All content from the Alpha Academy is for educational purposes only and is not investment advice.