| Overall Statistics |
|
Total Orders
400
Average Win
1.04%
Average Loss
-0.78%
Compounding Annual Return
1.720%
Drawdown
8.700%
Expectancy
0.287
Start Equity
100000
End Equity
153661.15
Net Profit
53.661%
Sharpe Ratio
-0.338
Sortino Ratio
-0.109
Probabilistic Sharpe Ratio
0.010%
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
1.34
Alpha
-0.012
Beta
0.037
Annual Standard Deviation
0.03
Annual Variance
0.001
Information Ratio
-0.341
Tracking Error
0.155
Treynor Ratio
-0.279
Total Fees
$2029.83
Estimated Strategy Capacity
$370000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
Portfolio Turnover
4.34%
|
# https://quantpedia.com/strategies/federal-open-market-committee-meeting-effect-in-stocks/
#
# The investor is invested in stocks during FOMC meetings (going long S&P 500 ETF, fund, future, or CFD on a close one day before the meeting and closing position on close after the meeting).
# Otherwise, he is invested in cash during the remaining days. The strategy has very low exposure to the stock market (8 days during the average year); therefore, it can be very easily leveraged
# to gain very significant returns.
#
# QC implementation changes:
# - FED dates are imported from text file.
from AlgorithmImports import *
from pandas.tseries.offsets import BDay
from datetime import datetime
class FederalOpenMarketCommitteeMeetingEffectinStocks(QCAlgorithm):
def Initialize(self) -> None:
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)
self.market:Symbol = self.AddEquity("SPY", Resolution.Minute).Symbol
self.fed_days_symbol:Symbol = self.AddData(FedDays, 'fed_days', Resolution.Daily, TimeZones.NewYork).Symbol
self.SetWarmUp(1, Resolution.Daily)
FedDays.set_algo(self)
self.recent_day:int = -1
def OnData(self, data: Slice) -> None:
if self.IsWarmingUp: return
# custom data is still coming
if self.securities[self.fed_days_symbol].get_last_data() and self.time.date() > FedDays.get_last_update_date()[self.fed_days_symbol]:
self.liquidate()
return
if self.fed_days_symbol in data and data[self.fed_days_symbol]:
self.Log(f"New FOMC meeting data arrived: {self.Time}; submitting an MOC order...")
# new fed day data arrived
quantity:float = self.CalculateOrderQuantity(self.market, 1.)
self.MarketOnCloseOrder(self.market, quantity)
self.recent_day = self.Time.day
else:
# other new minute resolution data arrived
if self.Portfolio[self.market].Invested:
if self.Time.day != self.recent_day:
self.recent_day = self.Time.day
self.Log(f"FOMC meeting day; submitting an MOC order to close opened position...")
self.MarketOnCloseOrder(self.market, -self.Portfolio[self.market].Quantity)
class FedDays(PythonData):
_last_update_date:Dict[str, datetime.date] = {}
@staticmethod
def get_last_update_date() -> Dict[str, datetime.date]:
return FedDays._last_update_date
algo = None
@staticmethod
def set_algo(algo):
FedDays.algo = algo
def GetSource(self, config:SubscriptionDataConfig, date:datetime, isLiveMode:bool) -> SubscriptionDataSource:
if isLiveMode:
# FedDays.algo.Log(f"Edited GetSource date {FedDays.algo.Time}")
return SubscriptionDataSource("https://data.quantpedia.com/backtesting_data/economic/fed_days.json", SubscriptionTransportMedium.RemoteFile, FileFormat.UnfoldingCollection)
return SubscriptionDataSource("https://data.quantpedia.com/backtesting_data/economic/fed_days.csv", SubscriptionTransportMedium.RemoteFile)
def Reader(self, config:SubscriptionDataConfig, line:str, date:datetime, isLiveMode:bool) -> BaseData:
if isLiveMode:
try:
# FedDays.algo.Log(f"Reader")
objects = []
data = json.loads(line)
end_time = None
for index, sample in enumerate(data):
custom_data = FedDays()
custom_data.Symbol = config.Symbol
custom_data.Time = (datetime.strptime(str(sample["fed_date"]), "%Y-%m-%d") - BDay(1)).replace(hour=9, minute=31)
# FedDays.algo.Log(f"{custom_data.Time}")
end_time = custom_data.Time
objects.append(custom_data)
# store last update dates
if config.Symbol not in FedDays._last_update_date:
FedDays._last_update_date[config.Symbol] = datetime(1,1,1).date()
if custom_data.Time.date() > FedDays._last_update_date[config.Symbol]:
FedDays._last_update_date[config.Symbol] = custom_data.Time.date()
return BaseDataCollection(end_time, config.Symbol, objects)
except ValueError:
# FedDays.algo.Log(f"Reader Error")
return None
else:
if not (line.strip() and line[0].isdigit()):
return None
custom = FedDays()
custom.Symbol = config.Symbol
custom.Time = (datetime.strptime(line, "%Y-%m-%d") - BDay(1)).replace(hour=9, minute=31)
custom.Value = 0.
custom["fed_date_str"] = line
# store last update dates
if config.Symbol not in FedDays._last_update_date:
FedDays._last_update_date[config.Symbol] = datetime(1,1,1).date()
if custom.Time.date() > FedDays._last_update_date[config.Symbol]:
FedDays._last_update_date[config.Symbol] = custom.Time.date()
return custom