This purpose of this project was to create stock price movement charts with widgets for interactivity using the available python libraries.

Price Movement Charts

Price movement charts help with timing the market for buying or selling opportunities by determining up and down trends in price movement. These charts can typically be used with any financial time series like stocks, bonds, options, futures or commodities.

Renko

Is a type of price movement chart that has no time dimension. The key parameter it requires is the box size which signifies each brick (price movement size). The box size can be set to a specific value, or it be set to be equal to the ATR (average true range) which is derived from the closing price of the stock. With these charts its able to quickly tell the direction of trend changes.

PNF

PNF otherwise known as Point and Figure Chart is very similar to the renko chart, in that it also does not have a time dimension. An X represents when the price has moved higher, and an O represents when the price has dropped. The PNF also has a box size that can be set as a specific value, or be equal to the ATR (average true range).

OHLC

This is a type of price movement chart that captures the open, high, low and closing prices for each given trading day.

The vertical line represents the range in prices from high to low for the day. The horizontal lines extending out from the vertical line, represents open price for the left, and close price for the right. OHLC price Indicator .png

Candlestick

Also known as Japanese candlesticks are a type of price movement chart that takes into consideration both price, time and volume. It helps to determine the sentiment of the market - Bullish or Bearish. Bullish - would indicate a buy, while Bearish - would indicate short or sell for a stock trader.

Candlestick patterns can help determine price direction and momentum. One key thing to note when using candlesticks to understand price movement, it is important to first identify the market trend, before finding candlestick patterns in the data. Candlestick patterns are also best suited for identifying short term price movements.

Long and short days

Long days refers to large price movement within the trading day, and short days refers to low price movement within the trading day. This comparison however is best suited for short-term price movement of about 5-10days. Candlestick indicator .png

Load required libraries

  • Pandas_datareader to import historical data on stocks from yahoo.
  • Pandas for working with large data sets.
  • Datetime for handling date datatypes.
  • Matplotlib for data visualization.
  • ipwidgets for interactive widgets
  • Numpy for handling numeric arrays.
  • mplfinance for creating price movement charts
!pip install mplfinance
Requirement already satisfied: mplfinance in /usr/local/lib/python3.6/dist-packages (0.12.7a0)
Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from mplfinance) (1.1.2)
Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (from mplfinance) (3.2.2)
Requirement already satisfied: numpy>=1.15.4 in /usr/local/lib/python3.6/dist-packages (from pandas->mplfinance) (1.18.5)
Requirement already satisfied: python-dateutil>=2.7.3 in /usr/local/lib/python3.6/dist-packages (from pandas->mplfinance) (2.8.1)
Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.6/dist-packages (from pandas->mplfinance) (2018.9)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->mplfinance) (2.4.7)
Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->mplfinance) (0.10.0)
Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->mplfinance) (1.2.0)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.7.3->pandas->mplfinance) (1.15.0)
from pandas_datareader import data
import numpy as np
from datetime import datetime 
from datetime import date, timedelta
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

# import ipwidgets library and functions
from __future__ import print_function
from ipywidgets import interact, interactive, fixed
import ipywidgets as widgets
from IPython.display import display

import mplfinance as mpf
mpf.__version__
'0.12.7a0'

Create widgets and dataframe for the stock data

Instructions for use.

  1. Insert tuple of stock list.
  2. Select stock from dropdown.
  3. Select number of calendar days for dates from the last trading day.
  4. Rerun all code after.

Create widget for stock list and number of calendar days

options = ('MMM', 'AOS', 'AAN', 'ABB', 'ABT', 'ABBV', 'ABM', 'ACN', 'AYI', 'GOLF', 'ADCT', 'ADT', 'AAP', 'ADSW', 'WMS', 'ACM', 'AEG', 'AER', 'AJRD', 'AMG', 'AFL', 'AGCO', 'A', 'AEM', 'ADC', 'AL', 'APD', 'AGI', 'ALK', 'ALB', 'ACI', 'AA', 'ALC', 'ARE', 'AQN', 'BABA', 'Y')

# create dropdown for selected stocks
stock_ticker = widgets.Dropdown(
    options= options,
    description='Select Stock Ticker',
    disabled=False,
    style = {'description_width': 'initial'}, 
    layout = {'width': '200px'}
)

# create selection slider for days
w = widgets.IntSlider(
    value=90,
    min=5,
    max=365,
    step=1,
    description = 'Calendar days',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d',
    style = {'description_width': 'initial','handle_color' : 'blue'}, 
    layout = {'width': '400px'}
)

# create function for time frame of selected calendar days from today
def timeframe(w):
    days = timedelta(w)
    start = date.today() - days
    today = date.today()
    print('Start Date: ',start, '                 ' ,'Last Date: ',today)
       
dates = widgets.interactive_output(timeframe, {'w': w} )

display(stock_ticker, w, dates)

Download data for the stock

v = widgets.Text(
    value=stock_ticker.value,
    description='Stockticker:',
    disabled=True
)

# create function to load stock data from yahoo 
def load_stock_data(stock_ticker, w):
    start = date.today() - timedelta(w)
    today = date.today()
    stock_data = data.DataReader(stock_ticker, start=start, end=today,
                       data_source='yahoo')
    return stock_data

# create dataframe for selected stock
stock = load_stock_data(stock_ticker.value, w.value)

# display ticker and dataframe

display(v, stock)
High Low Open Close Volume Adj Close
Date
2020-08-10 251.750000 246.100006 249.339996 248.130005 13621700 248.130005
2020-08-11 252.880005 247.830002 251.289993 248.419998 10681800 248.419998
2020-08-12 256.079987 248.679993 249.250000 255.190002 11120400 255.190002
2020-08-13 256.970001 252.880005 256.390015 253.720001 8794500 253.720001
2020-08-14 255.770004 251.639999 255.490005 253.970001 7876400 253.970001
2020-08-17 257.375000 250.085007 253.000000 256.959991 9760000 256.959991
2020-08-18 261.420013 256.059998 258.709991 259.200012 13267800 259.200012
2020-08-19 261.290009 257.380005 260.890015 260.589996 14096500 260.589996
2020-08-20 258.880005 254.179993 256.890015 257.970001 21460800 257.970001
2020-08-21 267.429993 258.309998 259.029999 265.799988 25648200 265.799988
2020-08-24 276.970001 271.619995 273.239990 276.019989 22475800 276.019989
2020-08-25 289.119995 276.040009 278.059998 286.000000 27535500 286.000000
2020-08-26 292.480011 284.100006 289.260010 291.959991 19530300 291.959991
2020-08-27 290.250000 282.100006 290.170013 284.170013 14805800 284.170013
2020-08-28 289.500000 283.570007 285.089996 289.000000 9689600 289.000000
2020-08-31 289.190002 283.609985 288.619995 287.029999 13253800 287.029999
2020-09-01 298.000000 288.869995 289.200012 298.000000 13815900 298.000000
2020-09-02 299.000000 289.790009 299.000000 296.070007 12638600 296.070007
2020-09-03 290.733002 278.160004 289.000000 282.500000 16766200 282.500000
2020-09-04 283.779999 267.390015 279.600006 281.390015 15885800 281.390015
2020-09-08 273.970001 266.589996 270.230011 270.019989 12734000 270.019989
2020-09-09 275.640015 270.880005 274.450012 273.149994 9465700 273.149994
2020-09-10 277.100006 267.399994 274.899994 267.549988 10676800 267.549988
2020-09-11 274.529999 268.119995 272.630005 271.609985 9412800 271.609985
2020-09-14 276.290009 271.760010 275.359985 274.100006 7883300 274.100006
2020-09-15 279.100006 274.799988 278.000000 277.959991 8291400 277.959991
2020-09-16 283.605011 278.000000 281.029999 278.140015 9583500 278.140015
2020-09-17 275.899994 272.321014 273.109985 275.720001 8016900 275.720001
2020-09-18 277.269989 270.549988 275.980011 272.410004 11753500 272.410004
2020-09-21 274.220001 266.399994 269.100006 273.820007 9076400 273.820007
2020-09-22 276.320007 270.049988 276.019989 275.290009 9673300 275.290009
2020-09-23 277.829987 271.500000 275.399994 272.950012 7353200 272.950012
2020-09-24 271.250000 267.334015 267.929993 269.730011 9562100 269.730011
2020-09-25 271.809998 264.559998 267.570007 271.089996 11466600 271.089996
2020-09-28 278.839996 274.199005 275.529999 276.010010 8761700 276.010010
2020-09-29 279.299988 274.899994 275.429993 276.929993 7673300 276.929993
2020-09-30 295.000000 283.709991 284.010010 293.980011 24709900 293.980011

Visualize percentage daily changes for the selected stock over time

stock_data_return = stock['Adj Close'].pct_change().mul(100)
stock_data_return.plot(figsize=[12,6], grid=True, title = stock_ticker.value)
plt.ylabel("Adjusted Close Returns")

plt.show()

Visualise the stock price data using different price movement indicators

Instruction for use.

  1. Select Chart Type and style.

All the charts assume 10, 20 or 50 days for moving average

chart_types = [('Line Price Chart', 'line'),
               ('Renko Price Chart', 'renko'), 
               ('PNF Price Chart','pnf'),
               ('Candlestick Price Chart', 'candle'),
               ('OHLC Price Chart', 'ohlc')]

chart = widgets.Dropdown(
    options= chart_types,
    description='Select Chart Type',
    disabled=False,
    style = {'description_width': 'initial'}, 
    layout = {'width': '300px'}
)

# create drop down using mplfinance library built-in styles

style_options = ['binance',
 'blueskies',
 'brasil',
 'charles',
 'checkers',
 'classic',
 'default',
 'mike',
 'nightclouds',
 'sas',
 'starsandstripes',
 'yahoo']

style_option = widgets.Dropdown(
    options= style_options,
    description='Select Style',
    disabled=False,
    style = {'description_width': 'initial'}, 
    layout = {'width': '300px'}
)

# create plot function using mplfinance library 
# fixed values for moving average (mav), figratio, and figscale, volume=True
# default settings for renko and pnf charts (bricksize = 'atr', box_size='atr')


def create_plot(chart, style_option):
    return mpf.plot(stock, type=chart, volume=True, mav = (10,20,50), figratio=(15, 8) , figscale=1.5, style=style_option, title = '\n'f'{stock_ticker.value}')
widgets.interactive(create_plot, chart=chart, style_option=style_option) 

References

  1. mplfinance Accessed September 25, 2020.

  2. Jupyter Widgets Accessed September 25, 2020.

  3. Datareader basic example (Yahoo Finance)

  4. Morris, Gregory L., 1948-, Candlestick charting explained timeless techniques for trading stocks and futures [electronic resource], New York : McGraw-Hill, c2006, 3rd ed.

  5. Price Movement ChartsAccessed September 25, 2020.

  6. Renko Charts Accessed September 25, 2020.

  7. PNF Charts Accessed September 25, 2020.