How do we predict regional prices available on Hectare Trading?
At hectare, we have established a set of predicted prices that a seller can expect to achieve for spot feed wheat, milling wheat and feed barley in their region. They can found on the Regional Predicted Prices dashboard here on the analytics platform. But in general they're used in cards that look like this:
South
£−0.45 ↘︎ ±£2.70£14.35 ↗︎ LIFFE price (£139) Last 365 Days
Why do we need to be able to predict prices at a regional level on Hectare Trading?
Simply put, we want to offer sellers live pricing information on what sort of price they can expect for their commodity when they list. However, this depends on multiple factors, most notabley the difference in regional pricing bias that can vary throughout the year. There isn't a great source of live data for this, which means must look to predict the price ourselves.
The current picture
Currently, in the UK agricultural market, if you're looking for live pricing information on spot prices the options are pretty slim.
People generally look at the change in price of London Feed Wheat on the ICE (UK) exchange throughout the day to estimate how prices are changing. However, the ICE exchange is not a great representation of prices across the country to factors such as haulage and localised buyer demand. You can read more about how regionality effects pricing here.
Another option is the AHDB corn returns pricing data, this is a mandatory survey that any group buying more the 10,000 tonnes of agricultural commodities has to fill in. However this is only done weekly and is often missing pricing in multiple regions.
Why don't we use display our own prices?
The issue is that we just don't have enough data in each region in a regular cadence to be able to give the seller an accurate picture of the price in their area.
This then leads to large shifts in prices being displayed to the user, which can lead to mixed messaging on the market being displayed to the customer.
For example, if we had a listing in Scotland on a Monday that achieved a price of £190, but then didn't recieve another listing until Friday. The price of feed wheat may have shifted by a large amount in that 4 day stretch, let's say £180. Our pricing would display a £10 negative swing in pricing in Scotland. Which isn't very representative of what is actually happening in the market.
So we need some way to predict a price which is:
- A live price that updates throughout the day.
- Has enough data points to not cause large deltas.
- Encorporates the regional offset of the user.
Feed Wheat Prediction
Feed wheat is arguabily the easiest place to start as we can compare our bid prices to the ICE (UK) London Feed Wheat price. This provides a constantly updating set of data throughout the day for us to predict prices on.
Comparing ICE (UK) and Hectare Trading prices
Whenever a bid is made on Hectare Trading for ex-farm feed wheat, it is compared to the close value of ICE (UK) london feed wheat price for the next upcoming movement month.
For example we recieve the following bid in Scotland:
We then compare this to the close price of the ICE (UK) to the nearest movement month available on the ICE (UK).
In this case the bid is for a Jan 2026 movement date, so we can compare directly to the Jan 2026 ICE price at the time of the bid. However, in cases in which we can't compare directly to the movement month, we subtract £2 from the ICE price for each month between the bid price and the nearest ICE price. For example, our bid before also had a bid price for December 2025. In this case we remove £2 from the Jan 2026 movement price and compare the two figures:
Developer Notes
This comparison step is done at the data source level. Meaning that rather than being calculated at runtime in javascript, it's extracted from the insights postgres database using sql.You can find the sql to provide this data [here](https://github.com/Hectare-Agritech/data-platform/blob/main/observable/src/data/regional-prices-prototype/liffe_prices_offset.json.js).
If we do this for all our bid information this looks like:
As the two prices are correlated, we can plot a regression based on the relationship between the two prices:
This allows us to predict what we believe the price achieved on hectare trading will be based on what the ICE price is at any given date. For example, if the nearest ICE was at a price of £180, based on this regression we would predict that the expected price on Hectare Trading would be: £
Developer Notes
These regressions are made with the regression npm model. To create this regression, pass an array of arrays containing the offset_liffe_price
and price
fields from the LIFFE Prices/Trading Bid comparison SQL the linear method of the package.
This will return a regression model that can provide predictions.
See the example of how this how been done for the below example here.
Since we want to be able to predict this for each super-region in the UK. We can split this into four separate regressions using the same method.
Historic Pricing
The relationship between the ICE and Hectare feed wheat price per region changes over time. As we want to give our sellers an idea of what prices they can expect at the point of listing. To do this we need to include enough bid prices to have a sample size large enough to provide an statistically significant regression, without leave too much a lag in which the regression wouldn't be responsive to changes in the relationship.
At the moment this is based on taking a window of bids in the 365 days before the regression date. See below how our regional regressions change each day as this rolling window changes.
Regression for date:
If we take the results of each of these historic predictions the results look like this:
Developer Notes
These historic regressions are made via the getHistoricReggressions
function, you can see it used to produce the examples above here.
It takes four parameters:
- The bid/ICE comparison dataset, used earlier in this page (SQL to provide this can be found here).
- A string that contains which region the regression history is being created for.
- The daily close prices of the ICE exchange to be used to predict prices on (SQL to provide this can be here).
- The bids table from the insights database (
insights.bids
).
This returns an array of objects that contains the following entries:
- The date of the regression
- The regression object
- The bids that make up the regression
- The liffe/ice close price for the day
- The predicted price (predicted value based on the current liffe/ice price & the day's regression)
- The spot prices made on the day of the regression (used for later error calculation).
And that my friend, is how we predict the historic regional Hectare Trading feed wheat price based on historic ICE prices. You can read more about how accurate these predictions are and some other information here.
Milling Wheat Prediction
Like feed wheat, we do not have enough milling wheat bids in each region at a regular enough cadence to present our data to users as a live price. However, we also do not have a live marketplace price for milling wheat like we do with the ICE (UK) for feed wheat.
So we'll have to use a different source of data to assist us in our prediction. Enter the AHDB corn returns.
AHDB Corn Returns Premium
The AHDB corn returns is a mandatory survey conducted weekly by the AHDB, sent to any entity that buys more than 10,000 tonnes of agricultural commodity a year. This survey contains a weighted average of the prices the buyers have offered throughout the week for a number of commodities and grades.
This includes milling wheat and feed. See below the trading price of feed wheat and bread milling wheat over time at a UK wide level for the last 5 years (from time of writing).
By taking the difference between these two prices we can generate a weekly milling premium.
Predicting Milling Prices
With the above milling premium calculated over time, we can now apply this value to our historic regressions to get the predicted milling price over time.
For example, see the predicted feed wheat price and the predicted milling wheat price for the midlands over time.
This is how we predict historic milling prices on Hectare Trading, you can read more about the accuracy of these predictions and how our milling premium tracks with the AHDB corn returns here.
Developer Notes
To get the historic offsets the addWeeklyOffsetToRegressionHistory
function is used, you can see it used to produce the examples above here.
It takes two parameters:
- A historic regression object, which if created via the
getRegressionHistory
function which you can read about above. - A set of forward-filled AHDB corn return prices (a dataset in which the corn returns prices are filled with the previous week's data if there is none). See an example of this on this page here.
This returns an array of objects that contains the following entries:
- Original regression elements
- The milling offset at the date of the regression.
- The barley offset at the date of the regression (more on that later).
- The date the last offset information was available - to let users know if the offset is not fresh to the week.
Feed Barley Prediction
As discussed in the previous section, the AHDB corn returns survey contains information across a number of crop & commodity types. One of these is the price of Feed Barley in the UK. See below the difference between the price of feed wheat and feed barley over time.
The difference between these two values we call the 'barley offset', essentially how much we need to subtract from the feed wheat price to predict the feed barley price.
Using this method we can predict the price of feed barley per region on hectare trading. See below the predicted price of feed barley against the predicted price of feed wheat on Hectare Trading in the South.
Developer Notes
To get the historic offsets the addWeeklyOffsetToRegressionHistory
function is used, you can see it used to produce the examples above here.
It takes two parameters:
- A historic regression object, which if created via the
getRegressionHistory
function which you can read about above. - A set of forward-filled AHDB corn return prices (a dataset in which the corn returns prices are filled with the previous week's data if there is none). See an example of this on this page here.
This returns an array of objects that contains the following entries:
- Original regression elements
- The milling offset at the date of the regression (see above).
- The barley offset at the date of the regression.
- The date the last offset information was available - to let users know if the offset is not fresh to the week.
Calculating Errors
As our sellers will get a range of prices over a number of bids when they create a list. This price is can never be a definitive price of what a seller will achieve, but we do want it fall into the range of bids they receive.
We also want to provide some idea to the seller the relative range we expect prices to be in. Think of it as a "£180, give or take a couple of quid" kind of situation. This is the value you see next to the predicted price in the dashboard next to the little ± symbol. But how do we quantify that?
To do this we'd need to check how our prediction each day has performed historically to the real prices that came in on each day. To simply that, we check the prices we actually received and compare it to the price we predicted at the time of that bid.
For example on the 25th of July 2025, we predicted that the price of feed wheat in the south would be £153.66. On that day we received five bid offers for feed wheat, priced at: one at £156, two at £160 and two at £163.
We then take the difference from our price to these prices and record them as our error values. (£2.33, £5.33, £5.33, £9.33 and £9.33).
When repeat this process for the full 365 days of historic regressions prior to our daily prediction, we can plot our error values as a distribution.
We then take the standard deviation of this error rate to get our plus/minus value for the user. In the case for the prediction based on the error distribution above: ±£
You can read more about what our predictions overall error rate is and some more detailed analysis on error here.
Developer Notes
To get the error values based on a historic regress object the calculateError
function is used, you can see it used to produce the examples above here.
It takes a single historic regression parameter, which must contain the historic 'spot price' information. If you are using the version from above in this document, don't worry, it'll work. It also removes any extreme error that may be due to missing values or extremely high/low bids.
This returns an array of objects where each object is a spot bid compared to the predicted value at the time of the spot bid.
- date: The date of when the bid was made.
- spotPrice: The price of the bid made.
- predictedValue: The predicted value of the regression at the time the bid was made.
- error: The difference between the predicted price and the spot bid price.
The error values from this array and then mapped and used in a d3.deviation function to calculate the deviation for the error value.