| 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)
# 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