Overall Statistics
Total Trades
364
Average Win
1.03%
Average Loss
-0.75%
Compounding Annual Return
1.761%
Drawdown
9.000%
Expectancy
0.305
Net Profit
49.105%
Sharpe Ratio
0.418
Probabilistic Sharpe Ratio
0.024%
Loss Rate
45%
Win Rate
55%
Profit-Loss Ratio
1.37
Alpha
0.011
Beta
0.034
Annual Standard Deviation
0.03
Annual Variance
0.001
Information Ratio
-0.28
Tracking Error
0.159
Treynor Ratio
0.365
Total Fees
$1908.59
Estimated Strategy Capacity
$290000000.00
Lowest Capacity Asset
SPY R735QTJ8XC9X
# 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:

from AlgorithmImports import *
from pandas.tseries.offsets import BDay

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

        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):
    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}")

            # edited FED meeting calendar with fake dates inserted for the sake of paper-trading example purpose
            return SubscriptionDataSource("https://data.quantpedia.com/backtesting_data/economic/fed_days_edited.json", SubscriptionTransportMedium.RemoteFile, FileFormat.UnfoldingCollection)

        return SubscriptionDataSource("https://data.quantpedia.com/backtesting_data/economic/fed_days.json", SubscriptionTransportMedium.RemoteFile, FileFormat.UnfoldingCollection)
        
    def Reader(self, config:SubscriptionDataConfig, line:str, date:datetime, isLiveMode:bool) -> BaseData:
        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=15, minute=31)
                # FedDays.algo.Log(f"Parsed {custom_data.Time}")

                end_time = custom_data.Time  
                objects.append(custom_data)

            return BaseDataCollection(end_time, config.Symbol, objects) 

        except ValueError:
            # FedDays.algo.Log(f"Reader Error")
            return None