Я пытаюсь получить коэффициент простой линейной регрессии. Трюки
1) это W-месячная скользящая регрессия
2) для каждого окна должно быть минимальное количество записей, даты которых не расходятся больше года.
Однако мой код ломается: после перехода к функции calc_beta переданный в нее df не имеет всех исходных столбцов.
Я не могу прикрепить образец CSV-файла (форма 12 * 74). Но приложенное изображение показывает важную его часть (1 запас с данными за 12 месяцев, что означает, что он должен произвести только 1 бета в конце).
import pandas as pd
import numpy as np
# test_df is attached as csv
# 29639 PERMNO (stock identifier) only has 12 records but are consecutive in monthends (could produce 1 beta)
def calc_beta(df, indpt_var, dpt_vars):
print("@@@@@@@@@@@[enter image description here][1]@@@@@@@INSIDE calc_beta function@@@@@@@@@@@@@@")
print(df)
print("the shape is:", df.shape)
print("the columns are:", df.columns)
print("the len of columns is:", len(df.columns))
print("the indpt_var has dtype:", df[indpt_var].values.dtype)
print("the independent var is", indpt_var)
print("the dependent vars are", dpt_vars)
X = np.hstack((np.ones((df.shape[0], 1)), df[dpt_vars].values.astype(float)))
y = df[indpt_var].values.astype(float)
coeffs = list(np.dot(np.linalg.inv(np.dot(X.T, X)), np.dot(X.T, y)))[1:]
return {df["w_pos"].unique(): coeffs}
def monthend_check(df, w, min_w, direction):
df.reset_index(inplace=True)
achor_date = np.sort(df.monthend.values)[-1]
if direction == "up":
boundary_date = achor_date - relativedelta(months=w)
check_result = (boundary_date <= df.monthend) & (df.monthend <= achor_date)
else:
boundary_date = achor_date + relativedelta(months=w)
check_result = (achor_date <= df.monthend) & (df.monthend <= boundary_date)
# if it fails the check, then return the w_pos
if sum(check_result) < min_w:
return int(df.w_pos.unique())
def rollx(df, w, min_w, user_func, *args, direction="up"):
# create windows
if direction == "up":
paper_stack = np.dstack([df.values[i - w + 1:i + 1, ].T for i in range(w - 1, df.shape[0])]).T
new_df = pd.DataFrame(paper_stack.reshape(-1, df.shape[1]))
new_df.index = np.repeat(range(w - 1, df.shape[0]), w)
else:
paper_stack = np.dstack([df.values[i:i + w, ].T for i in range(df.shape[0] - w + 1)]).T
new_df = pd.DataFrame(paper_stack.reshape(-1, df.shape[1]))
new_df.index = np.repeat(range(df.shape[0] - w + 1), w)
# admin adj. to the new_df
new_df.columns = df.columns.tolist()
new_df.reset_index(inplace=True)
new_df.rename(columns={"index": "w_pos"}, inplace=True)
# check whether it meets the min_w requirement within each window created (identified by "w_pos")
nan_idx = list(new_df.groupby("w_pos").apply(monthend_check, w=w, min_w=min_w, direction=direction))
# for the groups whose "w_pos" is NOT in nan_idx & df_safe is not empty, apply function
df_safe = new_df.loc[(~new_df.w_pos.isin(nan_idx)),]
print(">>before the check gate, df_safe is")
print(df_safe)
print("is current df_safe empty?", df_safe.empty)
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
if not df_safe.empty:
print(">> at the check gate, PERMNO", df_safe.PERMNO.unique(), "passed the check!")
print(">> current w_pos are", df_safe.w_pos.unique())
print(">> df_safe that passed the check is:")
print(df_safe)
calc_result = df_safe.groupby("w_pos").apply(user_func, args[0], args[1])
# assuming first is indept_var, the second one is dept_vars
print("the calc_result is", calc_result)
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
return np.nan
indpt_var = ["stk_exret"]
dpt_vars = ["mkt_exret", "SMB", "HML"]
add_vars = (indpt_var, dpt_vars)
test_df.groupby("PERMNO").apply(rollx, 12, 10, calc_beta, *add_vars)
Показано 3 ошибки:
return {df ["w_pos"]. Unique (): coeffs}
TypeError: unhashable тип: 'numpy.ndarray'
KeyError: 'w_pos'
AttributeError: у объекта «DataFrame» нет атрибута «PERMNO»