Overall Statistics |
Total Trades 5 Average Win 38.32% Average Loss 0% Compounding Annual Return 11.508% Drawdown 17.300% Expectancy 0 Net Profit 192.786% Sharpe Ratio 1.1 Loss Rate 0% Win Rate 100% Profit-Loss Ratio 0 Alpha -0.112 Beta 11.347 Annual Standard Deviation 0.104 Annual Variance 0.011 Information Ratio 0.908 Tracking Error 0.104 Treynor Ratio 0.01 Total Fees $25.00 |
import decimal class BasicTemplateAlgorithm(QCAlgorithm): '''In this example we look at the canonical 15/30 day moving average cross. This algorithm will go long when the 15 crosses above the 30 and will liquidate when the 15 crosses back below the 30.''' # Initialize the global parameter at first def __init__(self): self.symbol = "AAPL" self.previous = None self.fast = None self.slow = None def Initialize(self): '''Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.''' #This part comes from the basic Template with Set the Start and End Date as the function name self.SetStartDate(2009, 1, 1) self.SetEndDate(2018, 11, 9) self.SetCash(100000) self.SetBenchmark(self.symbol) # Find more symbols here: http://quantconnect.com/data self.AddSecurity(SecurityType.Equity, self.symbol, Resolution.Minute) # In order to do the simple moving average strategy, we need to get the moving average for 50 days and 200 days rolling window # In the community I find QuantConnect has SMA as the function for getting simple moving average, # therefore it's easier for calculating the moving average than a regular python environment self.fast = self.SMA(self.symbol, 50, Resolution.Daily); self.slow = self.SMA(self.symbol, 200, Resolution.Daily); def OnData(self, data): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. Arguments: data: TradeBars IDictionary object with your stock data ''' # We need to wait for the 200 moving average to be calculated out since it needs more steps of date to formulate the 200 moving average if not self.slow.IsReady: return # This part is the result coming from debugging. I find that the running time is so long for backtesting without this part and # from community some algorithm suuggests there may exist a situation that the trade executes multiple times at same day # Therefore I added this part for ensure there is only one trade at same day if self.previous is not None and self.previous.date == self.Time.date: return # Convenient for following part, we get the postion as the current position of our portfolio with reference in documentation suggesting the # attribute "Quantity" gives us the position quantity. position = self.Portfolio[self.symbol].Quantity # This is the core part of the strategy # At first we only need to long the AAPL stock when our position is neutral. The reason for the position < 0 part is that I also implement a long-short strategy # The decimal.Decimal(1.00015) part is the usual tolerance part for moving average strategy with purpose of preventing too frequent position change with a high transaction costs # The execution part is simple from the reference of documentation that buy 1000 shares by a market order, which can be executed immediately with function "MarketOrder()" as instructed if position <= 0 and self.fast.Current.Value > self.slow.Current.Value*decimal.Decimal(1.00015): self.MarketOrder(self.symbol, 1000) #self.SetHoldings(self.symbol, 1.0) # The short or liquidate position is similar to the long position and the Liquidate function is refered in the documentation # As mentioned before, I also implment a long short strategy both for the whole portfolio or 1000 shares if position > 0 and self.fast.Current.Value < self.slow.Current.Value: #self.SetHoldings(self.symbol,-1.0) self.Liquidate(self.symbol) # As mentioned before, I need to check if there is only one trade at the same day, I need store today's date with variable "previous" after all the procedures self.previous = self.Time