# -*- coding: utf-8 -*-
"""
Created on Wed May 27 16:32:43 2026

@author: cting
"""

import pandas as pd
import statsmodels.api as sm

###############################################################################
def read_jp(ticker, datadir):
    filename = datadir + ticker  + '.csv'
    df = pd.read_csv(filename)
    df.index = pd.to_datetime(df["Date"], format="%Y%m%d")
    n = len(df)
    spfac = [1.0] * n
    for i in range(n):
        if df.Split.iloc[i] != 0.0:
            print('Stock Split:', df.Date.iloc[i], df.Split.iloc[i] )
            for j in range(i-1, -1, -1):
                spfac[j] *= df.Split.iloc[i]
    
    price = df.Close/spfac
    df['Price'] = price
    return(df)


def read_French(filename):   
    
    fd = open(filename)
    lines = fd.readlines()
    fd.close()
    
    N = len(lines)
    for i in range(N):
        if lines[i].find('Mkt-RF') != -1:
            I = i+1
            break
    
    for i in range(I, N):
        if len(lines[i]) == 1:
            J = i
            break
    
    date, marketpremium, riskfree = [], [], []
    for i in range(I, J):
        line = lines[i][:-1]    
        itemlist = line.split(',')
        
        date.append(itemlist[0].rstrip())
        marketpremium.append(float(itemlist[1].rstrip())/100)
        riskfree.append(float(itemlist[-1].rstrip())/100)
        
    French = pd.DataFrame({'Date':date, 'Mkt-RF': marketpremium,
                           'RF': riskfree})
    French['Date'] = (pd.to_datetime(French.Date, format='%Y%m') + 
                      pd.offsets.MonthEnd(0)).dt.strftime('%Y%m%d')
    
    French.index =pd.to_datetime(French["Date"], format="%Y%m%d")
    
    return(French)


###############################################################################
datadir = 'C:\\YahooJap\\stocks\\'
ticker = '1329'
df = read_jp(ticker, datadir)
filename = 'Japan_3_Factors.csv'
French = read_French(filename)

# -------------------------------------------------------------------------
# Step 1: Resample Daily Prices to Monthly Returns
# -------------------------------------------------------------------------
# We use the last 'Adj Close' price of each month to calculate the 1-month return.
# .pct_change() calculates the monthly asset return (R_i)

monthly_asset_returns = (
    df['Price']
    .resample('ME')  # 'ME' stands for Month End (replaces the deprecated 'M')
    .last()
    .pct_change(fill_method=None)
    .dropna()
    .to_frame(name='R_i')
)

#mdf = df.resample('ME').last()
  


#inter_df = pd.merge(
#    mdf, French, left_index=True, right_index=True, how="inner"
#)

# -------------------------------------------------------------------------
# Step 2: Merge Asset Returns with Fama-French Factors
# -------------------------------------------------------------------------
# We merge on the datetime index. Since both are now set to the calendar 
# month-end, they will align flawlessly.
merged_df = pd.merge(monthly_asset_returns, French, left_index=True, 
                     right_index=True, how='inner')

# -------------------------------------------------------------------------
# Step 3: Calculate the Dependent Variable (Excess Asset Return: R_i - RF)
# -------------------------------------------------------------------------
merged_df['Excess_Return'] = merged_df['R_i'] - merged_df['RF']

# -------------------------------------------------------------------------
# Step 4: Run the CAPM Linear Regression
# -------------------------------------------------------------------------
# CAPM Formula: R_i - RF = alpha + beta * (Mkt-RF) + epsilon
X = merged_df['Mkt-RF']  # Independent Variable (Market Excess Return)
X = sm.add_constant(X)   # Adds a constant term to estimate the intercept (alpha)
y = merged_df['Excess_Return'] # Dependent Variable

# Change the fit method to use Newey-West standard errors with a 3-month lag window
model = sm.OLS(y, X).fit(cov_type='HAC', cov_kwds={'maxlags': 3})

# -------------------------------------------------------------------------
# Step 5: Extract and Display Results
# -------------------------------------------------------------------------
print(model.summary())

alpha = model.params['const']
beta = model.params['Mkt-RF']
p_alpha = model.pvalues['const']
p_beta = model.pvalues['Mkt-RF']

print("\n" + "="*40)
print(f"Estimated CAPM Beta (Systematic Risk): {beta:.4f} (p-val: {p_beta:.4f})")
print(f"Estimated CAPM Alpha (Abnormal Return): {alpha:.4f} (p-val: {p_alpha:.4f})")
print("="*40)
