Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

*.png
.idea
111 changes: 97 additions & 14 deletions solution_skeleton.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,30 +76,113 @@ def generate_portfolio(df_train: pd.DataFrame, df_test: pd.DataFrame):

# <<--------------------- YOUR CODE GOES BELOW THIS LINE --------------------->>

#EXPLANATION
#https://maesela.notion.site/Prescient-48a940d3bff4497db8512468dbe7bc18?pvs=4

# This is your playground. Delete/modify any of the code here and replace with
# your methodology. Below we provide a simple, naive estimation to illustrate
# how we think you should go about structuring your submission and your comments:

# We use a static Inverse Volatility Weighting (https://en.wikipedia.org/wiki/Inverse-variance_weighting)
# strategy to generate portfolio weights.
# Use the latest available data at that point in time

# Define the column names
columns = list_stocks

# Create the empty DataFrame with specified columns
df_stock_accelerations = {key: [] for key in list_stocks}
count_a = 0
for stock_iterator in range(len(list_stocks)):

# stock k's returns
# k = stock_iterator
rk = df_returns[list_stocks[stock_iterator]]

# ema = exponential moving average return
# alpha = smoothing factor
def ema(returns_k, previous_ema):
alpha = 0.2
return (alpha * returns_k) + ( (1-alpha) * previous_ema )

ema_last_month = 0

for date_iterator in range(2, len(df_returns)):
# stock k's returns in month t-1
# t = date_iterator

rkt = rk[date_iterator-1]

# change in exponential moving average
delta_w = ema (rkt, ema_last_month) - ema_last_month

# acceleration at month t
beta = 15 # must be > 0 and a whole number. Beta is the time period
a_t = delta_w / beta
count_a += 1
print(count_a)

# append the acceleration
df_stock_accelerations[list_stocks[stock_iterator]].append(a_t)


# print(df_stock_accelerations)
num_accs = len(df_stock_accelerations[list_stocks[0]])
for row in range(num_accs):
accelerations = {stock: df_stock_accelerations[stock][row] if df_stock_accelerations[stock] else None for stock in list_stocks}

raw_weights = {key: 0 for key in list_stocks}

max_acceleration_key = max(accelerations, key=accelerations.get)

for key, single_acc in accelerations.items():
if single_acc < 0:
raw_weights[key] = 0
else:
raw_weight_k = 0.1 if (accelerations[key] / accelerations[max_acceleration_key] ) > 0.1 else (accelerations[key] / accelerations[max_acceleration_key] )
raw_weights[key] = raw_weight_k


sum_raw_weights = sum(raw_weights.values())
print("sum of raw weights", raw_weights)
weights = {key: 0 for key in list_stocks}
for key, value in raw_weights.items():
weights[key] = value / sum_raw_weights



print(weights)
df_weights = pd.DataFrame(columns=list_stocks)

# Convert the dictionary to a DataFrame
new_row_df = pd.DataFrame([weights])

# Add the new row using the `loc` indexer
df_weights = pd.concat([df_weights, new_row_df], ignore_index=True)

# df_weights = df_weights.append(weights, ignore_index=True)

# add to all weights
#df_this = pd.DataFrame(data=[[df_test.loc[i, 'month_end']] + df_w['weight'].to_list()], columns=df_latest.columns)
#df_weights = pd.concat(objs=[df_weights, df_this], ignore_index=True)

for i in range(len(df_test)):
# # delete this loop
# for i in range(len(df_test)):

# latest data at this point
df_latest = df_returns[(df_returns['month_end'] < df_test.loc[i, 'month_end'])]
# # latest data at this point
# df_latest = df_returns[(df_returns['month_end'] < df_test.loc[i, 'month_end'])]

# vol calc
df_w = pd.DataFrame()
df_w['vol'] = df_latest.std(numeric_only=True) # calculate stock volatility
df_w['inv_vol'] = 1/df_w['vol'] # calculate the inverse volatility
df_w['tot_inv_vol'] = df_w['inv_vol'].sum() # calculate the total inverse volatility
df_w['weight'] = df_w['inv_vol']/df_w['tot_inv_vol'] # calculate weight based on inverse volatility
df_w.reset_index(inplace=True, names='name')

# add to all weights
df_this = pd.DataFrame(data=[[df_test.loc[i, 'month_end']] + df_w['weight'].to_list()], columns=df_latest.columns)
df_weights = pd.concat(objs=[df_weights, df_this], ignore_index=True)
# # vol calc
# df_w = pd.DataFrame()
# df_w['vol'] = df_latest.std(numeric_only=True) # calculate stock volatility
# df_w['inv_vol'] = 1/df_w['vol'] # calculate the inverse volatility
# df_w['tot_inv_vol'] = df_w['inv_vol'].sum() # calculate the total inverse volatility
# df_w['weight'] = df_w['inv_vol']/df_w['tot_inv_vol'] # calculate weight based on inverse volatility
# df_w.reset_index(inplace=True, names='name')

# # add to all weights
# df_this = pd.DataFrame(data=[[df_test.loc[i, 'month_end']] + df_w['weight'].to_list()], columns=df_latest.columns)
# df_weights = pd.concat(objs=[df_weights, df_this], ignore_index=True)

# <<--------------------- YOUR CODE GOES ABOVE THIS LINE --------------------->>

Expand Down