<jupyter_start><jupyter_text>Data Prep<jupyter_code># load data
nike_stock = pd.read_csv(r'data/nike_stock.csv')
nike_stock.head(10)
# cleaning
nike_stock['Date'] = nike_stock['Date'].astype('datetime64[ns]')
nike_stock['Date'] = nike_stock['Date'].dt.date.astype('datetime64[ns]')
nike_stock.columns = ['Date', 'Price']
# imputations
dates = pd.DataFrame((pd.date_range(start=nike_stock['Date'].min(), end=nike_stock['Date'].max())), columns=['Date'])
nike_stock = nike_stock.merge(dates, on='Date', how='right')
nike_stock['Price'] = nike_stock['Price'].interpolate()
# trend, seasonal, residual
result = sm.tsa.seasonal_decompose(nike_stock.set_index('Date'), period=253)
trend = result.trend
seasonal = result.seasonal
residual = result.resid
'''
The NYSE and NASDAQ average about 253 trading days a year. 
This is from 365.25 (days on average per year) * 5/7 (proportion work days per week) - 6 (weekday holidays) - 3*5/7 (fixed date holidays) = 252.75 ≈ 253. 
The holidays where the stock exchange is closed are 
New Year's Day, 
Martin Luther King, Jr. Day, 
Presidents' Day, 
Good Friday, 
Memorial Day, 
Independence Day, 
Labor Day, 
Thanksgiving Day, 
and Christmas Day; 
there are also some holidays where trading is permitted, including Columbus Day, Veterans Day, and New Year's Eve.
'''
# plot
fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, ncols=1, sharex=True, figsize=(20, 10))
sns.lineplot(data=trend, ax=ax1, label='trend')
sns.lineplot(data=seasonal, ax=ax2, label='seasonal')
sns.lineplot(data=residual, ax=ax3, label='residual')
ax1.grid()
ax2.grid()
ax3.grid()
plt.show();<jupyter_output><empty_output><jupyter_text>Train Test Split<jupyter_code># train val test split
def make_train_val_test(df, test_size=0.2, n_split=5, shuffle=False):
    '''get train, val, and test data.'''
    
    df = df.reset_index(drop=True)
    if test_size < 1:
        test_size = int(len(df) * test_size)
        #print(test_size)
    
    # test set
    test = df.iloc[-test_size:, :]
    
    # train/val set
    train = df.loc[~df.index.isin(test.index)]
    bags = []
    
    for b in range(n_split):
        bags.append(train.iloc[int(b/5 * len(train)):int((b + 1)/5 * len(train)), :])
    if shuffle:
        random.shuffle(bags)
    
    train = pd.concat(bags[:n_split-1], axis=0)
    val = bags[n_split-1]
    
    return train, val, test

train, val, test = make_train_val_test(nike_stock)<jupyter_output><empty_output><jupyter_text>Modeling  ARMA<jupyter_code># train
arma = ARMA(train.set_index('Date'), order=(5, 0)).fit()
print(f'AIC: {arma.aic}')
# predict train
train_pred = arma.predict(start=train.index[0], end=train.index[-1])
train_pred = train_pred.reset_index()
train_pred.columns= ['Date', 'Price']
train_pred.loc[0, 'Price'] = np.NaN
# predict validation
val_pred = arma.predict(start=val.index[0], end=val.index[-1])
val_pred = val_pred.reset_index()
val_pred.columns= ['Date', 'Price']
# plot prediction
plt.figure(figsize=(15, 5))
sns.lineplot(data=train, x='Date', y='Price')
sns.lineplot(data=train_pred, x='Date', y='Price', color='green', label='ground truth train')
sns.lineplot(data=val, x='Date', y='Price', color='black', label='ground truth test')
sns.lineplot(data=val_pred, x='Date', y='Price', color='red', label='prediction')<jupyter_output><empty_output><jupyter_text>Conclusion: Obey Stationary Assumption, ARMA IS Aparrently NOT Working Well...  ARIMA<jupyter_code># train
ps = range(10)
ds = range(10)
qs = range(10)
parameters_list = []
for p in ps:
    for d in ds:
        for q in qs:
            parameters_list.append([p, d, q])

results = []
best_params = None
best_model = None
best_aic = np.inf
for params in parameters_list:  
    try:
        model = sm.tsa.SARIMAX(
            train.set_index('Date'), 
            order=(params[0], params[1], params[2]), 
            enforce_stationarity=False,
            enforce_invertibility=False
        ).fit()
        
        aic = model.aic
        if aic < best_aic:
            best_model = model
            best_aic = aic
            best_params = params
        results.append([params, aic])
        
    except ValueError:
        print('Params Error:', params)
        continue

best_model.summary()
# predict train
pred_train = best_model.predict(start=0, end=9345).reset_index()
pred_train.columns = ['Date', 'Pred_Price']
pred_train['Period'] = 'train'
pred_train
# predict val
pred_val = best_model.predict(start=9346, end=11682).reset_index()
pred_val.columns = ['Date', 'Pred_Price']
pred_val['Period'] = 'val'
pred_val
# predict test
pred_test = best_model.predict(start=11683, end=14602).reset_index()
pred_test.columns = ['Date', 'Pred_Price']
pred_test['Period'] = 'test'
pred_test
pred_results = pd.concat([
    pred_train,
    pred_val,
    pred_test
], axis=0)

pred_results
model_updated = sm.tsa.SARIMAX(
    pd.concat([train, val], axis=0).set_index('Date'), 
    order=(2,0,0),             
    enforce_stationarity=False,
    enforce_invertibility=False
).fit()
model_updated.summary()
# updated predict test 
pred_test_updated = model_updated.predict(start=11683, end=14602).reset_index()
pred_test_updated.columns = ['Date', 'Pred_Price']
pred_test_updated['Period'] = 'test_updated'
pred_test_updated
# plot prediction
plt.figure(figsize=(15, 5))
sns.lineplot(data=train, x='Date', y='Price', color='black', label='ground truth')
sns.lineplot(data=pred_train, x='Date', y='Pred_Price', color='yellow', label='prediction train')
sns.lineplot(data=val, x='Date', y='Price', color='black')
sns.lineplot(data=pred_val, x='Date', y='Pred_Price', color='orange', label='prediction val')
sns.lineplot(data=test, x='Date', y='Price', color='black')
sns.lineplot(data=pred_test, x='Date', y='Pred_Price', color='red', label='prediction test')
sns.lineplot(data=pred_test_updated, x='Date', y='Pred_Price', color='green', label='update prediction test');

final_results = nike_stock.merge(pred_results, on='Date')
final_results<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15811465819822831, 'fraction_numerical': 0.019555406986461642, 'mean_word_length': 4.860920666013712, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '546492', 'license': 'MIT', 'n_tokens_mistral': 2231, 'n_tokens_neox': 2136, 'n_words': 446, 'path': 'Nike_Stock/nike_stock_prediction.ipynb', 'repo_name': 'ryq99/Swoosh_Spirit', 'size': '5983'}