Overall Statistics |
Total Trades 246 Average Win 1.18% Average Loss -1.33% Compounding Annual Return 2.498% Drawdown 18.100% Expectancy 0.257 Net Profit 48.438% Sharpe Ratio 0.344 Probabilistic Sharpe Ratio 0.224% Loss Rate 33% Win Rate 67% Profit-Loss Ratio 0.89 Alpha 0.025 Beta -0.029 Annual Standard Deviation 0.066 Annual Variance 0.004 Information Ratio -0.37 Tracking Error 0.192 Treynor Ratio -0.794 Total Fees $246.00 |
# Default Imports START from QuantConnect import * from QuantConnect import Orders from QuantConnect.Parameters import * from QuantConnect.Benchmarks import * from QuantConnect.Brokerages import * from QuantConnect.Util import * from QuantConnect.Interfaces import * from QuantConnect.Algorithm import * from QuantConnect.Algorithm.Framework import * from QuantConnect.Algorithm.Framework.Selection import * from QuantConnect.Algorithm.Framework.Alphas import * from QuantConnect.Algorithm.Framework.Portfolio import * from QuantConnect.Algorithm.Framework.Execution import * from QuantConnect.Algorithm.Framework.Risk import * from QuantConnect.Indicators import * from QuantConnect.Data import * from QuantConnect.Data.Consolidators import * from QuantConnect.Data.Custom import * from QuantConnect.Data.Fundamental import * from QuantConnect.Data.Market import * from QuantConnect.Data.UniverseSelection import * from QuantConnect.Notifications import * from QuantConnect.Orders import * from QuantConnect.Orders.Fees import * from QuantConnect.Orders.Fills import * from QuantConnect.Orders.Slippage import * from QuantConnect.Scheduling import * from QuantConnect.Securities import * from QuantConnect.Securities.Equity import * from QuantConnect.Securities.Forex import * from QuantConnect.Securities.Interfaces import * from datetime import date, datetime, timedelta from QuantConnect.Python import * from QuantConnect.Storage import * from System.Drawing import Color QCAlgorithmFramework = QCAlgorithm QCAlgorithmFrameworkBridge = QCAlgorithm # Default Imports ENDfrom typing import Dictfrom typing import Dict from typing import Dict from System import String class MyAlgo(QCAlgorithm): # general secs = [ "SPY" ] maxPositions = len(secs) # indicators sma_duration = 200 rsi_duraction = 14 # buy rsi_buy_level = 30 # sell rsi_sell_level = 40 sell_after_days = 14 def Initialize(self): self.SetStartDate(2005, 1, 1) self.SetEndDate(2020, 12, 31) self.SetCash(10000) self.smas: Dict[String, SimpleMovingAverage] = {} self.rsis: Dict[String, RelativeStrengthIndex] = {} self.bought_at: Dict[String, datetime] = {} for sec in self.secs: self.Debug("Add " + sec + " to view list!") self.AddEquity(sec, Resolution.Daily) self.smas[sec] = self.SMA(sec, self.sma_duration, Resolution.Daily, Field.Close) self.rsis[sec] = self.RSI(sec, self.rsi_duraction, MovingAverageType.Simple , Resolution.Daily, Field.Close) chart = Chart(sec) chart.AddSeries(Series("Price", SeriesType.Line, 0)) chart.AddSeries(Series("Buy", SeriesType.Scatter, 0)) chart.AddSeries(Series("Sell", SeriesType.Scatter, 0)) chart.AddSeries(Series("SMA", SeriesType.Line, 0)) chart.AddSeries(Series("RSI", SeriesType.Line, 1)) chart.AddSeries(Series("RSI Buy Level", SeriesType.Line, 1)) self.AddChart(chart) self.SetWarmUp(max(self.sma_duration, self.rsi_duraction)) def OnData(self, data: Slice): for sec in self.secs: if not data.ContainsKey(sec): self.Debug("Data for " + sec + " not found. Skipping for this day!") break if self.IsWarmingUp: break self.handleSells(sec, data) self.handleBuys(sec, data) self.Plot(sec, "Price", data[sec].Close) self.Plot(sec, "SMA", self.smas[sec].Current.Value) self.Plot(sec, "RSI", self.rsis[sec].Current.Value) self.Plot(sec, "RSI Buy Level", self.rsi_buy_level) def handleSells(self, sec: String, data: Slice): if self.Portfolio[sec].Invested and self.isSellSignal(sec, data): self.Liquidate(sec) currentPrice = data[sec].Close self.Plot(sec, "Sell", currentPrice) def handleBuys(self, sec: String, data: Slice): if self.Portfolio[sec].Invested: return if self.isBuySignal(sec, data): currentPositions = self.countPositions() currentCash = self.Portfolio.Cash if currentPositions == self.maxPositions: return orderVolume = currentCash / (self.maxPositions - currentPositions) currentPrice = data[sec].Close quantity = orderVolume / currentPrice self.MarketOnOpenOrder(sec, quantity) self.bought_at[sec] = self.Time self.Plot(sec, "Buy", currentPrice) def isBuySignal(self, sec: String, data: Slice): if data[sec].Close <= self.smas[sec].Current.Value: return False return self.rsis[sec].Current.Value < self.rsi_sell_level def isSellSignal(self, sec: String, data: Slice): return self.rsis[sec].Current.Value >= self.rsi_sell_level or (self.Time - self.bought_at[sec]).days >= self.sell_after_days def countPositions(self): count = 0 for sec in self.Portfolio: if sec.Value.Invested: count += 1 return count