How To Build And Optimize A Trend-Following Strategy For Coffee Futures Trading

In this article, we'll explore the development of a trading system for Coffee futures (@KC), listed on the Intercontinental Exchange (ICE) in New York. The goal is to diversify our portfolio by incorporating lesser-known instruments compared to the more commonly traded futures.

The coffee market belongs to the category of "soft commodities," which also includes futures on sugar, cocoa, cotton, and orange juice. This market has several interesting characteristics: it's notably volatile-even on an intraday basis-relatively uncorrelated with equity futures, and maintains decent trading volumes.

To analyze this market in depth, we'll adopt a Trend Following approach, which tends to yield good results across most commodities. We'll test whether this approach proves just as effective when applied to Coffee futures.

Coffee Futures Strategy Logic: Trend Following Setup with Entry & Exit Rules

The strategy we're going to develop follows a classic Trend Following logic, based on the breakout of significant highs and lows.

Specifically, the system will go long when the price breaks above the highest high recorded over a certain number of sessions-"Highest(High,n_sessions)"-and will go short when the price breaks below the lowest low over a certain number of sessions-"Lowest(Low,n_sessions)".

The system will be allowed to trade throughout the full session, which for Coffee futures runs from 4:15 AM to 1:30 PM (exchange time), Monday through Friday. Entries and exits will occur within the same trading day, meaning all positions will be closed by the end of the session at the latest-unless the Stop Loss is hit earlier. For this initial analysis, the Stop Loss will be set at $1,500.

We'll test our trading system on a 15-minute time frame (data1), while entry levels will be calculated on a Daily time frame (data2), using historical data from the beginning of 2010 through March 2025.

This concept can be translated into just a few lines of code:

input:n_sessions(5),mystop(1500),myprofit(0);

if EntriesToday(d)=0 then Buy next  bar at Highest(High,n_sessions)data2 stop;

if EntriesToday(d)=0 then Sellshort next bar at Lowest(Low,n_sessions)data2 stop;

if mystop>0 then setstoploss(mystop);

if myprofit>0 then setprofittarget(myprofit);

setstopcontract;

setexitonclose;

First, let’s optimize and define the most profitable number of sessions (n_sessions) to use when calculating breakout levels for highs and lows. We’ll optimize the input n_sessions using steps from 1 to 10.

Figure 1 – Optimization of the "n_sessions" input to determine the optimal number of sessions for calculating highs and lows.

The optimization reveals that as the number of sessions increases, the net profit-and most other performance metrics-tends to deteriorate, with the exception of maximum drawdown. In our case, we choose a value of 2, meaning we'll calculate our entry levels based on the last two sessions. A position will be opened when the price breaks through these levels.

Looking at the performance metrics from our first test, we immediately see a profitable and upward-sloping equity curve-demonstrating that this futures contract responds well to Trend Following logic. While the results will certainly need improvement as we continue development, we’re already starting with a decent average trade of around $60 and a net profit of $160,800-not bad for a raw system with no filters applied yet.

Figure 2 – Detailed Equity Curve of the Trend Following strategy on Coffee futures.

Figure 3 – Strategy Performance Summary and Total Trade Analysis of the Trend Following strategy on Coffee futures.

To improve our trading system, the first step is to check whether operating the system within a time window that differs from the full session can be beneficial. We'll modify our code using a proprietary function and add the inputs "MyStartTrade" and "MyEndTrade", which define the start and end times of our trading window. We will then proceed to optimize these parameters.

var:istartofsession(false);

istartofsession=_OHLCMulti5(0415,1330,ohlcvalues);

array:ohlcValues[23](0);

input: stoploss(1500), takeprofit(0);

input: MyStartTrade(415),MyEndTrade(1330);

input: n_sessions(2);

//ingressi

if tw(MyStartTrade,MyEndTrade)

and EntriesToday(d)=0

then begin

                   Buy next  bar at Highest(High,n_sessions)data2 stop;

                   Sellshort next bar at lowest(Low,n_sessions)data2 stop;

end;

if stoploss>0 then setstoploss(stoploss);

if takeprofit>0 then setprofittarget(takeprofit);

setstopcontract;

setexitonclose;

Figure 4 – Optimization of the "MyStartTrade" input to determine the best time to begin trading.

Figure 5 – Optimization of the "MyEndTrade" input to determine the best time to stop trading.

From the optimization results, we can see that by narrowing our trading window-starting at 5:00 AM and ending at 11:00 AM-we achieve a clear improvement in maximum drawdown, reducing it from over $26,000 to less than $23,000. This is likely because early in the session, market movements are often erratic and lack direction, while after a certain point in the day, it makes little sense to enter new trades since all positions are closed by the end of the session.

Boosting Strategy Performance with Price Patterns

Let's continue refining the system by focusing on one of the most critical performance metrics: the average trade. In order for the system to be truly viable for live trading, we need to significantly improve this figure-especially considering real-world trading costs such as commissions and slippage, which are also influenced by the relatively high tick value of Coffee futures ($18.75 per tick).

One potential enhancement is to add a filter based on the "Daily Factor"-a pattern that measures how much the previous day’s price moved from open to close, relative to its full daily range. This pattern doesn’t provide directional signals but gives us insight into volatility: a very low Daily Factor indicates that prices moved very little relative to their total range, while a high Daily Factor signals a strong directional move, either bullish or bearish.

Once we calculate the Daily Factor ("DF"), we can compare it to a predefined threshold ("DF_level") to determine if it’s above or below that value. Both "DF" and "DF_level" range from 0 to 1.

We'll now implement this logic in our script with a few lines of code and proceed to optimize the "DF_level" input, ranging from 0.1 to 1 in steps of 0.05.

//Daily Factor

input:DF_level(1);

var: DF(0);

if (highs(1)-lows(1))<>0 then begin

DF=absvalue(opens(1)-closes(1))/(highs(1)-lows(1));

end;

Figure 6 – Optimization of the "DF_level" input to define the filter based on the Daily Factor pattern.

Based on the optimization results, we choose a value of 0.8. This sets the following condition: the strategy will only be allowed to open a position if the body of the previous session (Open – Close) is less than 80% of the session’s full range (High – Low).

This filter helps boost our average trade by $20, raising it to over $85. It also contributes to a further reduction in maximum drawdown and an increase in net profit.

Day-of-Week Bias in Coffee Futures: Filtering for the Most Profitable Trading Days

At this stage, we have a significantly improved system, but it's still not ready for live trading with real money. So let's look for further refinements. One potential idea is to exclude specific weekdays that have consistently proven to be less profitable across the historical data analyzed.

To do this, we update our script by introducing two new inputs: "skipdaylong" and "skipdayshort". These inputs will identify which trading days to exclude from our strategy, depending on whether it's a long or short entry.

We'll then optimize these inputs using a range from 1 to 5, corresponding to the days of the week in the MultiCharts programming language, where 1 = Monday and 5 = Friday.

input: skipdaylong(-1),skipdayshort(-1);

if dayofweek(d)<>skipdaylong then Buy next  bar at Highest(High,len)data2 stop;

if dayofweek(d)<>skipdayshort then Sellshort next bar at Lowest(Low,len)data2 stop;

Figure 7 – Optimization results for the "skipdaylong" and "skipdayshort" inputs, sorted by average trade.

To validate the optimization results, we use our proprietary software, which allows us to analyze instrument-specific biases at various levels-from intraday hourly biases to monthly and yearly ones.

Looking at Figure 8, we immediately notice that on Mondays (highlighted in the figure), Coffee futures tend to move sideways, showing no clear directional trend. On the other hand, the remaining weekdays exhibit more pronounced trends, typically bearish for this instrument. Moreover, a Daily Factor measured on Fridays is generally weaker than the same metric observed on other days.

Based on this analysis, we decide to exclude Monday from our trading activity. This adjustment allows us to push the average trade slightly above $100.

Figure 8 – Weekly Bias analysis of Coffee futures using the proprietary Bias Finder software.

Optimizing Stop Loss and Profit Target for Improved Strategy Profitability

As the final step in our testing, we proceed-as usual-with an optimization of the Stop Loss, which so far had been set at $1,500. At the same time, we evaluate the possible benefit of adding a Profit Target. This final refinement leads us to set both the Stop Loss and Profit Target at $1,700.

The final metrics achieved through our study are approximately $189,000 in net profit, $118 average trade, and $14,756 maximum drawdown.

Figure 9 – Stop Loss optimization for the Trend Following strategy on Coffee futures.

Figure 10 – Profit Target optimization for the Trend Following strategy on Coffee futures.

Figure 11 – Final equity curve of the Coffee futures strategy.

Figure 12 – Final Performance Summary and Total Trade Analysis for the Coffee futures strategy.

Final Thoughts: Is Trend Following on Coffee Futures Worth It for Systematic Traders?

In summary, the Trend Following approach we explored in this article has proven to be particularly promising when applied to Coffee futures. This reinforces the value of exploring lesser-known markets as a way to diversify one's trading portfolio.

The analysis has provided strong insights, but the strategy would still need further development before it's ready for live trading-especially in terms of selecting the most profitable trades and improving the average trade value to make the system viable in real-world conditions.

Until next time-happy trading!

Andrea Unger

Market News and Data brought to you by Benzinga APIs

Comments
Loading...