How to Create Bollinger Bands and Moving Average in Julia with Plots and DataFrame?

Hi all,

I want to plot a graph with Bollinger Bands and Moving Average indicator, the data will be loaded from CSV.

Here are my conditions:

  1. I have this code to show graph and histogram from CSV data in Julia (previous post: DataFrames Plot: Plot the year for the x-tick at x-axis)
using CSV, Dates, DataFrames, Plots, Plots.PlotMeasures

filejak = "./csv/Jakarta Stock Exchange Composite Index Historical Data.csv"

dfjak = CSV.read(filejak, DataFrame)

dfjak.Price .= parse.(Float64, replace.(dfjak.Price, "," => ""))
dfjak[!,"Change %"] .= parse.(Float64, replace.(dfjak[!,"Change %"], "%" => ""))

dfjak.Dates = Date.(dfjak.Date, "mm/dd/yyyy")
tick_years = Date.(unique(Dates.year.(dfjak.Dates)))
DateTick = Dates.format.(tick_years, "yyyy")
xlims = extrema([tick_years; dfjak.Dates])

p1 = plot(dfjak.Dates, dfjak.Price, title="",
    xticks=(tick_years,DateTick), xlims=xlims,
    label="Jakarta Stock Exchange (Price)", xlabel="", ylabel="")
p2 = histogram(dfjak.Date, dfjak[!,"Change %"], title="",
    label="Jakarta Stock Exchange (% Change)", xlabel="", ylabel="")

plot(p1, p2, size=(1200,800), layout = (2, 1), 
    legend=:outerright, left_margin=10mm, bottom_margin=5mm,
     xaxis = "", yaxis = "Frequencies")

  1. Now I want to plot the graph with xtick is the year and ytick is the price along with the indicators: Moving Average and Bollinger Bands. But, I only have the code in Python (but it is scraping data from yfinance instead of from CSV), thus the code with PyCall for Bollinger Bands is:
using PyCall

ENV["PYTHON"] = "/home/browni/.julia/conda/3/bin/python3"
# the path is from the command 'which python3'

py"""

import matplotlib.pyplot as plt
import datetime as dt
import yfinance as yf

company = 'ATVI'

# Define a start date and End Date
start = dt.datetime(2017,1,1)
end =  dt.datetime(2023,1,1)

# Read Stock Price Data 
data = yf.download(company, start , end)

#data.tail(10)
#print(data)

# Creating and Plotting Bollinger Bands
data['middle_band'] = data['Close'].rolling(window=20).mean()
data['upper_band'] = data['Close'].rolling(window=20).mean() + data['Close'].rolling(window=20).std()*2
data['lower_band'] = data['Close'].rolling(window=20).mean() - data['Close'].rolling(window=20).std()*2

plt.figure(figsize=(10,10))
plt.plot(data['upper_band'], 'g--', label="upper")
plt.plot(data['middle_band'], 'r--', label="middle")
plt.plot(data['lower_band'], 'y--', label="lower")
plt.plot(data['Close'], label="Close")
plt.title("Activision Blizzard Stock Price 1/1/17 - 1/1/23")
plt.legend()
plt.show()

"""

code with PyCall for Moving Average is:

using PyCall

ENV["PYTHON"] = "/home/browni/.julia/conda/3/bin/python3"
# the path is from the command 'which python3'

py"""

import matplotlib.pyplot as plt
import datetime as dt
import yfinance as yf

company = 'ATVI'

# Define a start date and End Date
start = dt.datetime(2000,1,1)
end =  dt.datetime(2023,1,1)

# Read Stock Price Data 
data = yf.download(company, start , end)

#data.tail(10)
#print(data)

# Creating and Plotting Moving Averages
data["SMA1"] = data['Close'].rolling(window=50).mean()
data["SMA2"] = data['Close'].rolling(window=200).mean()
data['ewma'] = data['Close'].ewm(halflife=0.5, min_periods=20).mean()

plt.figure(figsize=(10,10))
plt.plot(data['SMA1'], 'g--', label="SMA1")
plt.plot(data['SMA2'], 'r--', label="SMA2")
plt.plot(data['Close'], label="Close")
plt.title("Activision Blizzard Stock Price 1/1/00 - 1/1/23")
plt.legend()
plt.show()

"""

Thanks before.

1 Like

You probably want to use RollingFunctions

julia> using RollingFunctions

julia> prices = rand(100);

julia> moving_average = rollmean(prices, 20);

julia> moving_std = rollstd(prices, 20);

julia> bollinger_high = moving_average .+ 2moving_std;

julia> bollinger_low = moving_average .- 2moving_std;

julia> using Plots

julia> plot([moving_average bollinger_low bollinger_high], label = ["Moving average" "Low" "High"], ls = [:solid :dash :dash])
5 Likes

It’s working:

thanks @nilshg

this is the code from CSV data:

using CSV, Dates, DataFrames, Plots, Plots.PlotMeasures, RollingFunctions

fileindy = "./csv/IDX-Stocks/INDY Historical Data.csv"

dfindy = CSV.read(fileindy, DataFrame)

dfindy.Price .= parse.(Float64, replace.(dfindy.Price, "," => ""))
dfindy[!,"Change %"] .= parse.(Float64, replace.(dfindy[!,"Change %"], "%" => ""))

dfindy.Dates = Date.(dfindy.Date, "mm/dd/yyyy")
tick_years = Date.(unique(Dates.year.(dfindy.Dates)))
DateTick = Dates.format.(tick_years, "yy")
xlimsindy = extrema([tick_years; dfindy.Dates])

p1 = plot(dfindy.Dates, dfindy.Price, title="",
    xticks=(tick_years,DateTick), xlims=xlimsindy,
    label="Indika Energy (Price)", xlabel="", ylabel="")

# Set up MA and Bollinger Band
prices = dfindy.Price;
moving_average = rollmean(prices, 20);
moving_std = rollstd(prices, 20);

bollinger_high = moving_average .+ 2moving_std;
bollinger_low = moving_average .- 2moving_std;

p2 = plot([moving_average bollinger_low bollinger_high], 
	label = ["Moving average" "Low" "High"], ls = [:solid :dash :dash])

plot(p1, p2, size=(900,800), layout = (2, 1), 
    legend=:outerright, left_margin=10mm, bottom_margin=5mm,
     xaxis = "", yaxis = "")

for anyone wants to try for their own research.