Overall Statistics |
Total Trades 71 Average Win 1.74% Average Loss -0.25% Compounding Annual Return 14057.506% Drawdown 2.100% Expectancy 0.819 Net Profit 7.993% Sharpe Ratio 155.692 Probabilistic Sharpe Ratio 99.979% Loss Rate 77% Win Rate 23% Profit-Loss Ratio 6.96 Alpha 69.851 Beta -2.08 Annual Standard Deviation 0.461 Annual Variance 0.212 Information Ratio 106.805 Tracking Error 0.68 Treynor Ratio -34.492 Total Fees $211.82 Estimated Strategy Capacity $15000000.00 Lowest Capacity Asset MSFT R735QTJ8XC9X |
from AlgorithmImports import * class BasicAlgo(QCAlgorithm): def Initialize(self): self.SetStartDate(2020, 2, 19) # Set Start Date self.SetEndDate(2020, 2, 24) # Set End Date self.SetCash(100000) # Set Strategy Cash self.symbol = self.AddEquity("MSFT", Resolution.Second).Symbol self.td = float(self.GetParameter("tick_amount")) self.window_size_p = int(float(self.GetParameter("window_size_p"))) self.window_size_n = int(float(self.GetParameter("window_size_n"))) self.prob_threshold = float(self.GetParameter("pt")) renkoClose = ClassicRenkoConsolidator(self.td) renkoClose.DataConsolidated += self.HandleRenkoClose self.SubscriptionManager.AddConsolidator(self.symbol, renkoClose) self.next_positive_prob = 0 self.next_negative_prob = 0 self.next_positive_prob_1 = 0 self.next_negative_prob_1 = 0 self.next_positive_prob_2 = 0 self.next_negative_prob_2 = 0 self.tick_seq = [] self.index_list = [] self.cash_rate = 0.005 self.leverage_rate = .0075 self.short_rate = 0.0025 self.leverage_costs = 0 self.cash_interests = 0 self.short_costs = 0 self.max_leverage = 2 self.window_total_p = 0 self.window_total_n = 0 self.positive_ticks = 0 self.next_positive = 0 self.negative_ticks = 0 self.next_negative = 0 self.window_total_2_p = 0 self.window_total_2_n = 0 self.positive_ticks_2 = 0 self.next_positive_2 = 0 self.negative_ticks_2 = 0 self.next_negative_2 = 0 def OnData(self, data): self.next_positive_prob = self.next_positive_prob_1 self.next_negative_prob = self.next_negative_prob_1 if not self.Portfolio.Invested: if self.next_negative_prob > self.prob_threshold: if sum(self.tick_seq[-(self.window_size_n)+1:]) == -self.window_size_n+1: self.SetHoldings(self.symbol,-1) self.Debug('Shorted at ' + str(data[self.symbol].Close)) if self.next_positive_prob > self.prob_threshold: if sum(self.tick_seq[-(self.window_size_p)+1:]) == self.window_size_p-1: self.SetHoldings(self.symbol,1) self.Debug('Bought at ' + str(data[self.symbol].Close)) if self.Portfolio[self.symbol].IsShort: if sum(self.tick_seq[-(self.window_size_n)+1:]) == self.window_size_n-1: self.SetHoldings(self.symbol, 0) self.Debug('Stoped short at '+ str(data[self.symbol].Close)) if self.Portfolio[self.symbol].IsLong: if sum(self.tick_seq[-(self.window_size_p)+1:]) == -self.window_size_p+1: self.Liquidate() self.Debug('Liqudated at '+ str(data[self.symbol].Close)) def HandleRenkoClose(self, sender, data): self.Debug(f"CLOSE - {data.Time} - {data.Open} {data.Close} {self.Securities[self.symbol].Price}") if data.Open < data.Close: self.tick_seq.append(1) else: self.tick_seq.append(-1) self.Get_Probabilities() def Get_Probabilities(self): if len(self.tick_seq) == 0: return self.tick_idx = [i for i in range(len(self.tick_seq))] for i in range(self.window_size_p ,len(self.tick_seq)+1): self.window_total_p = np.sum( self.tick_seq[i-self.window_size_p:i-1] ) if self.window_total_p == self.window_size_p-1: self.positive_ticks += 1 if self.tick_seq[i-1] == 1: self.next_positive += 1 for i in range(self.window_size_n ,len(self.tick_seq)+1): self.window_total_n = np.sum( self.tick_seq[i-self.window_size_n:i-1] ) if -self.window_total_n == self.window_size_n-1: self.negative_ticks += 1 if self.tick_seq[i-1] == -1: self.next_negative += 1 if self.positive_ticks == 0: self.next_positive_prob_1 = 0 else: self.next_positive_prob_1 = self.next_positive/self.positive_ticks if self.negative_ticks == 0: self.next_negative_prob_1=0 else: self.next_negative_prob_1 = self.next_negative /self.negative_ticks self.Debug('Renko N. Positive probability: ' + str(self.next_positive_prob_1) +' negative probability ' + str(self.next_negative_prob_1))