该策略主要投资于原油衍生合约(如NYMEX的CL1期货),使用美国能源信息署(EIA)的原油现货价格数据和全球金融不确定性(GFU)指数。投资者使用单变量预测回归模型,根据GFU预测下个月原油价格回报率。策略根据GFU预测,进行原油资产的买入或卖空操作,适用于风险厌恶系数为3的投资者。投资组合包含一个头寸,每月进行再平衡。

策略概述

投资范围主要包括原油的衍生合约 [例如,在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? [点击浏览原文]

<摘要>

本研究识别出一个强有力的预测变量——全球金融不确定性(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

Leave a Reply

Discover more from Quant Buffet

Subscribe now to keep reading and get access to the full archive.

Continue reading