Overall Statistics |
Total Trades 334 Average Win 0.01% Average Loss -0.02% Compounding Annual Return -0.254% Drawdown 0.300% Expectancy -0.039 Net Profit -0.156% Sharpe Ratio -0.949 Probabilistic Sharpe Ratio 6.075% Loss Rate 49% Win Rate 51% Profit-Loss Ratio 0.90 Alpha -0.003 Beta 0.001 Annual Standard Deviation 0.003 Annual Variance 0 Information Ratio -2.129 Tracking Error 0.123 Treynor Ratio -2.856 Total Fees $2073.36 |
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel class BankingIndustryStocks(FundamentalUniverseSelectionModel): ''' This module selects the most liquid stocks listed on the Nasdaq Stock Exchange. ''' def __init__(self, filterFineData = True, universeSettings = None, securityInitializer = None): '''Initializes a new default instance of the TechnologyUniverseModule''' super().__init__(filterFineData, universeSettings, securityInitializer) self.numberOfSymbolsCoarse = 1000 self.numberOfSymbolsFine = 100 self.dollarVolumeBySymbol = {} self.lastMonth = -1 def SelectCoarse(self, algorithm, coarse): ''' Performs a coarse selection: -The stock must have fundamental data -The stock must have positive previous-day close price -The stock must have positive volume on the previous trading day ''' if algorithm.Time.month == self.lastMonth: return Universe.Unchanged sortedByDollarVolume = sorted([x for x in coarse if x.HasFundamentalData and x.Volume > 0 and x.Price > 0], key = lambda x: x.DollarVolume, reverse=True)[:self.numberOfSymbolsCoarse] self.dollarVolumeBySymbol = {x.Symbol:x.DollarVolume for x in sortedByDollarVolume} # If no security has met the QC500 criteria, the universe is unchanged. if len(self.dollarVolumeBySymbol) == 0: return Universe.Unchanged return list(self.dollarVolumeBySymbol.keys()) def SelectFine(self, algorithm, fine): ''' Performs a fine selection for companies in the Morningstar Banking Sector ''' # Filter stocks and sort on dollar volume sortedByDollarVolume = sorted([x for x in fine if (\ x.AssetClassification.MorningstarSectorCode == MorningstarSectorCode.FinancialServices ) ], key = lambda x: self.dollarVolumeBySymbol[x.Symbol], reverse=True) if len(sortedByDollarVolume) == 0: return Universe.Unchanged self.lastMonth = algorithm.Time.month return [x.Symbol for x in sortedByDollarVolume[:self.numberOfSymbolsFine]]
from pykalman import KalmanFilter import numpy as np from System.Drawing import Color class VerticalCalibratedCompensator(QCAlgorithm): def Initialize(self): self.SetStartDate(2019, 5, 20) # Set Start Date self.SetEndDate(2019, 12, 30) self.ticker1="MSFT" self.ticker2="SPY" self.SetCash(5000000) # Set Strategy Cash self.AddEquity(self.ticker1, Resolution.Hour) self.AddEquity(self.ticker2, Resolution.Hour) self.delt=.05 self.Delta=0.45 self.TargetXQty=0 self.TargetYQty=0 self.current_state="A" self.next_state="A" self.counter=0 self.state_mean = np.zeros(2) self.state_cov=np.ones((2, 2)) self.delta = 1/2 self.trans_cov = self.delta / (1 - self.delta) * np.eye(2) self.prevAvgXfillPrice=0 self.prevAvgYfillPrice=0 self.kf = KalmanFilter(n_dim_obs=1, n_dim_state=2, initial_state_mean=self.state_mean, initial_state_covariance=self.state_cov, transition_matrices=np.eye(2), observation_covariance=1.0, transition_covariance=self.trans_cov) stockPlot2 = Chart("Beta") stockPlot2.AddSeries(Series('beta', SeriesType.Line,0)) self.AddChart(stockPlot2) stockPlot3 = Chart("Intercept") stockPlot3.AddSeries(Series('intercept', SeriesType.Line, '$', Color.Green)) self.AddChart(stockPlot3) stockPlot1 = Chart('Trade Plot') # On the Trade Plotter Chart we want 3 series: trades and price: stockPlot1.AddSeries(Series('Spread', SeriesType.Line, '$', Color.Green)) stockPlot1.AddSeries(Series('Buy', SeriesType.Scatter, '$', Color.Red, ScatterMarkerSymbol.Triangle)) stockPlot1.AddSeries(Series('Sell', SeriesType.Scatter, '$', Color.Blue, ScatterMarkerSymbol.TriangleDown)) self.AddChart(stockPlot1) def OnData(self, data): if not self.IsMarketOpen(self.ticker1): return if( not(data.ContainsKey(self.ticker1)) or not(data.ContainsKey(self.ticker2)) ): return x=data.Bars[self.ticker1].Close y=data.Bars[self.ticker2].Close self.state_mean, self.state_cov= (self.kf.filter_update( filtered_state_mean =self.state_mean, filtered_state_covariance =self.state_cov, observation = np.array([y]), observation_matrix = np.array([[x,1]]) )) beta=round(self.state_mean[0],2) intercept=round(self.state_mean[1],2) y_hat=round( (x * beta) + intercept , 2) res=round(y-y_hat,2) self.Plot('Trade Plot' , 'Spread', 100 * res) self.Plot('Beta', 'beta', 100 * beta) self.Plot('Intercept', 'intercept', 100 * intercept) #self.Log(f"beta : {beta}") #self.Log(f"intercept : {intercept}") #self.Log(f"state mean {self.state_mean}") #self.Log(f"residue {res}") #self.Log(f"x {x}\ny {y}\n\n") if(-self.delt <= res and res < self.delt): self.next_state="A" if(self.delt<= res and res <self.Delta ): self.next_state="B+" if(self.Delta<= res and res < (2 * self.Delta) ): self.next_state="C+" if( (2 * self.Delta) <= res and res < (3 * self.Delta) ): self.next_state="D+" if( (3 * self.Delta) <= res and res < (4 * self.Delta) ): self.next_state="E+" if( - self.delt >= res and res > -self.Delta ): self.next_state="B-" if(- self.Delta >= res and res > (-2 * self.Delta) ): self.next_state="C-" if( (-2 * self.Delta) >= res and res > (-3 * self.Delta) ): self.next_state="D-" if( (-3 * self.Delta) >= res and res > (-4 * self.Delta) ): self.next_state="E-" if(self.current_state != self.next_state): mf=-400 if(self.next_state=="A"): self.TargetXQty=self.Portfolio[self.ticker1].Quantity self.TargetYQty=self.Portfolio[self.ticker2].Quantity if(self.next_state=="C+"): self.TargetXQty=round(beta*mf,0) self.TargetYQty=-mf if(self.next_state=="D+"): self.TargetXQty=round(beta*3*mf,0) self.TargetYQty=-3*mf if(self.next_state=="E+"): self.TargetXQty=round(beta*7*mf,0) self.TargetYQty=-7*mf if(self.next_state=="C-"): self.TargetXQty=-round(beta*1*mf,0) self.TargetYQty=mf if(self.next_state=="D-"): self.TargetXQty=-round(beta*3*mf,0) self.TargetYQty=3*mf if(self.next_state=="E-"): self.TargetXQty=-round(beta*7*mf,0) self.TargetYQty=7*mf self.TargetXQty=self.TargetXQty self.TargetYQty=self.TargetYQty oldXqty=self.Portfolio[self.ticker1].Quantity oldYqty=self.Portfolio[self.ticker2].Quantity self.xTradeQty=-(oldXqty - self.TargetXQty) self.yTradeQty=-(oldYqty - self.TargetYQty) if(abs(self.yTradeQty)>10): unrealizedProfit=self.Portfolio.TotalUnrealizedProfit orderTicketX=self.MarketOrder(self.ticker1 , self.xTradeQty, True, '') orderTicketY=self.MarketOrder(self.ticker2 , self.yTradeQty, True, '') avgXfillPrice=orderTicketX.AverageFillPrice avgYfillPrice=orderTicketY.AverageFillPrice #Do logging if orderTicketX.Status == OrderStatus.Filled and orderTicketY.Status == OrderStatus.Filled: self.Log(f",{oldXqty},{oldYqty},{self.prevAvgXfillPrice},{self.prevAvgYfillPrice},{x},{y},{res},{beta},{intercept},{unrealizedProfit},{avgXfillPrice},{avgYfillPrice},{self.current_state},{self.next_state}") #update prevAvgXfillPrice prevAvgYfillPrice self.prevAvgXfillPrice=avgXfillPrice self.prevAvgYfillPrice=avgYfillPrice if(self.yTradeQty>0): self.Plot('Trade Plot' , 'Buy', 100 * res) if(self.yTradeQty<0): self.Plot('Trade Plot' , 'Sell', 100 * res) #self.Log(f"moving from {self.current_state} state to state{self.next_state}") self.current_state=self.next_state