Overall Statistics |
Total Trades 246 Average Win 1.12% Average Loss -1.24% Compounding Annual Return 3.293% Drawdown 19.200% Expectancy 0.037 Net Profit 3.311% Sharpe Ratio 0.265 Probabilistic Sharpe Ratio 22.861% Loss Rate 46% Win Rate 54% Profit-Loss Ratio 0.90 Alpha 0.083 Beta -0.355 Annual Standard Deviation 0.212 Annual Variance 0.045 Information Ratio -0.065 Tracking Error 0.279 Treynor Ratio -0.159 Total Fees $3844.50 Estimated Strategy Capacity $1200000.00 |
from datetime import timedelta, datetime class FocusedYellowLemur(QCAlgorithm): def Initialize(self): self.SetStartDate(2015, 12, 1) # Set Start Date self.SetEndDate(2016, 12, 1) self.SetCash(100000) # Set Strategy Cash self.Data = {} for ticker in ["TSLA","AAPL"]: symbol = self.AddEquity(ticker, Resolution.Hour, Market.USA).Symbol self.Data[symbol] = SymbolData(self, symbol) self.stopLossLevel = -0.05 # stop loss percentage self.stopProfitLevel = 0.01# stop profit percentage self.tolerance = 1.01 self.SetWarmUp(100, Resolution.Hour) def OnData(self, data): if self.IsWarmingUp: return for symbol, symbolData in self.Data.items(): if not (data.ContainsKey(symbol) and data[symbol] is not None and symbolData.IsReady): continue fast = symbolData.fast.Current.Value slow = symbolData.slow.Current.Value current_price = symbolData.closeWindow[0] #current_price = data[symbol].Close self.is_uptrend = fast > slow * self.tolerance self.is_downtrend = slow > fast * self.tolerance if self.Portfolio[symbol].Invested: if self.isLong: condStopProfit = (current_price - self.buyInPrice)/self.buyInPrice > self.stopProfitLevel condStopLoss = (current_price - self.buyInPrice)/self.buyInPrice < self.stopLossLevel if condStopProfit: self.Liquidate(symbol) self.Log(f"{self.Time} Long Position Stop Profit at {current_price}") if condStopLoss: self.Liquidate(symbol) self.Log(f"{self.Time} Long Position Stop Loss at {current_price}") else: condStopProfit = (self.sellInPrice - current_price)/self.sellInPrice > self.stopProfitLevel condStopLoss = (self.sellInPrice - current_price)/self.sellInPrice < self.stopLossLevel if condStopProfit: self.Liquidate(symbol) self.Log(f"{self.Time} Short Position Stop Profit at {current_price}") if condStopLoss: self.Liquidate(symbol) self.Log(f"{self.Time} Short Position Stop Profit at {current_price}") if not self.Portfolio[symbol].Invested: uptrend = self.is_uptrend downtrend = self.is_downtrend if downtrend and current_price < fast: self.SetHoldings(symbol, 0) # get buy-in price for trailing stop loss/profit self.buyInPrice = current_price # entered long position self.isLong = True #Timebought = self.Time self.Log(f"{self.Time} Entered Long Position at {current_price}") if uptrend and current_price > fast: self.SetHoldings(symbol, -1) # get sell-in price for trailing stop loss/profit self.sellInPrice = current_price # entered short position self.isLong = False #Timesold = self.Time self.Log(f"{self.Time} Entered Short Position at {current_price}") class SymbolData: def __init__(self, algorithm, symbol): self.fast = SimpleMovingAverage(5) #Resolution.Hour self.fastWindow = RollingWindow[IndicatorDataPoint](2) #Generating 5-period SMA values of 4 hours Resolution algorithm.RegisterIndicator(symbol, self.fast, timedelta(hours=4)) self.fast.Updated += self.FastUpdated self.slow = SimpleMovingAverage(10) #Resolution.Hour self.slowWindow = RollingWindow[IndicatorDataPoint](2) #Generating 10-period SMA values of 4 hours Resolution. algorithm.RegisterIndicator(symbol, self.slow, timedelta(hours=4)) self.slow.Updated += self.SlowUpdated self.closeWindow = RollingWindow[float](10) # Add consolidator to track rolling close prices self.consolidator = TradeBarConsolidator(timedelta(hours=4)) self.consolidator.DataConsolidated += self.CloseUpdated algorithm.SubscriptionManager.AddConsolidator(symbol, self.consolidator) def FastUpdated(self, sender, updated): '''Event holder to update the fast SMA Rolling Window values''' if self.fast.IsReady: self.fastWindow.Add(updated) def SlowUpdated(self, sender, updated): '''Event holder to update the slow SMA Rolling Window values''' if self.slow.IsReady: self.slowWindow.Add(updated) def CloseUpdated(self, sender, bar): '''Event holder to update the close Rolling Window values''' self.closeWindow.Add(bar.Close) @property def IsReady(self): return self.fast.IsReady and self.slow.IsReady and self.closeWindow.IsReady