Overall Statistics
Total Trades
248
Average Win
3.44%
Average Loss
-3.55%
Compounding Annual Return
15.274%
Drawdown
19.300%
Expectancy
0.255
Net Profit
172.742%
Sharpe Ratio
0.767
Probabilistic Sharpe Ratio
18.164%
Loss Rate
36%
Win Rate
64%
Profit-Loss Ratio
0.97
Alpha
0.12
Beta
-0.044
Annual Standard Deviation
0.151
Annual Variance
0.023
Information Ratio
0.045
Tracking Error
0.215
Treynor Ratio
-2.629
Total Fees
$212227.10
Estimated Strategy Capacity
$330000.00
Lowest Capacity Asset
TMF UBTUG7D0B7TX
import numpy as np

RESOLUTION = Resolution.Minute
LEVERAGE = 1.90

class BondThursdays(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2015, 1, 1)
        self.SetCash(1000000)  
        
        self.bnds = [
            #self.AddEquity("IEF", RESOLUTION).Symbol,  
            #self.AddEquity("TIP", RESOLUTION).Symbol,
            self.AddEquity("TMF", RESOLUTION).Symbol,
            #self.AddEquity("AGG", RESOLUTION).Symbol
        ]
        
        self.mkt = self.AddEquity("SPY", RESOLUTION).Symbol
        
        self.lookback = 60 #int(self.GetParameter("LOOKBACK"))
        self.max_vol = 0.0075 #float(self.GetParameter("MAX_VOL"))
        
        self.prices = RollingWindow[float](2)
        self.daily_returns = RollingWindow[float](self.lookback)
        self.ema = ExponentialMovingAverage(5)
        self.std = 0
        
        self.Warmup(self.mkt, self.lookback * 2)
        
        self.Schedule.On(self.DateRules.EveryDay(self.mkt), self.TimeRules.AfterMarketOpen(self.mkt, 30), self.Update)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Thursday), self.TimeRules.AfterMarketOpen(self.mkt, 10), self.Buy)
        self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday), self.TimeRules.AfterMarketOpen(self.mkt, 10), self.Sell)
        
        
    def Warmup(self, symbol, lookback):
        self.prices.Add(2.4) # random number
        history = self.History(symbol, lookback, Resolution.Daily)
        for time, prices in history.loc[symbol].iterrows():
            self.ema.Update(self.Time, prices["close"])
            self.prices.Add(prices["close"])
            self.daily_returns.Add((self.prices[1] - prices["close"])/self.prices[1])
            self.std = np.std(list(self.daily_returns))
            
    def Update(self):
        close = self.Securities[self.mkt].Close
        self.ema.Update(self.Time, close)
        self.prices.Add(close)
        self.daily_returns.Add((self.prices[1] - close)/self.prices[1])
        self.std = np.std(list(self.daily_returns))
        
    def Buy(self):
        buy = (self.std < self.max_vol) and (self.prices[0] > self.ema.Current.Value)
        if not self.Portfolio.Invested and buy:
            for bnd in self.bnds:
                self.SetHoldings(bnd, LEVERAGE/(len(self.bnds)))
 
    def Sell(self):
        if self.Portfolio.Invested:
            self.Liquidate()