Always-long inverse-volatility grain basket

The comparison portfolio for the ENSO-onset trade: simply owning wheat, corn and soybeans all the time. A weather strategy has to beat holding the same crops through every season to be worth anything.

Conclusion: Control

A benchmark, not a candidate. Held continuously it returned 2.1% a year at 22.0% volatility, with a worst fall of 72.0% over 302 months. Strategies are measured against this.

Figure 1 · Growth of $1

2001–2026 · net of 15bp round-trip costs
What one dollar became, after costs: $1.68 by 2026. Shown against S&P 500, rebased to the same starting dollar.
Return for risk
0.09
range (0.29) to 0.51
Ann. return
2.1%
volatility 22.0%
Max drawdown
72.0%
over 302 months
Beats the search
0.2%
chance, after correction

Method

Hypothesis

Benchmark. Any climate strategy must beat just owning it.

Rule

UNIVERSE = [ZW=F ZC=F ZS=F ZM=F ZR=F KE=F]
function positions(bar):
# no signal, no timing: always fully invested
for symbol in UNIVERSE:
w[symbol] = 1 / vol_36m(symbol, bar.prev) # equal risk
return w
# ── execution ────────────────────────────────────────────────────────
COST_PER_TRADE = 15 bps of the notional that changes hands
function on_bar(bar, book):
if not bar.is_month_end:
return # decisions are made monthly only
target = positions(bar) # the rule above
target = scale_to_gross(target, 1.0)
rebalance(book, target, bar)
function scale_to_gross(w, limit):
gross = sum(abs(w)) # total capital at work
if gross == 0:
return w # flat is a valid target
return w * limit / gross # leverage fixed, never implicit
function rebalance(book, target, bar):
for symbol in union(book.symbols, target.symbols):
delta = target[symbol] - book.weight(symbol)
if delta > 0:
buy(symbol, delta, fill = next_bar.close)
else if delta < 0:
sell(symbol, -delta, fill = next_bar.close)
book.charge(COST_PER_TRADE * abs(delta))
# Orders are filled at the next month's close, never the one the decision
# was made on. There is no stop_loss(), take_profit(), limit order or
# position cap: a holding changes only when positions() returns a
# different target at the next month end.

Evaluation

Table 1 · Performance

2001-05 – 2026-06 · 302 months, 302 invested
MeasureValue
Annualised return2.1%
Annualised volatility22.0%
Return for risk taken0.09
95% range(0.29) to 0.51
t-statistic0.47
Maximum drawdown72.0%
Hit rate50.3%
Annual turnover0.38×
Return skew(0.26)
Return kurtosis3.90
The range is measured by resampling the history in blocks, so runs of good and bad months stay intact.

Table 2 · Robustness

DiagnosticValueReads asBadOkayYayHmm
Design half (pre-2015)0.14return for risk≤ 00 – 0.40≥ 0.40
Holdout half (2015+)0.01return for risk≤ 00 – 0.40≥ 0.40
Top-5-month share of profit153.6%how much rode on a few months — lower is better≥ 40%25 – 40%< 25%
Top-2-year share of profit147.7%concentration
Distinct trading episodes1how many independent runs this really is< 5050 – 100≥ 100
Chance the edge is real67.9%non-normality corrected
Chance it beats the whole search0.2%chance of beating the whole search by luck
bad/ok boundary is the pre-registered criterion · ok/good is a margin above it, not a criterion · blank where none was registered
The last row asks whether the result would stand out from the hundred-odd ideas tried here, rather than being judged alone.

Table 3 · Net return by calendar year

after costs
20012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026+47%-47%
YearNet return
2001(40.4%)
200216.9%
200325.7%
2004(22.8%)
200511.0%
200629.4%
200747.0%
2008(15.0%)
2009(3.4%)
201027.7%
2011(10.7%)
201214.9%
2013(14.3%)
2014(15.9%)
2015(15.7%)
2016(4.3%)
20174.5%
20181.1%
20197.0%
202021.9%
202111.8%
202212.3%
2023(20.2%)
2024(16.6%)
2025(10.4%)
202610.4%

Table 4 · Concentration detail

MeasureValue
Best years2007:+47%, 2006:+29%, 2010:+28%
Worst year2001:-40%

Reference

Instruments

last price and one-month change, live from Yahoo Finance
SymbolNotes
ZW=FChicago SRW Wheat — continuous futures on CBOT, quoted in US cents.
ZC=FCorn — continuous futures on CBOT, quoted in US cents.
ZS=FSoybeans — continuous futures on CBOT, quoted in US cents.
ZM=FSoybean Meal — continuous futures on CBOT, in USD.
ZR=FRough Rice — continuous futures on CBOT, in USD.
KE=FKC HRW Wheat — continuous futures on CBOT, quoted in US cents.

Sample

2001-05 – 2026-06 · 302 months

Sources

NOAA Physical Sciences Laboratory. Climate indices. ONI, Niño 3.4, MEI v2, DMI, PDO, AMO, TNA, QBO, solar flux. psl.noaa.gov/data/climateindices/list
Queensland Department of Agriculture and Fisheries. Southern Oscillation Index. The Long Paddock. Monthly, 1876–. www.longpaddock.qld.gov.au/soi/soi-data-files
Yahoo Finance. Historical market prices. Adjusted close, month-end. Retrieved with yfinance. finance.yahoo.com

Revision history

RevStageStatusChange
01DraftDirection and criteria fixed before the experiment ran
02TestedControlBenchmark, not scored against the criteria
algorithmic-trading-anthology-july-2026-c2-buy-hold-grain | d/rksci