隔夜-日内大宗商品日内反转策略
登录后收藏学术论文
Market Closure and Short-Term Reversal
II. 策略合理性
- Centre for Economic Policy Research
- ?Centre for Economic Policy Research (CEPR)
- ?Imperial College Business School
- University of Oxford
- Quantitative BioSciences
- ?CEPR (Centre for Economic Policy Research)
- ?University of Oxford, Oxford-Man Institute of Quantitative Finance
- Tsinghua University
- ?Tsinghua University, School of Economics and Management
策略概要
该策略针对11种商品期货,包括玉米、CBOT乙醇、瘦猪、活牛等,选择流动性最强的合约。通过买入前一天的隔夜输家和卖出隔夜赢家,构建零投资组合。商品权重使用
回测表现
波动率31.02%
夏普比率1.47
索提诺比率-2.897
胜率44%
完整 Python 代码
from AlgorithmImports import *
#endregion
class OvernightIntradayDailyReversalinCommodities(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2015, 1, 1)
self.SetCash(1000000)
symbols:List[str] = [
Futures.Grains.Corn,
Futures.Meats.LeanHogs,
Futures.Meats.LiveCattle,
Futures.Forestry.Lumber,
Futures.Grains.Oats,
Futures.Grains.SoybeanMeal,
Futures.Grains.Soybeans,
Futures.Grains.Wheat,
]
self.traded_percentage:float = 0.2
self.futures:List[Symbol] = []
self.recent_close:Dict[Symbol, float] = {}
for symbol in symbols:
future = self.AddFuture(symbol, Resolution.Minute, dataNormalizationMode=DataNormalizationMode.BackwardsRatio, contractDepthOffset=0)
self.futures.append(future.Symbol)
self.day_close_flag:bool = False
self.day_open_flag:bool = False
self.Schedule.On(self.DateRules.EveryDay(self.futures[3]), self.TimeRules.BeforeMarketClose(self.futures[3], 1), self.DayClose)
self.Schedule.On(self.DateRules.EveryDay(self.futures[3]), self.TimeRules.AfterMarketOpen(self.futures[3], 1), self.DayOpen)
def OnData(self, data: Slice) -> None:
if self.day_open_flag:
self.day_open_flag = False
returns:Dict[Symbol, float] = { symbol : data[symbol].Open / self.recent_close[symbol] - 1 for symbol in self.futures if symbol in self.recent_close and symbol in data and data[symbol] }
self.recent_close.clear()
long:List[Symbol] = [x[0] for x in returns.items() if x[1] < 0]
short:List[Symbol] = [x[0] for x in returns.items() if x[1] > 0]
for i, portfolio in enumerate([long, short]):
for symbol in portfolio:
# notional value = asset price * contract multiplier
notional_value:float = (self.Securities[symbol].Price * self.Securities[symbol].SymbolProperties.ContractMultiplier)
quantity:int = int((((-1) ** i) * self.Portfolio.TotalPortfolioValue) / len(portfolio) * self.traded_percentage) // notional_value
self.MarketOrder(self.Securities[symbol].Mapped, quantity)
if self.day_close_flag:
self.day_close_flag = False
self.Liquidate()
self.recent_close = { symbol : data[symbol].Close for symbol in self.futures if symbol in data and data[symbol] }
def DayClose(self) -> None:
self.day_close_flag = True
def DayOpen(self) -> None:
self.day_open_flag = True