An end-to-end machine learning project that predicts Netflix (NFLX) stock closing prices using an Artificial Neural Network (ANN), complete with a trained model, feature scaler, and a deployed Flask web application.
- Repository Structure
- Project Overview
- Dataset
- Exploratory Data Analysis
- Feature Engineering
- Model: Artificial Neural Network
- Model Evaluation
- Flask Web Application
- Tech Stack
- Getting Started
- Key Concepts Glossary
- References
NetflixStockPricePrediction/
├── README.md
├── LICENSE ← Apache-2.0
├── NetflixStockPricePrediction.ipynb ← Full EDA + model training
├── NFLX.csv ← Netflix historical stock data
├── ann_model.h5 ← Saved trained ANN model
├── scaler.pkl ← Saved MinMaxScaler/StandardScaler
├── app.py ← Flask web application
├── Procfile ← Heroku/cloud deployment config
├── requirements.txt ← Python dependencies
├── .gitignore
└── templates/ ← HTML templates for Flask UI
| File | Description |
|---|---|
NetflixStockPricePrediction.ipynb |
Complete pipeline: EDA → preprocessing → model → evaluation |
NFLX.csv |
Netflix OHLCV stock data (Open, High, Low, Close, Volume) |
ann_model.h5 |
Pre-trained ANN model saved in HDF5 format |
scaler.pkl |
Serialized scaler for consistent inference-time preprocessing |
app.py |
Flask API serving predictions via HTML interface |
Procfile |
Process file for cloud platform deployment (Heroku) |
requirements.txt |
Flask, tensorflow, scikit-learn, pandas, numpy, gunicorn |
Problem: Given historical Netflix stock data, predict the next day's closing price.
Solution pipeline:
Historical NFLX Stock Data (NFLX.csv)
↓
Exploratory Data Analysis (price trends, volume, rolling averages)
↓
Feature Engineering (technical indicators, lag features, normalization)
↓
ANN Training (TensorFlow/Keras sequential model)
↓
Model Evaluation (MSE, RMSE, MAE, R²)
↓
Model Serialization (ann_model.h5, scaler.pkl)
↓
Flask Web App (user enters features → model predicts closing price)
File: NFLX.csv
| Property | Value |
|---|---|
| Ticker | NFLX (Netflix, Inc.) |
| Exchange | NASDAQ |
| Columns | Date, Open, High, Low, Close, Adj Close, Volume |
| Coverage | Multi-year historical daily data |
| Size | ~93 KB |
| License | Apache 2.0 |
Column Descriptions:
| Column | Type | Description |
|---|---|---|
Date |
String/Date | Trading day |
Open |
Float | Opening price |
High |
Float | Intraday high price |
Low |
Float | Intraday low price |
Close |
Float | Closing price (target) |
Adj Close |
Float | Adjusted closing price (splits/dividends) |
Volume |
Integer | Number of shares traded |
Key EDA steps performed in the notebook:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
dataset = pd.read_csv('NFLX.csv')
dataset['Date'] = pd.to_datetime(dataset['Date'])
dataset.set_index('Date', inplace=True)
# Closing price over time
plt.figure(figsize=(14, 5))
plt.plot(dataset['Close'])
plt.title('Netflix (NFLX) Closing Price History')
plt.xlabel('Date')
plt.ylabel('Price (USD)')
plt.show()
# Correlation heatmap
sns.heatmap(dataset[['Open', 'High', 'Low', 'Close', 'Volume']].corr(),
annot=True, cmap='Blues')
# Rolling average (30-day, 90-day)
dataset['MA30'] = dataset['Close'].rolling(window=30).mean()
dataset['MA90'] = dataset['Close'].rolling(window=90).mean()Key observations:
- NFLX stock shows strong upward trend (2002–2021), with COVID-era volatility
Open,High,Low,Closeare highly correlated (Pearson r > 0.99)Volumeis inversely correlated with price at high price levels- Moving averages smooth short-term noise and reveal long-term trends
# Create features: OHLC + Volume + rolling statistics
dataset['MA7'] = dataset['Close'].rolling(7).mean()
dataset['MA21'] = dataset['Close'].rolling(21).mean()
dataset['Return'] = dataset['Close'].pct_change()
dataset['Volatility'] = dataset['Return'].rolling(21).std()
# Select features and target
features = ['Open', 'High', 'Low', 'Volume', 'MA7', 'MA21']
X = dataset[features].dropna().values
y = dataset['Close'].dropna().values
# Scale features to [0, 1]
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
X_scaled = scaler.fit_transform(X)An ANN regression model takes numerical stock features as input and outputs a continuous price prediction. Unlike time-series recurrent models (LSTM), this ANN treats each trading day as an independent observation using engineered features.
Why ANN for stock prediction:
- Captures complex non-linear relationships between technical indicators and price
- Fast inference — suitable for real-time prediction via API
- Feature normalization eliminates scale sensitivity
Regression ANN:
Input Layer → [Open, High, Low, Volume, MA7, MA21, ...]
Hidden Layer 1 → Dense(64), ReLU activation
Hidden Layer 2 → Dense(32), ReLU activation
Hidden Layer 3 → Dense(16), ReLU activation
Output Layer → Dense(1), Linear activation (continuous price)
| Layer | Type | Units | Activation |
|---|---|---|---|
| Input | — | n features | — |
| Hidden 1 | Dense | 64 | ReLU |
| Hidden 2 | Dense | 32 | ReLU |
| Hidden 3 | Dense | 16 | ReLU |
| Output | Dense | 1 | Linear |
import tensorflow as tf
from sklearn.model_selection import train_test_split
import pickle
X_train, X_test, y_train, y_test = train_test_split(
X_scaled, y, test_size=0.2, random_state=42, shuffle=False # No shuffle for time series
)
# Build model
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu', input_shape=(X_train.shape[1],)),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(16, activation='relu'),
tf.keras.layers.Dense(1) # Linear output for regression
])
model.compile(optimizer='adam', loss='mean_squared_error', metrics=['mae'])
history = model.fit(
X_train, y_train,
validation_data=(X_test, y_test),
epochs=100,
batch_size=32,
verbose=1
)
# Save model and scaler
model.save('ann_model.h5')
with open('scaler.pkl', 'wb') as f:
pickle.dump(scaler, f)Training hyperparameters:
| Hyperparameter | Value |
|---|---|
| Optimizer | Adam |
| Loss function | Mean Squared Error |
| Metric | Mean Absolute Error |
| Epochs | 100 |
| Batch size | 32 |
| Validation split | 20% |
| Shuffle | False (preserve time order) |
Loss formula:
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import numpy as np
y_pred = model.predict(X_test).flatten()
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"RMSE: ${rmse:.2f}")
print(f"MAE: ${mae:.2f}")
print(f"R²: {r2:.4f}")
# Plot actual vs predicted
plt.figure(figsize=(14, 5))
plt.plot(y_test, label='Actual Close', color='blue')
plt.plot(y_pred, label='Predicted Close', color='orange')
plt.title('Actual vs Predicted Netflix Stock Price')
plt.xlabel('Days')
plt.ylabel('Price (USD)')
plt.legend()
plt.show()| Metric | Description |
|---|---|
| RMSE | Root Mean Squared Error — penalizes large errors |
| MAE | Mean Absolute Error — average prediction error in dollars |
| R² | Coefficient of determination — how well variance is explained |
The app.py file serves a Flask REST application that loads the pre-trained model and scaler, accepts user input from an HTML form, and returns a predicted closing price.
from flask import Flask, request, render_template
import numpy as np
import tensorflow as tf
import pickle
import pandas as pd
app = Flask(__name__)
# Load pre-trained artefacts
model = tf.keras.models.load_model('ann_model.h5')
scaler = pickle.load(open('scaler.pkl', 'rb'))
@app.route('/')
def home():
return render_template('index.html')
@app.route('/predict', methods=['POST'])
def predict():
features = [float(x) for x in request.form.values()]
input_data = np.array([features])
input_scaled = scaler.transform(input_data)
prediction = model.predict(input_scaled)[0][0]
return render_template('index.html',
prediction_text=f'Predicted Closing Price: ${prediction:.2f}')
if __name__ == '__main__':
app.run(debug=True)HTML form (templates/index.html): User enters Open, High, Low, Volume values → clicks Predict → sees estimated closing price.
# Run locally
python app.py
# Procfile (for Heroku / cloud)
web: gunicorn app:appDeployment requirements:
Flask
scikit-learn
pandas
numpy
matplotlib
seaborn
tensorflow
gunicorn
| Library | Version | Usage |
|---|---|---|
| Python | 3.x | Core language |
| TensorFlow | 2.x | ANN model training and inference |
| Keras | 2.x (via TF) | High-level model building API |
| Flask | 2.x | Web application framework |
| Gunicorn | Latest | WSGI server for production deployment |
| scikit-learn | 1.x | MinMaxScaler, metrics |
| Pandas | 1.x | CSV loading, datetime handling |
| NumPy | 1.x | Array operations |
| Matplotlib | 3.x | Price trend / prediction visualization |
| Seaborn | 0.x | Heatmaps, distribution plots |
| Jupyter | Latest | Exploratory analysis and model training |
# 1. Clone
git clone https://github.com/nithinrajkore/NetflixStockPricePrediction.git
cd NetflixStockPricePrediction
# 2. Install dependencies
pip install -r requirements.txt
# 3. Run the notebook (model training + EDA)
jupyter notebook NetflixStockPricePrediction.ipynb
# 4. Run Flask web app locally
python app.py
# → Open http://127.0.0.1:5000| Term | Definition |
|---|---|
| OHLCV | Open, High, Low, Close, Volume — standard stock market data format |
| Moving Average (MA) | Rolling mean over N days; smooths price noise |
| MinMaxScaler | Scales features to [0, 1]: |
| ANN Regression | Neural network with linear output for continuous prediction |
| MSE | Mean Squared Error: average squared prediction error |
| RMSE | Root MSE: error in same units as target (dollars) |
| MAE | Mean Absolute Error: average absolute prediction deviation |
| R² | Fraction of price variance explained by the model (1 = perfect) |
| HDF5 (.h5) | File format for saving Keras model weights and architecture |
| Pickle (.pkl) | Python object serialization for saving the scaler |
| Flask | Lightweight Python web framework for serving ML models |
| Gunicorn | Production-grade WSGI server for deploying Flask apps |
| Procfile | Heroku configuration declaring the process type and command |
- Géron, A. (2019). Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow (2nd ed.). O'Reilly.
- TensorFlow documentation: https://www.tensorflow.org/
- Flask documentation: https://flask.palletsprojects.com/
- Dataset: Netflix (NFLX) historical stock data via Yahoo Finance
- Fama, E. F. (1970). Efficient Capital Markets: A Review of Theory and Empirical Evidence. Journal of Finance.