Volatility forecasting with 4 lines of code without ML knowledge
Hello friends! My name is Denis, I am an algorithmic trader and developer.
When I came to algotrading, I really wanted to apply machine learning quickly. But for this, you need to understand ML and Data Science, and I was just starting. Now I already understand, but I know that not all traders are ready to spend months on it.
Especially for those who want to try ML for volatility prediction without deep knowledge, I made the dquant library.
Now you can train a model without any knowledge of feature engineering, splits, or hyperparameters. All you need is a basic understanding of python and the ability to access raw data (open, close, high, low, and volume).
This is not a comprehensive guide, but rather a basic example. For more information, please refer to the documentation.
The whole process consists of 2 steps:
- Raw data preparation (open, close, high, low, volume)
- Training and prediction (4 lines of code)
What happens under the hood?:
- Data is divided into input and output
- Features are created from input data, targets from output data
- Data is divided into training and validation sets
- Training can stop early if the model starts to overfit
- At the end of training, an error graph is displayed
You can use the model for predictions, or you can save the model and use it later.
Go.
Installation
pip install dquantDone. Dependencies (pandas, numpy, xgboost, lightgbm, matplotlib) are pulled automatically.
Check:
import dquantprint(dquant.version) # prints the versionQuick Start: EURUSD Volatility Prediction for 4 Lines with Yahoo Finance
With Yahoo Finance, we can get price data for a specific period. First, we need to install the yfinance python library.
Installing Yahoo Finance
pip install yfinancePython code
import pandas as pd
import yfinance as yf
from datetime import datetime, timedelta
from dquant.models import VolClustXGB
# 1. Download hourly data
start_date = datetime.now() - timedelta(days=700)
df = yf.download("EURUSD=X", start=start_date, interval='1h')# Create a data frame with the input data
df = pd.DataFrame({
'open': df[('Open', 'EURUSD=X')].values,
'high': df[('High', 'EURUSD=X')].values,
'low': df[('Low', 'EURUSD=X')].values,
'close': df[('Close', 'EURUSD=X')].values,
'volume': df[('Volume', 'EURUSD=X')].values
}, index=df.index)# 2. Create a model
model = VolClustXGB({}, early_stopping=True)# 3. Train the model
features = ['TR', 'returns', 'abs_returns', 'gap', 'body', 'shadow', 'close_position', 'roll_atr_14']
model.fit(df, feature_list=features, input_bars=70, horizon=20, trees_count=200, show_results=True)# 4. Make a forecast
rez = model.forecast(df.iloc[-70:].copy(), show=True)
The training and prediction process itself takes 4 lines, and you need to get the raw data first.
What you will see:
Training graph (error on train/validation)
- Red histogram — historical volatility
- Green histogram — forecast for the next 20 bars
Done. You can immediately set stops or calibrate the position size.
Get Denis Makarov’s stories in your inbox
Join Medium for free to get updates from this writer.
Let’s analyze the code from the dquant library itself in more detail.
The first line
model = VolClustXGB({}, early_stopping=True)We create a class VolClustXGB, it uses the XGBoost (eXtreme Gradient Boosting) model. The first argument will be an empty dictionary. This means that the default hyperparameters will be used during training. early_stopping=True means that training will automatically stop when the model starts to overfit.
If you want to add your own hyperparameters (for this you need to understand ML), then the dictionary should not be empty. For example:
settings = {
'objective': 'reg:squarederror',
'learning_rate': 0.1,
'n_estimators': 1,
'max_depth': 3,
'min_child_weight': 5,
'subsample': 0.8,
'random_state': 42
}
model = VolClustXGB(settings, early_stopping=True)But you can also use the default example if you don’t go into ML. This library was created specifically for you.
The second and third lines
features = ['TR', 'returns', 'abs_returns', 'gap', 'body', 'shadow', 'close_position', 'roll_atr_14']model.fit(df, feature_list=features, input_bars=70, horizon=20, trees_count=200, show_results=True)This is where the data labeling and training take place.
In the second line, you choose which features you want to use for training.
In the third line, we pass our raw data, df, as the first argument.
The second argument, feature_list=features, represents our features.
The third argument, input_bars=70, specifies the number of bars we want to input. This is our input data, which our model will use to train on. After training, we will need to input this amount of data to our model in order to make predictions.
The fourth argument, horizon=20, is the number of steps in our prediction. In our case, we will train the model to predict volatility 20 bars in advance. Since we have hourly data, we will predict 20 hours in advance.
The fifth argument, trees_count=200, is the maximum number of trees on which we will train our model. We have early_stopping=True in the first line, which means that the model will stop training if overfitting occurs, even if we set 1000 or 10000 trees.
The sixth argument, show_results=True, means that a graph will be displayed after training, showing the decrease in error on the training and validation data.
The fourth line
rez = model.forecast(df.iloc[-70:].copy(), show=True)And finally, the fourth line. The model is already trained, and we are predicting volatility.
The first argument, df.iloc[-70:].copy(), is our input data. Our model takes 70 bars as input, as we have trained it. In this example, we are simply taking the last 70 bars from our imported data.
The second argument, show=True, displays the prediction result on the chart. If you do not want this, simply omit this argument.
rez = model.forecast(df.iloc[-70:].copy())The prediction result will be written to the rez variable regardless of whether you want the result on the graph or not.
Saving the model
model.save("eurusd_vol_model")# later
model.load("eurusd_vol_model")model.forecast(df.iloc[-70:].copy(), show=True)
How to try it right now
You can run this code directly in your browser using the Jupiter Notebook
Links
The library is completely open-source (MIT). If you find a bug or want a feature, create an Issue, and I will respond quickly.








