Price forward curves
Background
We simulate assets over their whole lifetime, which can be up to 30 years. To calculate expected financial results for this period, we need an estimate of grid prices over the same period.
Estimating prices this far ahead is extremely hard. Prices can change because of macroeconomic factors (commodity prices, currency exchange rates, inflation, and so on) and because of conditions on the grid, including policy (renewable energy subsidies, nuclear power policy, and so on) and technological progress (cost of storage, new storage technologies, improved and cheaper solar cells, and so on).
To keep our model explainable, we assume that the seasonality of prices will not change in the future: for example, prices stay higher in winter than in spring, and higher on weekdays than on weekends. We make no assumption on the long-term trend of the curves: the base curves we generate have approximately the same average price each year. We also assume that the relation between basic weather variables (temperature, solar radiation, and wind speed) and prices will remain similar in the future. The base curves are then adjusted to assumptions about the yearly average price and yearly average volatility over the lifetime of the plant. Users can provide their own yearly average and volatility assumptions in scenarios.
Calculation logic
The main steps for price generation are:
- base curve creation based on historical data
- scenario curve creation based on base curves and assumptions
- version management for base curve reproducibility
Base curve creation
We create the base curves with a gradient-boosted tree model (CatBoost), trained separately for each grid zone. For each day, it predicts all 48 half-hourly prices at once from weather and calendar features. The model is not auto-regressive: it uses no past prices as inputs, so it can generate prices decades ahead. A separate gradient-boosted classifier marks the slots expected at the price floor (0.01 JPY/kWh) in the base curves.
These "raw" base curves can be negative.
Input
The model uses weather data from 5 fixed locations in each grid zone, averaged per zone, as prediction variables. For the system price, it uses 5 major cities. The weather data comes from the same source as the simulator weather. We use the following variables:
- Air temperature at 2 m in °C
- Global horizontal irradiance in W/m2
- Wind speed
- Calendar features: day of the week, month, day of the year, and weekend and holiday flags
We train the model on the JEPX day-ahead prices for each zone, using prices from 2021-04-01 up to the latest available actuals. Base curves cover the nine grid zones of the main grid and the system price; Okinawa is not covered. The training is performed monthly, on the 15th.
The trained model then generates the base price curves for the future, up to 2059-12-31. As predictor variables, it uses the same standardized weather data (based on mapping the future to the past) described in simulator weather.
Scenario curve creation
Once the base curves are created, we modify them according to the assumptions in the scenario associated with the asset. These assumptions are a yearly average price and a yearly average volatility (mean absolute deviation) for each grid zone and each year of the plant's lifetime. Scenario curves contain day-ahead prices only.
There is currently no explicit assumption for the frequency of zero-price slots in a given year. Their frequency results from the interaction between the base curves and the average and volatility assumptions. For example, a lower average price and higher volatility tend to increase the frequency of zero-price events in that year. Zero-price slots in scenario curves come only from the 0.01 JPY/kWh floor applied in the last step below; the floor classifier of the base curves does not affect them.
As a first step, we take these assumptions from the scenario, treating each year as the start of the financial year (1 April), and interpolate linearly between these points month by month: the value changes at the start of each month and stays constant within it. Before the first year and after the last year defined, the values are held flat. This interpolation gives the average price assumption and the volatility assumption for each 30-minute slot.
We then calculate the rolling mean of the raw base price curve over the trailing 12 months:
where is the set of all future slots and the raw base price at time . The rolling windows use generated prices only: in the first year of the future, where a full 12-month window is not yet available, , , and below take the value of the first full window. Actual prices are added for past slots only after the scenario curve has been calculated. Next, the price trend is calculated as:
We calculate the rolling mean and deviation as:
And the rolling mean absolute deviation (MAD) as:
The volatility term is then:
The scenario price is defined as:
The simulator uses this scenario price to calculate the trading results and to optimize the battery operation over the asset life.
Version management
To keep financial models reproducible and stable, Tensor Cloud keeps versioned base curves. The models are retrained every month, on the 15th. Each run that passes the stability checks below is published as a new version. Versioning lets users:
- Select specific versions: Choose which version of base curves to use for their scenarios
- Maintain consistency: Use the same base curve version across multiple simulations for comparable results
- Access historical versions: Return to previous versions for result reproduction or comparison
- Inspect versions: See the training and inference data ranges and the period covered by each version
Users select the base curve version when they configure a scenario.
Each version is named after the year and month in which it was generated, for example 26.10. A further run in the same month adds a letter, for example 26.10b. A version is published only if the curves of every grid zone pass automated stability checks.