The Rolling Intrinsic Intraday Energy Trading Optimization repository models continous intraday trading with the means of discretization and linear optimization. While the results of the underlying paper are based on actual EPEX Spot data (which requires paid access), the open-source repository at hand provides randomly generated data.
The notebook 'Create Randomized Intraday Transaction Data' constitutes the first step: random transaction data (continous buy/sell orders) are created. Then, in the folder 'Code/Rolling Intrinsic' the Python scripts 'Rolling Intrinsic H.py' and 'Rolling Intrinsic QH.py' can be executed to model rolling intrinsic trading, respectively on the market for hourly or quarter hourly products. The Python script executes the function simulate_period() with the parameters described below. Finally, the results are then saved in the 'results' folder.
-
threshold:
- Description: This is the relative price change threshold as a percentage. It represents the minimum price change required to trigger an action (buy/sell).
- Example: A threshold of 0 means that even the smallest price fluctuation can trigger trading decisions.
-
threshold_abs_min:
- Description: This is the absolute minimum price change threshold. It ensures that there’s a fixed minimum price movement (in absolute terms) that must occur before any trading action is triggered, regardless of percentage changes.
- Example: A value of 0 means no minimum price movement is required.
-
discount_rate:
- Description: This is used for time-based price discounting. It represents the percentage rate at which the future value of cash flows is discounted.
- Example: A discount rate of 0 means no time discounting is applied to prices, treating future prices as if they were happening now.
-
bucket_size:
- Description: This refers to the time interval (in minutes) for grouping or aggregating trades.
- Example: For example, with a bucket size of 15, trades are grouped into 15-minute intervals, helping to control the granularity of the optimization process.
-
c_rate:
- Description: This is the charge rate for the battery storage system. It defines how fast the system can charge or discharge as a fraction of the total storage capacity.
- Example: A value of 0.5 means the battery can charge or discharge up to 50% of its capacity in one unit of time.
-
roundtrip_eff:
- Description: This refers to the roundtrip efficiency of the battery storage system. It represents the overall efficiency of the battery when charging and discharging.
- Example: A roundtrip efficiency of 0.86 means that for every 100 units of energy stored, 86 units are available for use after charging and discharging.
-
max_cycles:
- Description: This defines the maximum number of charge-discharge cycles the battery can perform in a given period (e.g., a year).
- Example: A value of 365 means the battery can undergo one full cycle (charge + discharge) per day on average, limiting the total wear on the battery system.
First, you need to set up the PostgreSQL database. You can follow these steps:
Open a terminal and run the PostgreSQL command-line interface:
psql -d postgres
Create the database for your project:
CREATE DATABASE intradaydb;
Create a user named leloq
with the password 123
:
CREATE USER leloq WITH PASSWORD '123';
Change the ownership of intradaydb
database to the leloq
user:
ALTER DATABASE intradaydb OWNER TO leloq;
Type \q
to exit the PostgreSQL shell.
\q
Next, set up the Python environment. You'll need Python 3.8 or higher. You can set up a virtual environment and install the required dependencies as follows:
python3 -m venv venv
source venv/bin/activate
Install all required libraries listed in the requirements.txt
file:
pip install -r requirements.txt
Gurobi can be used as a solver in this project. Make sure you have a valid Gurobi license. If you haven't installed it yet, you can follow these steps:
Install Gurobi Python bindings:
pip install gurobipy
Set up your Gurobi license (follow the instructions on the Gurobi website).
In the python files Code/Rolling Intrinsic/Rolling Intrinsic H.py
& Code/Rolling Intrinsic/Rolling Intrinsic QH.py
change to the GUROBI solver pulp provides and disable the default solver from pulp:
from pulp import (
LpProblem,
LpVariable,
lpSum,
LpMaximize,
GUROBI,
# PULP_CBC_CMD,
)
...
# m_battery.solve(PULP_CBC_CMD(msg=0))
m_battery.solve(GUROBI(msg=0))
Now, you can run the code from the notebook 'Create Randomized Intraday Transaction Data'. Alternatively, you can fill the intradaydb table with actual data from any continous intraday market you want to cover.
Now you're ready to run the optimization code in the "Code/Rolling Intrinsic" folder.
Make sure you execute the file with current working directory being rolling_intrinsic_intraday_trading/
.
This is necessary for the output landing in the output/
folder.
After having run the optimization code, you can visualize the behaviour of the Algorithm by running the jupyter notebooks
plotting_trading_behaviour_RIB_*.ipynb
.
The only thing you have to do is to enter the date you want to visualize in the 2nd cell as constants.
Imagine you want to plot December 24th 2022. In that case, you have to change the string in START_OF_DAY
to be 2022-12-24 00:00:00
and END_OF_DAY
to 2022-12-25 00:00:00
START_OF_DAY = pd.Timestamp('2022-12-24 00:00:00', tz='Europe/Berlin')
END_OF_DAY = pd.Timestamp('2022-12-25 00:00:00', tz='Europe/Berlin')
EXECUTION_TIME_START = (START_OF_DAY - timedelta(days=1)).replace(hour=16, minute=0)
EXECUTION_TIME_END = START_OF_DAY.replace(hour=22, minute=54, second=59)
After doing that, just run all cells.
The plots are stored in the path output/plots/rolling_intrinsic_*.png
Just run the jupyter notebook revenue_plots_and_results_table.ipynb
.
In case you want to change the timeframe of the visualisation also adapt the two constants in cell 2.
START_DATE = pd.Timestamp('2022-01-01 00:00:00', tz='Europe/Berlin')
END_DATE = pd.Timestamp('2023-01-01 00:00:00', tz='Europe/Berlin')
- Python: 3.8+
- PostgreSQL: 13+
- Gurobi: Optimization solver
- Libraries:
psycopg2
pandas
numpy
gurobipy
sqlalchemy
pulp
jupyter
matplotlib
loguru
This project is licensed under the MIT License - see the LICENSE
file for details.
Contributions are welcome! Please open an issue or submit a pull request.
Jannik Dresselhaus, Jan Ludwig, Leo Semmelmann, Kim Miskiw