指商品/服务价格因季节、假期、消费习惯、天气等供需因素,在全年呈现周期性波动的现象。
例如航空业中,假期出行需求激增会推高票价,淡季需求低迷则促使票价下降。
通过季节性调整航班排班、运力与票价,实现高季利润最大化,低季减少亏损
依据季节性预判旅客流量,优化值机柜台、跑道使用效率
利用低季低价窗口规划出行,可降低20%-30%出行成本
季节性差异推动航司创新,如LCC在低季推出"早鸟票"
远程办公使商务出行减少30%以上,乘客偏好国内目的地
全球供应链中断导致飞机交付延迟,航司运力恢复缓慢
疫情初期航司为维持现金流被迫大幅降价,可能重塑长期季节性定价习惯
| 研究主题 | 代表学者 | 核心发现 |
|---|---|---|
| 机场类型与季节性 | Halpern (2011) | 旅游机场季节性强于大城市机场,国际/包机加剧季节性 |
| 机场盈利与季节性 | Zuidberg (2017) | 季节性与盈利呈倒"U"型关系 |
| 巴西航空定价 | Póvoa & Oliveira (2008) | 节假日使票价平均上涨8%-10% |
| 巴西航空定价 | Brito et al. (2021) | 机场私有化后部分航线票价上涨5% |
| 旅游季节性 | Cazanova et al. (2014) | 节日/假期是季节性核心驱动 |
| 航司季节性策略 | Merkert & Webber (2018) | 高季应优先提高上座率而非涨价 |
数据来源:巴西民航局(ANAC) 2013年1月-2023年11月国内城市对月度数据
数据平台:哈佛Dataverse平台的AVDATA-BR-CP数据库
* 从哈佛Dataverse导入航空票价数据集
import delimited ///
https://dataverse.harvard.edu/api/access/datafile/avdatabr_cp_cae/8171526, ///
case(preserve) clear
* case(preserve) 保留变量名原始大小写
* clear 清除内存中现有数据
* 筛选样本
* 从哈佛Dataverse导入航空票价数据集
import delimited ///
https://dataverse.harvard.edu/api/access/datafile/avdatabr_cp_cae/8171526, ///
case(preserve) clear
* case(preserve) 保留变量名原始大小写
* clear 清除内存中现有数据
* 保留2013年及以后的数据
keep if Year>=2013
* 生成平均飞机规模变量:可用座位数/出发班次
gen mean_aircsize = nr_available_seats/nr_departures
* 查看平均飞机规模的描述性统计
summ mean_aircsize
* 删除平均飞机规模小于50的观测值(排除小型航线)
drop if mean_aircsize<50
* 按城市对分组,生成每个城市对的观测数量
bysort CityPair: gen nr_panels = [_N]
* 查看面板观测数量的分布
summ nr_panels
* 删除观测数量少于60的城市对
drop if nr_panels<60
* 显示最终样本的面板结构信息
* 城市对数量
tab CityPair
di "城市对数量 = " `r(r)'
* 时间期数(月份)
tab YearMonth
di "时间期数 = " `r(r)'
* 年份数量
tab Year
di "年份数量 = " `r(r)'
* end of section
最终样本:487个城市对、131个月度时期(2013.01-2023.11)
共55,950个观测值
* 生成城市对编码变量
egen k = group(CityPair)
* 生成时间期编码变量
egen t = group(YearMonth)
* 声明面板数据格式:k为个体维度,t为时间维度
tsset k t
* 变量提取...
* 生成城市对编码变量
egen k = group(CityPair)
* 生成时间期编码变量
egen t = group(YearMonth)
* 声明面板数据格式:k为个体维度,t为时间维度
tsset k t
* 从原始数据集中提取需要的变量
keep k t price km_great_circle_distance jetfuel_price_org ///
nr_revenue_pax market_concentration_hhi pc_load_factor ///
YearMonth Year Month CityPair
* 描述性统计:排除时间标识变量
fsum, not(YearMonth k t) format(%10.2f)
* 变量转换...
* 生成城市对编码变量
egen k = group(CityPair)
* 生成时间期编码变量
egen t = group(YearMonth)
* 声明面板数据格式:k为个体维度,t为时间维度
tsset k t
* 从原始数据集中提取需要的变量
keep k t price km_great_circle_distance jetfuel_price_org ///
nr_revenue_pax market_concentration_hhi pc_load_factor ///
YearMonth Year Month CityPair
* 描述性统计:排除时间标识变量
fsum, not(YearMonth k t) format(%10.2f)
* 生成城市对编码变量
egen k = group(CityPair)
* 生成时间期编码变量
egen t = group(YearMonth)
* 声明面板数据格式:k为个体维度,t为时间维度
tsset k t
* 从原始数据集中提取需要的变量
keep k t price km_great_circle_distance jetfuel_price_org ///
nr_revenue_pax market_concentration_hhi pc_load_factor ///
YearMonth Year Month CityPair
* 描述性统计:排除时间标识变量
fsum, not(YearMonth k t) format(%10.2f)
* 生成模型所需的转换变量
* 被解释变量:机票价格的对数
gen AirFare = ln(price)
* 核心解释变量:距离的对数
gen Distance = ln(km_great_circle_distance)
* 核心解释变量:燃油价格的对数
gen FuelPrice = ln(jetfuel_price_org)
* 核心解释变量:乘客密度的对数
gen PaxDens = ln(nr_revenue_pax)
* 核心解释变量:市场集中度的对数(乘以10000避免取对数问题)
gen MktConc = ln(market_concentration_hhi*10000)
* 核心解释变量:载客率的对数
gen LoadFactor = ln(pc_load_factor)
* 疫情虚拟变量:2020年2月-2022年4月期间为1,其余为0
gen Pandemic = (YearMonth>=202002 & YearMonth<=202204)
* 时间趋势变量:将时间标准化到0-2.18范围
gen Trend = t/60
* 季节性变量生成...
* 生成城市对编码变量
egen k = group(CityPair)
* 生成时间期编码变量
egen t = group(YearMonth)
* 声明面板数据格式:k为个体维度,t为时间维度
tsset k t
* 从原始数据集中提取需要的变量
keep k t price km_great_circle_distance jetfuel_price_org ///
nr_revenue_pax market_concentration_hhi pc_load_factor ///
YearMonth Year Month CityPair
* 描述性统计:排除时间标识变量
fsum, not(YearMonth k t) format(%10.2f)
* 生成城市对编码变量
egen k = group(CityPair)
* 生成时间期编码变量
egen t = group(YearMonth)
* 声明面板数据格式:k为个体维度,t为时间维度
tsset k t
* 从原始数据集中提取需要的变量
keep k t price km_great_circle_distance jetfuel_price_org ///
nr_revenue_pax market_concentration_hhi pc_load_factor ///
YearMonth Year Month CityPair
* 描述性统计:排除时间标识变量
fsum, not(YearMonth k t) format(%10.2f)
* 生成模型所需的转换变量
* 被解释变量:机票价格的对数
gen AirFare = ln(price)
* 核心解释变量:距离的对数
gen Distance = ln(km_great_circle_distance)
* 核心解释变量:燃油价格的对数
gen FuelPrice = ln(jetfuel_price_org)
* 核心解释变量:乘客密度的对数
gen PaxDens = ln(nr_revenue_pax)
* 核心解释变量:市场集中度的对数(乘以10000避免取对数问题)
gen MktConc = ln(market_concentration_hhi*10000)
* 核心解释变量:载客率的对数
gen LoadFactor = ln(pc_load_factor)
* 疫情虚拟变量:2020年2月-2022年4月期间为1,其余为0
gen Pandemic = (YearMonth>=202002 & YearMonth<=202204)
* 时间趋势变量:将时间标准化到0-2.18范围
gen Trend = t/60
* 冬季假期虚拟变量:7月为1(巴西学校冬季假期)
gen WintBreak = (Month==7)
* 夏季搜索期虚拟变量:8-11月为1(夏季高峰前的搜索预订期)
gen SummBrSearch = (Month==8 | Month==9 | Month==10 | Month==11)
* 夏季高峰虚拟变量:12月-次年2月为1(巴西夏季旅游高峰)
gen SummBreak = (Month==12 | Month==1 | Month==2)
* 淡季虚拟变量:4-6月为1(旅游淡季)
gen LowSeason = (Month==4 | Month==5 | Month==6)
* end of section
* 转换后变量的描述性统计
fsum AirFare Distance FuelPrice PaxDens MktConc ///
LoadFactor Pandemic Trend
| 变量 | 观测数 | 均值 | 标准差 | 最小值 | 最大值 |
|---|---|---|---|---|---|
| 机票价格(对数) | 55,950 | 6.25 | 0.40 | 4.11 | 8.29 |
| 距离(对数) | 55,950 | 6.65 | 0.68 | 4.68 | 7.95 |
| 燃油价格(对数) | 55,950 | 1.10 | 0.28 | 0.43 | 1.82 |
| 乘客密度(对数) | 55,950 | 8.63 | 1.47 | 2.20 | 12.98 |
| 市场集中度(对数) | 55,950 | 8.61 | 0.39 | 7.80 | 9.21 |
| 载客率(对数) | 55,950 | 4.33 | 0.15 | 2.57 | 4.61 |
| 疫情虚拟变量 | 55,950 | 0.18 | 0.39 | 0.00 | 1.00 |
| 时间趋势 | 55,950 | 1.10 | 0.62 | 0.02 | 2.18 |
无季节性控制:
有季节性控制:在上述公式中加入季节性变量
* 无季节性控制的固定效应回归
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Pandemic Trend ///
, absorb(CityPair)
* absorb(CityPair):控制城市对固定效应
* 存储回归结果
est store WithoutSeas
* 季节性控制...
* 无季节性控制的固定效应回归
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Pandemic Trend ///
, absorb(CityPair)
* absorb(CityPair):控制城市对固定效应
* 存储回归结果
est store WithoutSeas
* 包含季节性控制的固定效应回归
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Pandemic Trend ///
WintBreak SummBrSearch SummBreak LowSeason ///
, absorb(CityPair)
* 存储回归结果
est store WithSeas
* 结果输出...
* 无季节性控制的固定效应回归
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Pandemic Trend ///
, absorb(CityPair)
* absorb(CityPair):控制城市对固定效应
* 存储回归结果
est store WithoutSeas
* 包含季节性控制的固定效应回归
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Pandemic Trend ///
WintBreak SummBrSearch SummBreak LowSeason ///
, absorb(CityPair)
* 存储回归结果
est store WithSeas
* 使用esttab输出两个模型的对比表,并保存为表2
esttab WithoutSeas WithSeas ///
, nocons nose not nogaps noobs ///
b(%9.4f) varwidth(14) brackets ///
aic(%9.0fc) bic(%9.0fc) ar2 scalar(N) sfmt(%9.0fc) ///
addnote("Notes: Fixed Effect estimation")
* nocons: 不显示常数项
* nose: 不显示标准误
* not: 不显示t统计量
* brackets: 标准误放在括号中
* end of section
| 变量 | (1) 无季节性 | (2) 有季节性 |
|---|---|---|
| 燃油价格 | 0.2931*** | 0.2897*** |
| 乘客密度 | -0.0888*** | -0.0937*** |
| 市场集中度 | 0.0854*** | 0.0859*** |
| 载客率 | 0.3121*** | 0.2935*** |
| 疫情变量 | -0.1674*** | -0.1690*** |
| 时间趋势 | 0.0215*** | 0.0180*** |
| 冬季假期 | - | -0.0009 |
| 夏季搜索期 | - | 0.0593*** |
| 夏季高峰 | - | 0.0145*** |
| 淡季 | - | -0.0452*** |
| 调整R² | 0.579 | 0.588 |
| AIC | 8,539 | 7,265 |
| BIC | 8,601 | 7,363 |
| 观测数 | 55,950 | 55,950 |
* p<0.05, ** p<0.01, *** p<0.001
* 生成更细粒度的月度虚拟变量
* 夏季前4个月:8月
gen SummBreak_bef4 = (Month==8)
* 夏季前3个月:9月
gen SummBreak_bef3 = (Month==9)
* 夏季前2个月:10月
gen SummBreak_bef2 = (Month==10)
* 夏季前1个月:11月
gen SummBreak_bef1 = (Month==11)
* 夏季开始月:12月
gen SummBreak_aft0 = (Month==12)
* 夏季后1个月:1月
gen SummBreak_aft1 = (Month==1)
* 夏季后2个月:2月
gen SummBreak_aft2 = (Month==2)
* 淡季第1个月:4月(基准组为3月)
gen LowSeason_aft1 = (Month==4)
* 淡季第2个月:5月
gen LowSeason_aft2 = (Month==5)
* 淡季第3个月:6月
gen LowSeason_aft3 = (Month==6)
* 包含精细化季节性的固定效应回归
* 使用通配符 * 包含所有相关变量
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Pandemic Trend ///
WintBreak SummBreak_* LowSeason_* ///
, absorb(CityPair)
* 存储回归结果
est store GranularSeas
* 使用esttab输出细粒度季节性模型的结果表,并保存为表3
esttab GranularSeas ///
, nocons nose not nogaps noobs ///
b(%9.4f) varwidth(14) brackets ///
aic(%9.0fc) bic(%9.0fc) ar2 scalar(N) sfmt(%9.0fc) ///
addnote("Notes: Fixed Effect estimation")
| 变量 | 系数 |
|---|---|
| 燃油价格 | 0.2910*** |
| 乘客密度 | -0.0941*** |
| 市场集中度 | 0.0865*** |
| 载客率 | 0.2950*** |
| 疫情变量 | -0.1677*** |
| 时间趋势 | 0.0167*** |
| 冬季假期(7月) | -0.0008 |
| 夏季前4月(8月) | 0.0563*** |
| 夏季前3月(9月) | 0.0688*** |
| 夏季前2月(10月) | 0.0812*** |
| 夏季前1月(11月) | 0.0315*** |
| 夏季开始(12月) | 0.0609*** |
| 夏季后1月(1月) | -0.0156** |
| 夏季后2月(2月) | 0.0020 |
| 淡季1月(4月) | -0.0492*** |
| 淡季2月(5月) | -0.0380*** |
| 淡季3月(6月) | -0.0482*** |
| 调整R² | 0.591 |
| 观测数 | 55,950 |
* 使用coefplot绘制GranularSeas模型中季节性变量的系数图,并显示95%置信区间,输出结果为图1
coefplot GranularSeas ///
, keep(WintBreak SummBreak_* SummBreak_* LowSeason_*) ///
xline(0, lcolor(green) lpattern(dash)) scheme(s2color) ///
level(95) recast(connected) lpattern(longdash) lwidth(0.1)
* keep(): 指定要绘制的变量
* xline(0): 在x=0处添加参考线
* scheme(s2color): 使用s2color配色方案
* level(95): 95%置信区间
* recast(connected): 连线图形式
结论:价格季节性呈"先升后降、峰谷分明"特征,10月为全年价格高点,4月为低点
* 疫情前样本回归(2013年1月-2020年1月)
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Trend WintBreak SummBreak_* LowSeason_* ///
if YearMonth<=202001, absorb(CityPair)
* 存储疫情前回归结果
est store PrePandemic
* 疫情后样本回归...
* 疫情前样本回归(2013年1月-2020年1月)
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Trend WintBreak SummBreak_* LowSeason_* ///
if YearMonth<=202001, absorb(CityPair)
* 存储疫情前回归结果
est store PrePandemic
* 疫情后样本回归(2022年5月-2023年11月)
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Trend WintBreak SummBreak_* LowSeason_* ///
if YearMonth>202204, absorb(CityPair)
* 存储疫情后回归结果
est store PostPandemic
* 结果输出...
* 疫情前样本回归(2013年1月-2020年1月)
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Trend WintBreak SummBreak_* LowSeason_* ///
if YearMonth<=202001, absorb(CityPair)
* 存储疫情前回归结果
est store PrePandemic
* 疫情后样本回归(2022年5月-2023年11月)
reghdfe AirFare FuelPrice PaxDens MktConc LoadFactor ///
Trend WintBreak SummBreak_* LowSeason_* ///
if YearMonth>202204, absorb(CityPair)
* 存储疫情后回归结果
est store PostPandemic
* 使用esttab将疫情前与疫情后两组结果并列输出,输出结果为表4
esttab PrePandemic PostPandemic ///
, nocons nose not nogaps noobs mtitles ///
b(%9.4f) varwidth(14) brackets ///
aic(%9.0fc) bic(%9.0fc) ar2 scalar(N) sfmt(%9.0fc) ///
addnote("Notes: Dependent variable - AirFare" ///
"Fixed Effect estimation")
* mtitles: 显示模型标题
* end
| 变量 | 疫情前 | 疫情后 |
|---|---|---|
| 燃油价格 | 0.1677*** | 0.0681* |
| 乘客密度 | -0.1608*** | -0.1466*** |
| 市场集中度 | 0.0889*** | -0.0582*** |
| 载客率 | 0.3020*** | 0.1889*** |
| 时间趋势 | -0.0244*** | 0.2301*** |
| 变量 | 疫情前 | 疫情后 |
|---|---|---|
| 冬季假期(7月) | 0.0668*** | -0.0293* |
| 夏季前4月(8月) | 0.0822*** | 0.0688*** |
| 夏季前3月(9月) | 0.0878*** | 0.0876*** |
| 夏季前2月(10月) | 0.1178*** | 0.0559*** |
| 夏季前1月(11月) | 0.0686*** | 0.0313* |
| 夏季开始(12月) | 0.1107*** | 0.0546*** |
| 夏季后1月(1月) | 0.0263*** | -0.0176 |
| 夏季后2月(2月) | 0.0181** | -0.0486** |
| 淡季1月(4月) | -0.0265*** | -0.1048*** |
| 淡季2月(5月) | -0.0125* | -0.0269* |
| 淡季3月(6月) | -0.0138* | -0.0444** |
| 调整R² | 0.647 | 0.722 |
| 观测数 | 37,441 | 8,373 |
* 用coefplot将疫情前后模型的季节性系数作对比图,便于可视化结构性变化,输出结果为图2
coefplot PrePandemic PostPandemic ///
, keep(WintBreak SummBreak_* SummBreak_* LowSeason_*) ///
xline(0, lcolor(green) lpattern(dash)) scheme(s2color) ///
level(95) recast(connected) lpattern(longdash) lwidth(0.1)
* 同时显示疫情前和疫情后的系数,便于对比结构性变化
结论:疫情后季节性"峰谷差扩大",呈现"去集中化"特征