The Jia Wu Expansion

Australian Market Analysis — Trend · Seasonality · 2010 Forecast

Author

JEPHTHAH PANGURU

Published

March 12, 2026


1 Business Context

Ms. Jia Wu International Co. is a major household goods distributor headquartered in Taiwan, with revenue exceeding 3.7 billion TWD across Southeast Asia. She is evaluating entry into the Australian market.

Analyst Wei-chung Huang was commissioned to analyse monthly retail sales data from the Australian Bureau of Statistics (January 1995 – December 2009) and answer three specific questions:

# Question
1 What is the current trend in monthly household goods sales?
2 What are the seasonal patterns — which months are strong, which are weak?
3 What is the monthly forecast for 2010?

2 The Raw Data

Show code
df_wide <- df_long %>%
  select(Year, Month, Sales) %>%
  pivot_wider(names_from = Month, values_from = Sales) %>%
  select(Year, all_of(months_order)) %>%
  left_join(df_annual %>% select(Year, Annual), by = "Year")

df_wide %>%
  mutate(across(Jan:Annual, ~ comma(.x, accuracy = 0.1))) %>%
  kable(
    caption = "Monthly Retail Sales — Australian Household Goods (AUD Millions)",
    align   = c("l", rep("r", 13))
  ) %>%
  kable_styling(
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    full_width = TRUE, font_size = 11
  ) %>%
  column_spec(1, bold = TRUE, color = col_navy) %>%
  column_spec(14, bold = TRUE, background = col_teal_l)
Monthly Retail Sales — Australian Household Goods (AUD Millions)
Year Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Annual
1995 1,463.9 1,373.3 1,533.7 1,420.6 1,576.3 1,607.5 1,545.7 1,550.8 1,583.0 1,622.6 1,705.5 2,212.4 19,195.3
1996 1,580.7 1,485.5 1,582.6 1,498.9 1,644.5 1,610.9 1,695.0 1,664.9 1,583.8 1,740.4 1,798.7 2,296.1 20,182.0
1997 1,686.0 1,576.9 1,608.8 1,610.8 1,712.9 1,664.3 1,698.0 1,662.9 1,678.9 1,811.1 1,835.5 2,418.4 20,964.5
1998 1,724.9 1,531.3 1,660.0 1,602.0 1,677.0 1,668.8 1,699.6 1,649.9 1,685.0 1,783.6 1,776.0 2,323.2 20,781.3
1999 1,775.4 1,597.2 1,733.6 1,681.0 1,764.5 1,779.0 1,817.4 1,830.7 1,894.3 2,000.7 2,037.0 2,568.3 22,479.1
2000 1,924.7 1,813.6 1,919.9 1,769.8 1,985.7 2,346.3 1,875.7 2,013.1 2,015.7 2,098.2 2,213.3 2,776.0 24,752.0
2001 2,095.8 1,887.4 2,063.2 1,982.7 2,118.3 2,205.1 2,217.5 2,253.1 2,188.7 2,404.9 2,517.4 3,113.9 27,048.0
2002 2,438.8 2,123.9 2,296.4 2,336.0 2,478.6 2,475.0 2,465.3 2,501.2 2,460.6 2,635.3 2,752.9 3,366.1 30,330.1
2003 2,528.5 2,231.8 2,430.7 2,368.9 2,539.9 2,595.6 2,675.1 2,665.2 2,726.7 2,903.8 2,948.3 3,650.5 32,265.0
2004 2,829.9 2,545.4 2,746.3 2,569.2 2,675.2 2,793.8 2,843.3 2,798.1 2,848.0 3,078.3 3,185.1 3,877.3 34,789.9
2005 2,963.1 2,622.9 2,782.9 2,787.4 2,879.3 2,969.3 2,964.4 2,984.4 2,971.0 3,099.2 3,252.9 4,088.1 36,364.9
2006 3,036.0 2,692.5 2,953.4 2,804.1 3,026.2 3,148.2 3,120.4 3,150.1 3,196.1 3,346.8 3,494.0 4,301.3 38,269.1
2007 3,332.3 2,963.4 3,283.3 3,010.1 3,239.8 3,399.0 3,333.5 3,433.6 3,443.2 3,591.4 3,774.4 4,684.7 41,488.7
2008 3,535.1 3,142.9 3,212.5 3,238.4 3,349.2 3,443.7 3,413.8 3,411.0 3,327.8 3,530.5 3,595.6 4,908.6 42,109.1
2009 3,560.7 2,968.2 3,301.6 3,203.9 3,379.7 3,620.6 3,452.3 3,467.7 3,406.1 3,641.3 3,787.3 4,707.5 42,496.9

2.1 Sales Over Time

Show code
ggplot(df_long, aes(x = Date, y = Sales)) +
  geom_line(colour = col_teal, linewidth = 0.5, alpha = 0.7) +
  geom_smooth(method = "lm", se = FALSE, colour = col_navy,
              linewidth = 1.2, linetype = "dashed") +
  scale_y_continuous(labels = comma_format(suffix = "M")) +
  scale_x_date(date_breaks = "2 years", date_labels = "%Y") +
  labs(
    title    = "Australian Household Goods Retail Sales — Jan 1995 to Dec 2009",
    subtitle = "Dashed line = linear trend. Clear upward trajectory with seasonal oscillation.",
    x = NULL, y = "Sales (AUD Millions)",
    caption  = "Source: Australian Bureau of Statistics"
  ) +
  theme_jw()

2.2 Annual Totals

Show code
df_annual %>%
  ggplot(aes(x = Year, y = Annual)) +
  geom_col(fill = col_teal, alpha = 0.85, width = 0.7) +
  geom_text(aes(label = paste0("$", round(Annual/1000, 1), "B")),
            vjust = -0.4, size = 3, colour = col_navy, fontface = "bold") +
  scale_y_continuous(labels = comma_format(suffix = "M")) +
  scale_x_continuous(breaks = 1995:2009) +
  labs(
    title    = "Annual Retail Sales — 1995 to 2009",
    subtitle = "Market grew from AUD 19,195M (1995) to AUD 42,497M (2009) — +121% over 15 years",
    x = NULL, y = "Annual Sales (AUD Millions)",
    caption  = "Source: Australian Bureau of Statistics"
  ) +
  theme_jw() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))


3 Trend Analysis

3.1 The Linear Regression Model

The trend answers: ignoring seasonal fluctuations, is the underlying market growing?

We fit a straight line through all 180 monthly data points using linear regression.

Show code
# Show model summary
tidy_fit <- broom::tidy(lm_fit)

tidy_fit %>%
  mutate(
    term      = c("Intercept (baseline Jan 1995)", "Slope (growth per month)"),
    estimate  = round(estimate, 4),
    std.error = round(std.error, 4),
    statistic = round(statistic, 2),
    p.value   = format.pval(p.value, digits = 3)
  ) %>%
  kable(
    col.names = c("Parameter", "Estimate", "Std Error", "t-statistic", "p-value"),
    caption   = "Linear Regression Results: Sales ~ t (t = months since Jan 1995)"
  ) %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  column_spec(2, bold = TRUE, color = col_navy)
Linear Regression Results: Sales ~ t (t = months since Jan 1995)
Parameter Estimate Std Error t-statistic p-value
Intercept (baseline Jan 1995) 1312.895 46.0156 28.53 <2e-16
Slope (growth per month) 13.482 0.4446 30.32 <2e-16
NoteKey Finding — Trend

Sales(t) = 1312.89 + 13.482 × t

The market grows by AUD 13.48M every month — equivalent to AUD 162M per year. Over 15 years, total market size more than doubled from AUD 19,195M to AUD 42,497M (+121%).

3.2 Actual vs. Trend

Show code
df_long %>%
  ggplot(aes(x = Date)) +
  geom_line(aes(y = Sales,  colour = "Actual Sales"), linewidth = 0.55, alpha = 0.8) +
  geom_line(aes(y = Trend,  colour = "Linear Trend"), linewidth = 1.3, linetype = "dashed") +
  scale_colour_manual(values = c("Actual Sales" = col_teal, "Linear Trend" = col_navy)) +
  scale_y_continuous(labels = comma_format(suffix = "M")) +
  scale_x_date(date_breaks = "2 years", date_labels = "%Y") +
  annotate("text", x = as.Date("2008-01-01"), y = 1600,
           label = paste0("Slope = +AUD ", round(slope,2), "M/month"),
           colour = col_navy, size = 3.5, fontface = "italic") +
  labs(
    title    = "Actual Sales vs. Linear Trend",
    subtitle = "Seasonal oscillation sits on top of a consistent upward trend",
    x = NULL, y = "Sales (AUD Millions)",
    caption  = "Source: Australian Bureau of Statistics"
  ) +
  theme_jw()

3.3 Annual YoY Growth

Show code
df_annual %>%
  filter(!is.na(YoY)) %>%
  ggplot(aes(x = Year, y = YoY,
             fill = ifelse(YoY >= 0, "Positive", "Negative"))) +
  geom_col(width = 0.7, alpha = 0.85) +
  geom_hline(yintercept = 0, colour = col_navy, linewidth = 0.8) +
  geom_text(aes(label = percent(YoY, accuracy = 0.1)),
            vjust = ifelse(df_annual$YoY[-1] >= 0, -0.4, 1.2),
            size = 3, fontface = "bold") +
  scale_fill_manual(values = c("Positive" = col_teal, "Negative" = col_red)) +
  scale_y_continuous(labels = percent_format()) +
  scale_x_continuous(breaks = 1996:2009) +
  labs(
    title    = "Year-on-Year Growth Rate",
    subtitle = "Only one dip (1998, Asian Financial Crisis). Growth slowed 2008–2009 (GFC).",
    x = NULL, y = "YoY Growth %",
    caption  = "Source: Australian Bureau of Statistics"
  ) +
  theme_jw() +
  theme(legend.position = "none",
        axis.text.x = element_text(angle = 45, hjust = 1))


4 Seasonal Analysis

4.1 How Seasonal Indices Work

\[\text{Seasonal Index} = \frac{\text{Monthly Average (across all years)}}{\text{Overall Monthly Average}} \times 100\]

  • Index above 100 → that month consistently sells above the annual average
  • Index below 100 → that month consistently sells below the annual average

4.2 Seasonal Index Table

Show code
seasonal_tbl %>%
  mutate(
    AvgSales  = comma(AvgSales,  accuracy = 0.1),
    SeasIndex = round(SeasIndex, 1),
    vs_avg    = paste0(ifelse(vs_avg > 0, "+", ""), round(vs_avg, 1), "%")
  ) %>%
  select(Month, AvgSales, SeasIndex, vs_avg, Signal) %>%
  kable(
    col.names = c("Month", "15-Year Average (AUD M)",
                  "Seasonal Index", "vs. Average", "Signal"),
    caption   = "Seasonal Indices — Australian Household Goods Sales",
    align     = c("l","r","c","c","l")
  ) %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  row_spec(which(levels(seasonal_tbl$Month) == "Dec"), bold = TRUE,
           background = col_teal_l, color = col_green) %>%
  row_spec(which(levels(seasonal_tbl$Month) == "Feb"), bold = TRUE,
           background = col_red_l,  color = col_red)
Seasonal Indices — Australian Household Goods Sales
Month 15-Year Average (AUD M) Seasonal Index vs. Average Signal
Jan 2,431.7 96.5 -3.5% Near average
Feb 2,170.4 86.1 -13.9% Below average
Mar 2,340.6 92.9 -7.1% Near average
Apr 2,258.9 89.7 -10.3% Below average
May 2,403.1 95.4 -4.6% Near average
Jun 2,488.5 98.8 -1.2% Near average
Jul 2,454.5 97.4 -2.6% Near average
Aug 2,469.1 98.0 -2% Near average
Sep 2,467.3 97.9 -2.1% Near average
Oct 2,619.2 104.0 +4% Near average
Nov 2,711.6 107.6 +7.6% Above average
Dec 3,419.5 135.7 +35.7% Above average

4.3 Seasonal Pattern Chart

Show code
seasonal_tbl %>%
  ggplot(aes(x = Month, y = SeasIndex, fill = Signal)) +
  geom_col(width = 0.72, alpha = 0.9) +
  geom_hline(yintercept = 100, linetype = "dashed",
             colour = col_navy, linewidth = 1) +
  geom_text(aes(label = round(SeasIndex, 1)),
            vjust  = -0.45, size = 3.2, fontface = "bold") +
  scale_fill_manual(values = c(
    "Above average" = col_teal,
    "Near average"  = "#5DADE2",
    "Below average" = col_red
  )) +
  scale_y_continuous(limits = c(70, 145),
                     breaks = seq(70, 140, 10)) +
  annotate("text", x = 12, y = 140,
           label = "Dec: PEAK\n+35.7% above avg",
           colour = col_green, size = 3, fontface = "bold", hjust = 1) +
  annotate("text", x = 2, y = 80,
           label = "Feb: WEAKEST\n−13.9% below avg",
           colour = col_red, size = 3, fontface = "bold") +
  labs(
    title    = "Seasonal Indices — All 12 Months",
    subtitle = "Dashed line = average (index 100). December dominates; February is the low point.",
    x = NULL, y = "Seasonal Index",
    caption  = "Index > 100 = above average month; Index < 100 = below average month"
  ) +
  theme_jw()

4.4 Average Sales Profile — Month by Month

Show code
seasonal_tbl %>%
  ggplot(aes(x = Month, y = AvgSales, group = 1)) +
  geom_area(fill = col_teal, alpha = 0.15) +
  geom_line(colour = col_teal, linewidth = 1.2) +
  geom_point(aes(colour = Signal), size = 4) +
  scale_colour_manual(values = c(
    "Above average" = col_green,
    "Near average"  = col_navy,
    "Below average" = col_red
  )) +
  scale_y_continuous(labels = comma_format(suffix = "M"),
                     limits = c(1800, 3700)) +
  geom_text(aes(label = comma(round(AvgSales, 0), suffix = "M")),
            vjust = -0.8, size = 2.8, colour = col_navy) +
  labs(
    title    = "Average Monthly Sales Profile (15-Year Average)",
    subtitle = "Q4 (Oct–Dec) is the critical selling window every year",
    x = NULL, y = "Average Sales (AUD Millions)",
    caption  = "Average across 1995–2009"
  ) +
  theme_jw()

ImportantKey Finding — Seasonality

December (index 135.7) is 35.7% above the monthly average — driven by Christmas gifting and Australian summer. Q4 (Oct–Nov–Dec) accounts for approximately 28% of annual sales in just 3 months. February (index 86.1) is the weakest month — the post-Christmas spending hangover.


5 2010 Monthly Forecast

5.1 Forecasting Method

\[\text{Forecast}(t) = \underbrace{(\text{Intercept} + \text{Slope} \times t)}_{\text{Trend component}} \times \underbrace{\text{Seasonal Index}}_{\text{Seasonal adjustment}}\]

Where \(t = 180\) for January 2010 through \(t = 191\) for December 2010.

5.2 Forecast Table

Show code
forecast_tbl %>%
  mutate(
    TrendVal   = comma(TrendVal,   accuracy = 0.1),
    SeasIdx    = round(SeasIdx,    3),
    Forecast   = comma(Forecast,   accuracy = 0.1),
    Actual2009 = comma(Actual2009, accuracy = 0.1),
    vs2009     = percent(vs2009,   accuracy = 0.1)
  ) %>%
  select(Month, t, TrendVal, SeasIdx, Forecast, Actual2009, vs2009) %>%
  kable(
    col.names = c("Month", "t", "Trend Value (AUD M)", "Seas. Index",
                  "Forecast (AUD M)", "2009 Actual (AUD M)", "vs 2009"),
    caption   = "2010 Monthly Forecast — Trend × Seasonal Adjustment",
    align     = c("l","c","r","c","r","r","c")
  ) %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  row_spec(which(forecast_tbl$Month == "Dec"), bold = TRUE,
           background = col_teal_l, color = col_green) %>%
  row_spec(which(forecast_tbl$Month == "Feb"), bold = TRUE,
           background = col_red_l,  color = col_red)
2010 Monthly Forecast — Trend × Seasonal Adjustment
Month t Trend Value (AUD M) Seas. Index Forecast (AUD M) 2009 Actual (AUD M) vs 2009
Jan 180 3,739.7 0.965 3,609.3 3,560.7 1.4%
Feb 181 3,753.1 0.861 3,233.1 2,968.2 8.9%
Mar 182 3,766.6 0.929 3,499.1 3,301.6 6.0%
Apr 183 3,780.1 0.897 3,389.1 3,203.9 5.8%
May 184 3,793.6 0.954 3,618.3 3,379.7 7.1%
Jun 185 3,807.1 0.988 3,760.1 3,620.6 3.9%
Jul 186 3,820.5 0.974 3,721.9 3,452.3 7.8%
Aug 187 3,834.0 0.980 3,757.3 3,467.7 8.4%
Sep 188 3,847.5 0.979 3,767.7 3,406.1 10.6%
Oct 189 3,861.0 1.040 4,013.7 3,641.3 10.2%
Nov 190 3,874.5 1.076 4,169.8 3,787.3 10.1%
Dec 191 3,888.0 1.357 5,276.7 4,707.5 12.1%

Total 2010 Forecast: AUD NAM vs. 2009 Actual: AUD NAM (+7.8% growth)

5.3 Forecast Chart — 2010 vs 2009

Show code
forecast_tbl %>%
  select(Month, Forecast, Actual2009) %>%
  pivot_longer(cols = c(Forecast, Actual2009),
               names_to = "Series", values_to = "Sales") %>%
  mutate(Series = recode(Series,
    "Forecast"   = "2010 Forecast",
    "Actual2009" = "2009 Actual")) %>%
  ggplot(aes(x = Month, y = Sales, fill = Series)) +
  geom_col(position = "dodge", width = 0.7, alpha = 0.88) +
  scale_fill_manual(values = c("2010 Forecast" = col_teal,
                               "2009 Actual"   = col_navy)) +
  scale_y_continuous(labels = comma_format(suffix = "M")) +
  geom_text(aes(label = comma(round(Sales, 0))),
            position = position_dodge(width = 0.7),
            vjust = -0.4, size = 2.5, fontface = "bold") +
  labs(
    title    = "2010 Forecast vs. 2009 Actual — Month by Month",
    subtitle = "Every month in 2010 is projected above 2009. December peak: AUD 5,277M.",
    x = NULL, y = "Sales (AUD Millions)",
    caption  = "Forecast method: Linear trend × seasonal index"
  ) +
  theme_jw()

5.4 Full Time Series with 2010 Forecast

Show code
# Extend with Holt-Winters for confidence intervals
hw_model <- HoltWinters(ts_sales)
hw_fc    <- forecast(hw_model, h = 12)

autoplot(hw_fc) +
  scale_y_continuous(labels = comma_format(suffix = "M")) +
  scale_colour_manual(values = c(col_teal)) +
  labs(
    title    = "Full Time Series with 2010 Forecast (Holt-Winters Model)",
    subtitle = "Shaded regions = 80% and 95% prediction intervals",
    x = NULL, y = "Sales (AUD Millions)",
    caption  = "Holt-Winters exponential smoothing with multiplicative seasonality"
  ) +
  theme_jw() +
  theme(legend.position = "none")

NoteKey Finding — 2010 Forecast

Total 2010 forecast is AUD 45,816M — up +7.8% on 2009. December 2010 alone is forecast at AUD 5,277M, the single largest month of the year. February 2010 is the weakest at AUD 3,233M.


6 Recommendation for Jia Wu

Show code
tibble(
  Question = c(
    "What is the trend?",
    "What are the seasonal patterns?",
    "What is the 2010 forecast?"
  ),
  Answer = c(
    paste0("Strongly upward. Market grew +121% from 1995–2009. Adds AUD ",
           round(slope*12,0), "M per year. Entry timing is favourable."),
    "December (index 135.7) is the dominant month — Christmas + Australian summer. Q4 = 28% of annual sales. February (86.1) is the weakest.",
    paste0("AUD ", comma(round(sum(forecast_tbl$Forecast),0)),
           "M total (+7.8% vs 2009). December peaks at AUD ",
           comma(round(forecast_tbl$Forecast[12],0)), "M.")
  )
) %>%
  kable(caption = "Answers to the Three Questions") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = TRUE) %>%
  column_spec(1, bold = TRUE, color = col_navy, width = "25%") %>%
  column_spec(2, width = "75%")
Answers to the Three Questions
Question Answer
What is the trend? Strongly upward. Market grew +121% from 1995–2009. Adds AUD 162M per year. Entry timing is favourable.
What are the seasonal patterns? December (index 135.7) is the dominant month — Christmas + Australian summer. Q4 = 28% of annual sales. February (86.1) is the weakest.
What is the 2010 forecast? AUD 45,816M total (+7.8% vs 2009). December peaks at AUD 5,277M.
TipStrategic Recommendations for Jia Wu International

1. Enter the market. The Australian household goods market is large, growing consistently, and shows no signs of structural decline. The trend is your friend.

2. Enter in Q1 or Q2 2010. Build supplier relationships and logistics infrastructure before October. Missing the Q4 peak window means missing 28% of annual sales in just three months.

3. Maximise inventory for October–December. December runs 35.7% above the monthly average. A supply chain that cannot deliver at Christmas has failed its most important test.

4. Plan for February–April weakness. Use this period for inventory replenishment, supplier meetings, and staff training — not revenue targets.

5. The market is the market. The structural growth is real — Australia’s household goods retail sector has grown every single year except 1998 (Asian Financial Crisis). The long-run fundamentals support entry.


7 Appendix — Session Info

Show code
sessionInfo()
R version 4.5.2 (2025-10-31 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26200)

Matrix products: default
  LAPACK version 3.12.1

locale:
[1] LC_COLLATE=English_Nigeria.utf8  LC_CTYPE=English_Nigeria.utf8   
[3] LC_MONETARY=English_Nigeria.utf8 LC_NUMERIC=C                    
[5] LC_TIME=English_Nigeria.utf8    

time zone: Africa/Lagos
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] scales_1.4.0     kableExtra_1.4.0 knitr_1.51       forecast_9.0.1  
 [5] lubridate_1.9.5  forcats_1.0.1    stringr_1.6.0    dplyr_1.2.0     
 [9] purrr_1.2.1      readr_2.2.0      tidyr_1.3.2      tibble_3.3.1    
[13] ggplot2_4.0.2    tidyverse_2.0.0 

loaded via a namespace (and not attached):
 [1] generics_0.1.4     xml2_1.5.2         stringi_1.8.7      lattice_0.22-7    
 [5] hms_1.1.4          digest_0.6.39      magrittr_2.0.4     evaluate_1.0.5    
 [9] grid_4.5.2         timechange_0.4.0   RColorBrewer_1.1-3 fastmap_1.2.0     
[13] Matrix_1.7-4       jsonlite_2.0.0     backports_1.5.0    mgcv_1.9-3        
[17] viridisLite_0.4.3  textshaping_1.0.5  cli_3.6.5          rlang_1.1.7       
[21] splines_4.5.2      withr_3.0.2        yaml_2.3.12        tools_4.5.2       
[25] parallel_4.5.2     tzdb_0.5.0         colorspace_2.1-2   broom_1.0.12      
[29] vctrs_0.7.1        R6_2.6.1           zoo_1.8-15         lifecycle_1.0.5   
[33] pkgconfig_2.0.3    urca_1.3-4         pillar_1.11.1      gtable_0.3.6      
[37] glue_1.8.0         Rcpp_1.1.1         systemfonts_1.3.2  xfun_0.56         
[41] tidyselect_1.2.1   rstudioapi_0.18.0  farver_2.1.2       htmltools_0.5.9   
[45] nlme_3.1-168       labeling_0.4.3     rmarkdown_2.30     svglite_2.2.2     
[49] timeDate_4052.112  fracdiff_1.5-3     compiler_4.5.2     S7_0.2.1