“该策略主要投资于原油衍生合约(如NYMEX的CL1期货),使用美国能源信息署(EIA)的原油现货价格数据和全球金融不确定性(GFU)指数。投资者使用单变量预测回归模型,根据GFU预测下个月原油价格回报率。策略根据GFU预测,进行原油资产的买入或卖空操作,适用于风险厌恶系数为3的投资者。投资组合包含一个头寸,每月进行再平衡。”
资产类别:差价合约(CFDs)、交易所交易基金(ETFs)、期货 | 区域:全球 | 频率:月度 | 市场:大宗商品 | 关键词:原油,预测
策略概述
投资范围主要包括原油的衍生合约 [例如,在NYMEX交易的轻质原油期货连续合约CL1!] (或现货市场)。
(原油回报的数据基于美国炼油厂进口原油的获取成本的现货价格。这些数据来自多个来源,原油价格数据由美国能源信息署(EIA)收集。全球金融不确定性(GFU)数据则来自Giovanni Caggiano的主页:https://sites.google.com/site/giovannicaggiano72/home。)
<计算>
投资者应使用简单的单变量预测回归模型方程(1),其响应变量是下个月t+1的原油价格回报率,预测变量为GFU。
该策略利用GFU的经济意义,实施类似于Gao等人(2018)和He等人(2021)的市场时机策略:具体来说,投资者根据GFU预测的下个月价格走势,买入或卖空原油资产。(策略的计算适用于风险厌恶系数为三的投资者 [按CER计算]。)最终的策略投资组合包含一个头寸,并定期每月进行再平衡。
策略合理性
科学家们通过利用全球金融不确定性(GFU)作为新的替代经济变量预测世界上最知名且最具流动性的商品价格,开创了一种新方法。这项研究为现有文献增添了重要的发现,显著提高了全球对原油回报预测的理解,并引入了GFU作为一个信息丰富且稳健的预测指标。作者验证了GFU的卓越表现在不同的经济指标和原油价格代理中仍然保持稳健。GFU作为原油价格预测文献中的有力补充,不仅在统计上优异,而且在经济上也具有重要价值。
论文来源
Forecasting Crude Oil Prices: Does Global Financial Uncertainty Matter? [点击浏览原文]
- Yong Ma, Shuaibing Li, Mingtao Zhou,湖南大学金融与统计学院
<摘要>
本研究识别出一个强有力的预测变量——全球金融不确定性(GFU),用于预测原油回报。我们的分析显示,与其他著名的不确定性指标和宏观经济预测变量相比,GFU在预测原油价格方面展现出更强的预测能力,其样本内的R^2为5.13%,样本外的R_{OS}^2为3.27%。从经济上来看,我们证明了基于GFU的回报预测,均方差投资者能够获得相对于竞争预测变量的显著经济收益。最后,我们的实证结果在面对不同经济指标和原油价格代理时,仍然具有显著的稳健性。


回测表现
| 年化收益率 | 4.65% |
| 波动率 | 19.38% |
| Beta | -0.206 |
| 夏普比率 | 0.24 |
| 索提诺比率 | N/A |
| 最大回撤 | N/A |
| 胜率 | 31% |
完整python代码
from AlgorithmImports import *
import data_tools
import statsmodels.api as sm
# endregion
class ForecastingCrudeOilPrices(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)
leverage:int = 3
self.oil:Symbol = self.AddData(data_tools.QuantpediaFutures, 'CME_CL1', Resolution.Daily).Symbol
self.Securities[self.oil].SetLeverage(leverage)
self.gfu:Symbol = self.AddData(data_tools.GFU, 'GFU', Resolution.Daily).Symbol
# self.test_size:float = 0.2
self.min_period:int = 12
self.price_storage:Dict[Symbol, List] = {}
for symbol in [self.oil, self.gfu]:
self.price_storage[symbol] = []
def OnData(self, data: Slice) -> None:
rebalance = False
# store daily price
if self.gfu in data and data[self.gfu]:
self.price_storage[self.gfu].append(data[self.gfu].Value)
self.price_storage[self.oil].append(self.Securities[self.oil].Price)
rebalance = True
# rebalance once new GFU data arrived
if rebalance:
last_update_date = [c.get_last_update_date() for c in [data_tools.QuantpediaFutures, data_tools.GFU]]
if all(self.Securities[symbol].GetLastData() and last_update_date[i] > self.Time.date() for i, symbol in enumerate([self.oil, self.gfu])):
if all(len(self.price_storage[symbol]) >= self.min_period for symbol in [self.oil, self.gfu]):
oil_prices:np.ndarray = np.array(self.price_storage[self.oil])
x:np.ndarray = np.array(self.price_storage[self.gfu])[1:]
y:np.ndarray = np.log(oil_prices[1:] / oil_prices[:-1]) # oil monthly log returns
# run regression
model = data_tools.multiple_linear_regression(x[:-1], y[1:])
predicted_oil_return:float = model.predict([1, x[-1]])[0]
# test_size:int = int(len(self.price_storage[self.oil]) * self.test_size)
# model = data_tools.multiple_linear_regression(x[:-1][:-test_size], y[1:][:-test_size])
# predicted_oil_return:float = model.predict(sm.add_constant(x[-test_size:]))[-1] if test_size > 1 else model_.predict([1, x[-test_size:]])[-1][0]
# trade based on prediction
if predicted_oil_return > 0:
self.SetHoldings(self.oil, 1)
else:
# self.Liquidate(self.oil)
self.SetHoldings(self.oil, -1)
else:
self.Liquidate()
return
