Demystifying the PE Band Chart: A Comprehensive Guide for Stock Valuation

Apr 9, 2023

8 min read


programmer-with-chrome

What Idea about PE Band ?


In this article, we will demonstrate how to create a PE Band chart using data for five banks: SCB, KBANK, BBL, BAY, and KTB. We will import the data from an Excel file and store it in a pandas DataFrame, then stack and sort the data for further analysis.


First, let’s import the necessary libraries:


import pandas as pd
import numpy as np

Next, we will read the data from an Excel file and store it in a dictionary:


data = pd.read_excel('Bank_Data.xlsx',sheet_name=['SCB','KBANK','BBL','BAY','KTB'])

To verify that the data has been imported correctly, we can print the keys of the dictionary:


data.keys()

dict_keys(['SCB', 'KBANK', 'BBL', 'BAY', 'KTB'])

For a quick preview of the data, we can use the items() method:


The data provided is a dictionary containing stock data for multiple banks (SCB, KBANK, BBL, BAY, and KTB) over a period from 01/2016 to 10/2021.


data.items()

dict_items([('SCB',        Date  Prior    Open   High     Low  Close    P/E   PEG  P/BV  \
    0   01/2016  119.5  118.50  130.0  112.00  130.0   9.28     -  1.52   
    1   02/2016  130.0  130.50  142.0  125.00  138.5   9.98     -  1.53   
    2   03/2016  138.5  138.50  146.5  135.00  141.0  10.16     -  1.56   
    3   04/2016  141.0  139.50  140.0  127.00  133.5   9.62     -  1.48   
    4   05/2016  133.5  133.00  134.0  123.00  134.0  10.22     -  1.42   
    ..      ...    ...     ...    ...     ...    ...    ...   ...   ...   
    65  06/2021  102.5  102.50  106.5   97.50   98.0  11.87 -0.39  0.79   
    66  07/2021   98.0   98.25   99.5   90.25   93.5  11.33 -0.37  0.76   
    67  08/2021   93.5   93.50  108.0   92.50  106.5  12.70 -0.51  0.86   
    68  09/2021  106.5  106.00  137.0  101.50  122.0  14.55 -0.59  0.98   
    69  10/2021  122.0  121.50  127.5  120.50  126.0  15.02 -0.61  1.02   
    
            MarketCap  
    0   441283.807510  
    1   470136.979540  
    2   478623.206607  
    3   453249.885038  
    4   454947.450150  
    ..            ...  
    65  332771.012644  
    66  317491.655393  
    67  361634.880207  
    68  414267.186716  
    69  427851.814950  
    
    [70 rows x 10 columns]), ('KBANK',        Date  Prior   Open   High    Low  Close    P/E   PEG  P/BV  \
    0   01/2016  150.5  150.0  169.5  144.0  169.5   9.23     -  1.44   
    1   02/2016  169.5  169.0  173.5  159.0  170.5  10.34     -  1.43   
    2   03/2016  170.5  171.5  185.0  164.0  173.0  10.49     -  1.45   
    3   04/2016  173.0  171.5  172.0  154.0  166.0  10.06     -  1.39   
    4   05/2016  166.0  166.5  174.5  157.5  174.0  11.34     -  1.44   
    ..      ...    ...    ...    ...    ...    ...    ...   ...   ...   
    65  06/2021  119.0  120.0  130.5  118.0  118.0   8.34  -1.7  0.62   
    66  07/2021  118.0  118.5  123.0  101.5  103.0   7.28 -1.48  0.54   
    67  08/2021  103.0  102.5  126.0  101.0  123.0   7.39  0.19  0.64   
    68  09/2021  123.0  122.5  140.0  117.0  133.5   8.02   0.2  0.69   
    69  10/2021  133.5  133.5  145.5  132.5  141.0   8.47  0.21  0.73   
    
            MarketCap  
    0   405657.602713  
    1   408050.862906  
    2   414034.013389  
    3   397281.192038  
    4   416427.273582  
    ..            ...  
    65  279580.655974  
    66  244040.742079  
    67  291427.293939  
    68  316305.233666  
    69  334075.190613  
    
    [70 rows x 10 columns]), ('BBL',        Date  Prior   Open   High    Low  Close    P/E   PEG  P/BV  \
    0   01/2016  152.5  151.5  154.5  142.5  152.5   8.26     -  0.82   
    1   02/2016  152.5  152.0  167.5  146.0  161.5   9.02     -  0.85   
    2   03/2016  161.5  161.5  182.0  161.0  180.0  10.05     -  0.95   
    3   04/2016  180.0  178.5  179.5  161.0  164.0   9.16     -  0.87   
    4   05/2016  164.0  165.0  167.0  151.5  163.5   9.43     -  0.84   
    ..      ...    ...    ...    ...    ...    ...    ...   ...   ...   
    65  06/2021  115.0  116.0  123.5  113.0  113.0  13.13 -0.25  0.47   
    66  07/2021  113.0  113.5  114.5  100.5  102.5  11.91 -0.23  0.43   
    67  08/2021  102.5  102.0  119.5  100.0  114.0  11.05 -0.37  0.47   
    68  09/2021  114.0  115.0  123.5  111.0  116.5  11.29 -0.37  0.48   
    69  10/2021  116.5  116.0  124.5  115.0  122.5  11.87 -0.39  0.50   
    
            MarketCap  
    0   291098.541335  
    1   308278.127381  
    2   343591.720920  
    3   313050.234616  
    4   312095.813169  
    ..            ...  
    65  215699.247022  
    66  195656.396635  
    67  217608.089916  
    68  222380.197151  
    69  233833.254515  
    
    [70 rows x 10 columns]), ('BAY',        Date  Prior   Open   High    Low  Close    P/E   PEG  P/BV  \
    0   01/2016  29.75  30.00  31.75  27.50  31.00  13.06     -  1.23   
    1   02/2016  31.00  31.50  32.50  29.75  30.75  12.14     -  1.19   
    2   03/2016  30.75  31.00  36.00  30.75  34.50  13.62     -  1.33   
    3   04/2016  34.50  34.50  35.50  31.75  34.75  13.72     -  1.34   
    4   05/2016  34.75  35.00  38.00  33.00  37.75  14.27     -  1.42   
    ..      ...    ...    ...    ...    ...    ...    ...   ...   ...   
    65  06/2021  32.50  32.75  34.75  30.75  31.25  10.21 -0.61  0.78   
    66  07/2021  31.25  31.25  31.75  28.00  28.25   9.23 -0.55  0.71   
    67  08/2021  28.25  28.25  32.50  27.25  32.00   7.71  0.51  0.77   
    68  09/2021  32.00  32.00  36.00  30.25  32.50   7.83  0.52  0.78   
    69  10/2021  32.50  32.50  33.50  32.00  32.50   7.83  0.52  0.78   
    
            MarketCap  
    0   228028.614963  
    1   226189.674520  
    2   253773.781168  
    3   255612.721612  
    4   277680.006931  
    ..            ...  
    65  229867.555406  
    66  207800.270087  
    67  235384.376736  
    68  239062.257623  
    69  239062.257623  
    
    [70 rows x 10 columns]), ('KTB',        Date  Prior  Open  High   Low  Close   P/E   PEG  P/BV      MarketCap
    0   01/2016   16.7  16.6  17.8  15.4   17.4  8.18     -  1.02  243183.465750
    1   02/2016   17.4  17.5  18.2  17.0   17.7  8.32     -  1.04  247376.284125
    2   03/2016   17.7  17.8  19.1  17.6   18.7  9.18     -  1.06  261352.345375
    3   04/2016   18.7  18.6  18.6  17.1   17.5  8.59     -  1.00  244581.071875
    4   05/2016   17.5  17.5  17.8  16.2   17.1  8.51     -  0.91  238990.647375
    ..      ...    ...   ...   ...   ...    ...   ...   ...   ...            ...
    65  06/2021   10.9  10.9  11.4  10.6   10.7  9.44 -0.21  0.44  149543.855375
    66  07/2021   10.7  10.6  10.9   9.9   10.1  8.91  -0.2  0.41  141158.218625
    67  08/2021   10.1  10.1  11.4  10.0   11.2  9.88 -0.22  0.46  156531.886000
    68  09/2021   11.2  11.2  11.7  10.8   11.0  8.50 -0.34  0.45  153736.673750
    69  10/2021   11.0  10.9  12.0  10.9   11.5  8.88 -0.36  0.47  160724.704375
    
    [70 rows x 10 columns])])

data['SCB']

DatePriorOpenHighLowCloseP/EPEGP/BVMarketCap
001/2016119.5118.50130.0112.00130.09.28-1.52441283.807510
102/2016130.0130.50142.0125.00138.59.98-1.53470136.979540
203/2016138.5138.50146.5135.00141.010.16-1.56478623.206607
304/2016141.0139.50140.0127.00133.59.62-1.48453249.885038
405/2016133.5133.00134.0123.00134.010.22-1.42454947.450150
6506/2021102.5102.50106.597.5098.011.87-0.390.79332771.012644
6607/202198.098.2599.590.2593.511.33-0.370.76317491.655393
6708/202193.593.50108.092.50106.512.70-0.510.86361634.880207
6809/2021106.5106.00137.0101.50122.014.55-0.590.98414267.186716
6910/2021122.0121.50127.5120.50126.015.02-0.611.02427851.814950

70 rows × 10 columns


bank’s data is in a Pandas DataFrame with 70 rows and 10 columns. The columns represent the following attributes: Date, Prior, Open, High, Low, Close, P/E, PEG, P/BV, and MarketCap.


df = pd.concat(data,axis=1)
df.swaplevel(axis=1)

DatePriorOpenHighLowCloseP/EPEGP/BVMarketCapDatePriorOpenHighLowCloseP/EPEGP/BVMarketCap
SCBSCBSCBSCBSCBSCBSCBSCBSCBSCBKTBKTBKTBKTBKTBKTBKTBKTBKTBKTB
001/2016119.5118.50130.0112.00130.09.28-1.52441283.80751001/201616.716.617.815.417.48.18-1.02243183.465750
102/2016130.0130.50142.0125.00138.59.98-1.53470136.97954002/201617.417.518.217.017.78.32-1.04247376.284125
203/2016138.5138.50146.5135.00141.010.16-1.56478623.20660703/201617.717.819.117.618.79.18-1.06261352.345375
304/2016141.0139.50140.0127.00133.59.62-1.48453249.88503804/201618.718.618.617.117.58.59-1.00244581.071875
405/2016133.5133.00134.0123.00134.010.22-1.42454947.45015005/201617.517.517.816.217.18.51-0.91238990.647375
6506/2021102.5102.50106.597.5098.011.87-0.390.79332771.01264406/202110.910.911.410.610.79.44-0.210.44149543.855375
6607/202198.098.2599.590.2593.511.33-0.370.76317491.65539307/202110.710.610.99.910.18.91-0.20.41141158.218625
6708/202193.593.50108.092.50106.512.70-0.510.86361634.88020708/202110.110.111.410.011.29.88-0.220.46156531.886000
6809/2021106.5106.00137.0101.50122.014.55-0.590.98414267.18671609/202111.211.211.710.811.08.50-0.340.45153736.673750
6910/2021122.0121.50127.5120.50126.015.02-0.611.02427851.81495010/202111.010.912.010.911.58.88-0.360.47160724.704375

70 rows × 50 columns


Rename


df.swaplevel(axis=1)['P/E']

SCBKBANKBBLBAYKTB
09.289.238.2613.068.18
19.9810.349.0212.148.32
210.1610.4910.0513.629.18
39.6210.069.1613.728.59
410.2211.349.4314.278.51
6511.878.3413.1310.219.44
6611.337.2811.919.238.91
6712.707.3911.057.719.88
6814.558.0211.297.838.50
6915.028.4711.877.838.88

70 rows × 5 columns


df.swaplevel(axis=1)['P/E'].mean()
    SCB      10.543714
    KBANK    10.909429
    BBL      10.136714
    BAY      10.640714
    KTB       8.742571
    dtype: float64

df.swaplevel(axis=1)['P/E'].iloc[-1]
    SCB      15.02
    KBANK     8.47
    BBL      11.87
    BAY       7.83
    KTB       8.88
    Name: 69, dtype: float64

import plotly.express as px

df = df.iloc[-36:].swaplevel(axis=1)['P/E']

df.iloc[-1]
    SCB      15.02
    KBANK     8.47
    BBL      11.87
    BAY       7.83
    KTB       8.88
    Name: 69, dtype: float64

# Calculate the mean of P/E for each bank
avg = df.mean()
# Get the last row of the P/E dataframe
last=df.iloc[-1]
# Find the maximum P/E value for each bank
max=df.max()
# Find the minimum P/E value for each bank
min=df.min()

avg-min
  SCB      4.596667
    KBANK    4.157500
    BBL      4.361667
    BAY      4.031944
    KTB      3.205278
    dtype: float64


# Calculate the upper range by subtracting the average value from the maximum value
upper_range  = max-avg
# Calculate the lower range by subtracting the minimum value from the average value
lower_range = avg-min
# Calculate the transparent box value by subtracting 0 from the minimum value
transparent_box = min-0

pd.DataFrame([transparent_box,lower_range,upper_range])

SCBKBANKBBLBAYKTB
05.6200005.28005.3600004.2700004.840000
14.5966674.15754.3616674.0319443.205278
24.8033333.95254.2783333.9880562.364722


# Create a DataFrame with the transparent box, lower range, and upper range values
band = pd.DataFrame([transparent_box,lower_range,upper_range],index=['transparent','lower','upper'])
band

SCBKBANKBBLBAYKTB
transparent5.6200005.28005.3600004.2700004.840000
lower4.5966674.15754.3616674.0319443.205278
upper4.8033333.95254.2783333.9880562.364722

# Transpose the DataFrame so that the banks are in the index and the ranges are in the columns
band = band.T
# Print the band DataFrame
band

transparentlowerupper
SCB5.624.5966674.803333
KBANK5.284.1575003.952500
BBL5.364.3616674.278333
BAY4.274.0319443.988056
KTB4.843.2052782.364722

Visualization section


import plotly.graph_objs as go

# Create a bar chart using the band DataFrame
fig = px.bar(band,
            template='simple_white',
             color_discrete_map ={'transparent':'white',
                                 'lower':'skyblue',
                                 'upper':'blue'})

# Add a scatter plot layer to the bar chart to display the last P/E values
fig.add_traces(go.Scatter(x=band.index,
                         y=last,
                         mode='markers',
                         marker_symbol ='line-ew'))

# Update the marker style for the scatter plot
fig.update_traces(marker=dict(size=30,
                             line=dict(width=5,color='red')),
                 selector=dict(mode='markers'))

# Display the chart
fig.show()


# Calculate the historical P/E band by subtracting the minimum value from the maximum value
histband = max-min
histband
    SCB      9.40
    KBANK    8.11
    BBL      8.64
    BAY      8.02
    KTB      5.57
    dtype: float64

# Create a DataFrame with the minimum value and historical P/E band
band2 = pd.DataFrame([min,histband],index=['transparent','historical pe'])

# Transpose the DataFrame so that the banks are in the index and the ranges are in the columns
band2 = band2.T
band2

transparenthistorical pe
SCB5.629.40
KBANK5.288.11
BBL5.368.64
BAY4.278.02
KTB4.845.57

visualization section with pe band


# Create a bar chart using the band2 DataFrame
fig = px.bar(band2,
            template='simple_white',
             color_discrete_map ={'transparent':'white',
                                 'historical pe':'chocolate'})
# Add a scatter plot layer to the bar chart to display the last P/E values
fig.add_traces(go.Scatter(x=band2.index,
                         y=last,
                         mode='markers',
                         marker_symbol ='line-ew'))
# Update the marker style for the scatter plot
fig.update_traces(marker=dict(size=30,
                             line=dict(width=5,color='red')),
                 selector=dict(mode='markers'))
# Display the chart
fig.show()


These two visualization sections create bar charts using the band and band2 DataFrames. The first chart displays the P/E bands as transparent, lower, and upper ranges, while the second chart shows the historical P/E band. In both charts, a scatter plot layer is added to display the last P/E values with customized marker styles. Finally, the charts are displayed using the fig.show() function.


Conclusion


In conclusion, the PE Band chart is an invaluable tool for investors aiming to enhance their stock valuation analysis. By leveraging Python and pandas to import, store, and process data, you can efficiently create a PE Band chart to guide your investment decisions. As you continue to explore financial analysis techniques, remember that the PE Band chart is just one of many valuable resources available to support informed decision-making.