Overall Statistics
Total Trades
992
Average Win
0.24%
Average Loss
-0.22%
Compounding Annual Return
4.069%
Drawdown
5.200%
Expectancy
0.259
Net Profit
32.501%
Sharpe Ratio
0.718
Probabilistic Sharpe Ratio
16.575%
Loss Rate
39%
Win Rate
61%
Profit-Loss Ratio
1.06
Alpha
0.03
Beta
-0.011
Annual Standard Deviation
0.04
Annual Variance
0.002
Information Ratio
-0.503
Tracking Error
0.154
Treynor Ratio
-2.518
Total Fees
$43217.89
Estimated Strategy Capacity
$1300000.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) + 1))
 
    def Sell(self):
        if self.Portfolio.Invested:
            self.Liquidate()