Overall Statistics
Total Trades
75
Average Win
7.71%
Average Loss
-3.87%
Compounding Annual Return
7.938%
Drawdown
34.400%
Expectancy
1.102
Net Profit
295.930%
Sharpe Ratio
0.569
Probabilistic Sharpe Ratio
1.277%
Loss Rate
30%
Win Rate
70%
Profit-Loss Ratio
1.99
Alpha
0.025
Beta
0.414
Annual Standard Deviation
0.106
Annual Variance
0.011
Information Ratio
-0.198
Tracking Error
0.124
Treynor Ratio
0.145
Total Fees
$694.08
Estimated Strategy Capacity
$16000000.00
Lowest Capacity Asset
AGG SSC0EI5J2F6T
# https://quantpedia.com/strategies/paired-switching/
#
# This strategy is very flexible. Investors could use stocks, funds, or ETFs as an investment vehicle. We show simple trading rules for a sample strategy
# from the source research paper. The investor uses two Vanguard funds as his investment vehicles – one equity fund (VFINX) and one government bond 
# fund (VUSTX). These two funds have a negative correlation as they are proxies for two negatively correlated asset classes. The investor looks at the
# performance of the two funds over the prior quarter and buys the fund that has a higher return during the ranking period. The position is held for one 
# quarter (the investment period). At the end of the investment period, the cycle is repeated.

class PairedSwitching(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2004, 1, 1)
        self.SetCash(100000)
        
        self.first = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.second = self.AddEquity("AGG", Resolution.Daily).Symbol
        self.months = 3

        self.Schedule.On(self.DateRules.MonthStart(self.first), self.TimeRules.AfterMarketOpen(self.first), self.Rebalance)

    def Rebalance(self):
        if(self.months % 3 == 0):
            if self.Securities.ContainsKey(self.first) and self.Securities.ContainsKey(self.second):
                history_call = self.History([self.first, self.second], timedelta(days=90))
                if not history_call.empty:
                    first_bars = history_call.loc[self.first.Value]
                    last_p1 = first_bars["close"].iloc[0]
    
                    second_bars = history_call.loc[self.second.Value]
                    last_p2 = second_bars["close"].iloc[0]
    
                    # Calculates performance of funds over the prior quarter.
                    first_performance = (float(self.Securities[self.first].Price) - float(last_p1)) / (float(self.Securities[self.first].Price))
                    second_performance = (float(self.Securities[self.second].Price) - float(last_p2)) / (float(self.Securities[self.second].Price))
                    
                    # Buys the fund that has the higher return during the period.
                    if(first_performance > second_performance):
                        if(self.Securities[self.second].Invested):
                            self.Liquidate(self.second)
                        self.SetHoldings(self.first, 1)
                    else:
                        if(self.Securities[self.first].Invested):
                            self.Liquidate(self.first)
                        self.SetHoldings(self.second, 1)

        self.months += 1