← Back to Blog

Weekly Export Sales Tracker

Mar 11, 2026 · 6 min read

Every Thursday, USDA publishes the Weekly Export Sales report — the most closely watched demand-side data for grains. By plotting cumulative commitments across marketing years, you can quickly see whether export pace is ahead or behind historical norms.

In this notebook we'll pull corn total commitments, compute seasonal week numbers, and build a year-over-year overlay chart.

[1]
import os import fastagsdata as fdata import matplotlib.pyplot as plt import pandas as pd fdata.set_key(os.environ['FASTAGSDATA_API_KEY'])

Pull corn export sales

Query the exportsales_api source for corn total commitments (tc). Each row is one weekly report. Values are in metric tons. Source: USDA Export Sales Reporting.

[2]
exports = fdata.get( 'exportsales_api', param=['tc'], comdty=['c'], shape_id='us' ) # Keep last 5 marketing years latest_year = exports['year'].max() export = exports[exports['year'] >= latest_year - 5].copy() print(f"{len(export)} rows, years {export['year'].min()}–{export['year'].max()}")
Out
302 rows, years 2021–2026

Compute marketing year weeks

Corn's marketing year starts September 1, so MY 2026 runs Sep 2025 through Aug 2026. We compute each row's week number within its marketing year so we can align years on the same axis.

[3]
# Corn marketing year starts Sep 1 (MY 2026 runs Sep 2025 → Aug 2026) my_start_month, my_start_day = 9, 1 # Each MY starts in the prior calendar year (MY 2026 → Sep 1 2025) export['my_cal_year'] = export['year'] - 1 export['my_start'] = export['my_cal_year'].apply(lambda y: pd.Timestamp(y, my_start_month, my_start_day)) # Week number within the marketing year export['days_into_my'] = (export['date_ref'] - export['my_start']).dt.days export['my_week'] = export['days_into_my'] // 7 + 1 # Pivot: one column per year, one row per week number pvt = export.pivot_table(index='my_week', columns='year', values='value') # Convert week numbers to dates for the x-axis my_start_date = pd.Timestamp(latest_year - 1, my_start_month, my_start_day) pvt.index = my_start_date + pd.to_timedelta(pvt.index * 7, unit='D') pvt.reset_index().head()
year my_week 2021 2022 2023 2024 2025 2026
0 2025-09-08 18846903.0 24326115.0 11718159.0 11159925.0 13361230.0 22601465.0
1 2025-09-15 20456088.0 24572698.0 12301269.0 11726782.0 14208580.0 23833099.0
2 2025-09-22 22595090.0 24945705.0 12483608.0 12568565.0 14743636.0 25756544.0
3 2025-09-29 24622215.0 25316093.0 12995653.0 14384529.0 16427705.0 27151393.0
4 2025-10-06 25847866.0 26581176.0 13222698.0 15294940.0 17649771.0 29411131.0

Seasonal overlay chart

Plot each marketing year as a separate line. The current year stands out with a thicker line.

[4]
fig, ax = plt.subplots(figsize=(10, 5)) pvt.plot(ax=ax, style='--', alpha=0.5, linewidth=1.2, legend=True) # Highlight the current marketing year ax.lines[-1].set(linestyle='-', linewidth=2.5, alpha=1.0) ax.set_xlabel('Date') ax.set_ylabel('Total Commitments (MT)') ax.set_title('Corn Export Commitments — Seasonal Overlay') ax.legend([f"MY {yr}" for yr in pvt.columns]) plt.tight_layout() plt.show()