
Buy DAX index (via ETF, CFD, fund or futures) at European close one day before each US holiday day. Sell on European close during US holiday day. Hold cash otherwise.
ASSET CLASS: CFDs, ETFs, futures | REGION: United States | FREQUENCY:
Daily | MARKET: equities | KEYWORD: US, Holiday, Effect, EU, Markets
I. STRATEGY IN A NUTSHELL
The strategy exploits informational advantages in the options market to forecast stock returns. By analyzing option-based indicators—such as volatility skew, implied-realized volatility spread, and changes in skew—it identifies stocks likely to outperform or underperform. The portfolio goes long on stocks with bullish option signals and short on those with bearish ones, rebalanced weekly for consistency.
II. ECONOMIC RATIONALE
Options markets often reflect private information earlier than equities because of their lower transaction costs, higher leverage, and relaxed short-selling limits. When equity markets lag in incorporating this information, option-implied signals can predict future stock movements.
III. SOURCE PAPER
The Effect of US Holidays on the European Markets: When the Cat’s Away [Click to Open PDF]
Casado, Muga, Santamaria,
<Abstract>
This paper presents evidence of the existence of a return effect on European stock markets coinciding with NYSE holidays, which is particularly marked after positive closing returns on the NYSE the previous day. The effect is large enough to be exploited by trading index futures. This anomaly can not be explained by seasonal effects, such as the day of the week effect, the January effect or the pre-holiday effect, nor is it consistent with behavioral finance models that predict positive correlation between trading volume and returns. However, examination of factors such as information volume or investor mix provides a reasonable explanation.


IV. BACKTEST PERFORMANCE
| Annualised Return | 6.52% |
| Volatility | N/A |
| Beta | 0 |
| Sharpe Ratio | N/A |
| Sortino Ratio | -0.451 |
| Maximum Drawdown | N/A |
| Win Rate | 59% |
V. FULL PYTHON CODE
from AlgorithmImports import *
class USHolidayEUMarkets(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2012, 1, 1)
self.SetCash(100000)
data = self.AddData(QuantpediaFutures, "EUREX_FDAX1", Resolution.Daily)
data.SetFeeModel(CustomFeeModel())
self.symbol = data.Symbol
def OnData(self, data):
if self.securities[self.symbol].get_last_data() and self.time.date() > QuantpediaFutures.get_last_update_date()[self.symbol]:
self.liquidate()
return
calendar1 = self.TradingCalendar.GetDaysByType(TradingDayType.PublicHoliday, self.Time, self.Time)
calendar2 = self.TradingCalendar.GetDaysByType(TradingDayType.Weekend, self.Time, self.Time + timedelta(days=2))
holidays = [i.Date for i in calendar1]
weekends = [i.Date for i in calendar2]
# subtract weekends in all holidays
public_holidays = list(set(holidays) - set(weekends))
if data.contains_key(self.symbol) and data[self.symbol]:
if not self.Portfolio.Invested and len(public_holidays) > 0:
self.SetHoldings(self.symbol, 1)
if self.Portfolio.Invested and len(public_holidays) == 0:
self.Liquidate()
# Quantpedia data.
# NOTE: IMPORTANT: Data order must be ascending (datewise)
class QuantpediaFutures(PythonData):
_last_update_date:Dict[Symbol, datetime.date] = {}
@staticmethod
def get_last_update_date() -> Dict[Symbol, datetime.date]:
return QuantpediaFutures._last_update_date
def GetSource(self, config, date, isLiveMode):
return SubscriptionDataSource("data.quantpedia.com/backtesting_data/futures/{0}.csv".format(config.Symbol.Value), SubscriptionTransportMedium.RemoteFile, FileFormat.Csv)
def Reader(self, config, line, date, isLiveMode):
data = QuantpediaFutures()
data.Symbol = config.Symbol
if not line[0].isdigit(): return None
split = line.split(';')
data.Time = datetime.strptime(split[0], "%d.%m.%Y") + timedelta(days=1)
data['back_adjusted'] = float(split[1])
data['spliced'] = float(split[2])
data.Value = float(split[1])
if config.Symbol not in QuantpediaFutures._last_update_date:
QuantpediaFutures._last_update_date[config.Symbol] = datetime(1,1,1).date()
if data.Time.date() > QuantpediaFutures._last_update_date[config.Symbol]:
QuantpediaFutures._last_update_date[config.Symbol] = data.Time.date()
return data
# Custom fee model.
class CustomFeeModel(FeeModel):
def GetOrderFee(self, parameters):
fee = parameters.Security.Price * parameters.Order.AbsoluteQuantity * 0.00005
return OrderFee(CashAmount(fee, "USD"))