<jupyter_start><jupyter_text>Lookback WindowIn order to capture the past as features, we create the below function. It takes as input some number of seconds to look back, defaulted to 60 seconds.<jupyter_code>def lookback(dataset, timesteps = 60):
    # this uses the shift method of pandas dataframes to shift all of the columns down one row
    # and then append to the original dataset
    data = dataset
    for i in range(1, timesteps):
        step_back = dataset.shift(i).reset_index()
        step_back.columns = ['index'] + [f'{column}_-{i}' for column in dataset.columns if column != 'index']
        data = data.reset_index().merge(step_back, on='index', ).drop('index', axis=1)
        
    return data.dropna()
        
features = lookback(data)
### split data into features and target
target = features['price_high'].values
features = features.drop('price_high', axis=1).values
model = Sequential()
model.add(Dense(32, input_dim=features.shape[1]))
model.add(Dense(16))
model.add(Dense(8))
model.add(Dense(1, activation='relu'))

model.compile(
    loss='mse',
    optimizer=Adam(lr=0.01), # is this the best optimizer/learning rate?
    metrics=['mean_squared_error', 'mean_absolute_error'] # does accuracy make sense in this context?
)

## callbacks
early_stopping = EarlyStopping(
    monitor='val_loss',
    mode='auto',
    restore_best_weights=True
)


history = model.fit(
    features,
    target,
    validation_split=.3,
    epochs=20,
    verbose=0
)
model.summary()<jupyter_output>Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 32)                11520     
_________________________________________________________________
dense_2 (Dense)              (None, 16)                528       
_________________________________________________________________
dense_3 (Dense)              (None, 8)                 136       
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 9         
=================================================================
Total params: 12,193
Trainable params: 12,193
Non-trainable params: 0
_________________________________________________________________<jupyter_text>Below we calculate predictions and root mean square error. Can we easily improve this RMSE?<jupyter_code>## prediction
predictions = model.predict(features)
rmse = np.sqrt(np.mean(np.square((target.reshape(-1, 1) - predictions))))
rmse<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14162607718246534, 'fraction_numerical': 0.021356313225927313, 'mean_word_length': 3.9171270718232045, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 8, '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': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '567317', 'license': 'MIT', 'n_tokens_mistral': 743, 'n_tokens_neox': 687, 'n_words': 193, 'path': 'bitcoin/bitcoin-predictor.ipynb', 'repo_name': 'papagorgio23/Python101', 'size': '2669'}