[Stock Analysis with Python] Weekly and Monthly Charts with Bollinger Bands to Understand Price Volatility
Table of Contents
Overview
In the previous article, we explained how to detect moving averages and golden cross/dead cross patterns. This time, we’ll explore fetching weekly and monthly data for longer-term trend analysis and using Bollinger Bands to statistically understand stock price movement ranges.
Motivation
In stock investing, it’s important to confirm long-term trends not only on daily charts but also on weekly and monthly charts. By taking a larger perspective, we can avoid being swayed by short-term price movements and better understand a company’s overall direction. Bollinger Bands, which combine moving averages with standard deviation, allow us to statistically understand price movement ranges. When prices approach the upper or lower bands, we can use them as reference points for trading decisions.
Like the previous article, we’ll continue our analysis using modern Python libraries: Polars, Plotly, marimo, kand, and yfinance-pl.
Libraries Used
The libraries are as follows:
| Library | Related Library | Description |
|---|---|---|
| polars | pandas | A library for high-speed data frame operations |
| plotly | matplotlib | A visualization library that allows users to interact with graphs |
| marimo | jupyter | A notebook that runs in .py format and allows interactive code execution |
| kand | ta-lib-python | A Rust-based technical analysis library that can be used in Python and Web through PYO3 and Wasm |
| yfinance-pl | yfinance | A Python library wrapping yfinance-rs that allows handling Yahoo Finance data with Polars |
Notebook and Code
The HTML version of the marimo notebook is available here. Here’s also a link to the Python code on GitHub.
Explanation
Fetching Weekly and Monthly Data
With yfinance-pl, you can fetch timeframes other than daily data by specifying the interval parameter in the history() method. Use 1d for daily, 1wk for weekly, and 1mo for monthly data.
import yfinance_pl as yf
ticker = yf.Ticker("8381.T")
# Fetch daily data (default)
hist_daily = ticker.history(period="1y", interval="1d")
# Fetch weekly data
hist_weekly = ticker.history(period="2y", interval="1wk")
# Fetch monthly data
hist_monthly = ticker.history(period="5y", interval="1mo")By using weekly or monthly data, you can eliminate short-term noise and identify longer-term trends. For example, viewing moving averages on weekly charts allows you to understand trends spanning several months to half a year.
Calculating Bollinger Bands
Bollinger Bands display a center line (moving average) with bands above and below it calculated using standard deviation. Typically, ±2σ (two standard deviations) is used. Statistically, about 95% of prices are expected to fall within these bands.
Using the kand library, you can calculate Bollinger Bands easily.
import kand as ka
import polars as pl
import yfinance_pl as yf
ticker = yf.Ticker("8381.T")
hist = ticker.history(period="1y")
# Convert closing price data to NumPy array
close = hist["close.amount"].to_numpy().astype("float64")
# Calculate Bollinger Bands (period 20, standard deviation 2)
bbands_result = ka.bbands(close, period=20, std_dev=2.0)
# Add results to DataFrame
hist_with_bbands = hist.with_columns(
bb_upper=pl.Series(bbands_result.upper), # Upper band (+2σ)
bb_middle=pl.Series(bbands_result.middle), # Center line (moving average)
bb_lower=pl.Series(bbands_result.lower), # Lower band (-2σ)
)The bbands() function accepts period (moving average period) and std_dev (standard deviation multiplier) parameters. Typically, a 20-day period with 2x standard deviation is used, but you can adjust these based on the stock and timeframe.
Understanding Bollinger Bands
Bollinger Bands can be interpreted in the following ways:
1. Band Width (Volatility)
The width of the bands indicates price volatility.
- Wide bands: Large price movements, strong trend, or unstable market
- Narrow bands (Squeeze): Small price movements, with a potential for a large move afterward
2. Band Walk
When price moves along the upper or lower band, it’s called a “band walk.”
- Walking along the upper band: Strong uptrend
- Walking along the lower band: Strong downtrend
3. Band Deviation
- Price exceeds the upper band: Potential overbought condition. Watch for reversal signals
- Price falls below the lower band: Potential oversold condition. Watch for rebound signals
However, during strong trends, prices can remain outside the bands for extended periods, so it’s important to use other indicators in combination with Bollinger Bands.
Visualizing the Chart
Using Plotly, you can display candlesticks and Bollinger Bands simultaneously.
import plotly.graph_objects as go
# Data preparation
df_plot = hist_with_bbands.with_columns(
[
pl.col("open.amount").cast(pl.Float64),
pl.col("high.amount").cast(pl.Float64),
pl.col("low.amount").cast(pl.Float64),
pl.col("close.amount").cast(pl.Float64),
]
)
dates = df_plot["date"].to_list()
# Create chart
fig = go.Figure()
# Candlestick chart
fig.add_trace(go.Candlestick(
x=dates,
open=df_plot["open.amount"],
high=df_plot["high.amount"],
low=df_plot["low.amount"],
close=df_plot["close.amount"],
increasing_line_color="red",
decreasing_line_color="green",
name="Stock Price",
))
# Upper Bollinger Band
fig.add_trace(go.Scatter(
x=dates,
y=df_plot["bb_upper"],
mode="lines",
name="BB Upper (+2σ)",
line=dict(color="rgba(250, 128, 114, 0.5)", width=1),
))
# Middle Bollinger Band
fig.add_trace(go.Scatter(
x=dates,
y=df_plot["bb_middle"],
mode="lines",
name="BB Middle (SMA20)",
line=dict(color="blue", width=1.5),
))
# Lower Bollinger Band
fig.add_trace(go.Scatter(
x=dates,
y=df_plot["bb_lower"],
mode="lines",
name="BB Lower (-2σ)",
line=dict(color="rgba(250, 128, 114, 0.5)", width=1),
fill="tonexty", # Fill between middle and lower band
fillcolor="rgba(250, 128, 114, 0.1)",
))
fig.update_layout(
title="Stock Price with Bollinger Bands",
xaxis_title="Date",
yaxis_title="Price",
xaxis_rangeslider_visible=False,
)
fig.show()This code displays candlesticks and three Bollinger Band lines (upper, middle, lower). By using fill="tonexty", we lightly shade the area between the middle and lower lines, making the band range visually clearer.
Summary
We’ve explained how to fetch weekly and monthly data and understand price movement ranges using Bollinger Bands. Weekly and monthly charts let you confirm long-term trends, while Bollinger Bands help you understand price movement ranges statistically.
By combining Bollinger Bands with the moving averages and golden cross/dead cross patterns from the previous article, you can perform more comprehensive analysis. We’ll continue to analyze stocks using modern Python libraries and explore other technical indicators.
Reference Book: 『Pythonで実践する株式投資分析』(Kanemitsu Katafuchi (Author), Yoshihiro Yamada (Editor))
![[Stock Analysis with Python] Detecting Moving Averages and Golden Cross Using Modern Libraries](https://b.rmc-8.com/img/2025/12/01/5383d87b9096bc828d358edd077fef67.png)
![[Python Stock Analysis] Calculating and Visualizing Ichimoku Cloud with Polars](https://b.rmc-8.com/img/2025/12/02/00541cf97f979f588ad2cad0ac6d6d7f.png)

![[Python] Automatically Record Sleep Time to Toggl](https://pub-21c8df4785a6478092d6eb23a55a5c42.r2.dev/img/eyecatch/garmin_toggl.webp)


Loading comments...