Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
0
Tracking Error
0
Treynor Ratio
0
Total Fees
$0.00
import numpy as np
import datetime
from scipy import stats 

### <summary>
### Basic template algorithm simply initializes the date range and cash. This is a skeleton
### framework you can use for designing an algorithm.
### </summary>
class StocksOnTheMove(QCAlgorithm):
    '''Basic template algorithm simply initializes the date range and cash'''

    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.'''
        self.SetStartDate(2012,1,1)  #Set Start Date
        self.SetEndDate(2012,2,5)    #Set End Date
        self.SetCash(100000)           #Set Strategy Cash
        # Find more symbols here: http://quantconnect.com/data
        self.atrWindow = 20
        self.lookBackWindow = self.atrWindow + 5
        self.riskFactor = 0.001
        self.momentumWindowLength = 90
        self.rankTablePercentile = .2
        self.significantPositionDifference = 0.1
        self.numberOfSymbols = 20
   
        self.atrDict = {}
        self.AddEquity('SPY', Resolution.Daily)
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.CoarseSelectionFunction)
       
      
        self.Schedule.On(self.DateRules.MonthStart("SPY"), 
                         self.TimeRules.AfterMarketOpen("SPY", 60), 
                         Action(self.Rebalance))
                         
    
    def CoarseSelectionFunction(self, coarse):
        CoarseWithFundamental = [x for x in coarse if x.HasFundamentalData]
        sortedByDollarVolume = sorted(CoarseWithFundamental, key=lambda x: x.DollarVolume, reverse=True)
        selectedSecurites = [x.Symbol for x in sortedByDollarVolume[:self.numberOfSymbols]]
        return selectedSecurites
                
    def slope(self,ts):
        x = np.arange(len(ts))
        slope, intercept, rValue, pValue, std_err = stats.linregress(x, ts)
        annualizedSlope = (1 + slope)**250
        return annualizedSlope * (rValue ** 2)    
        
    def Rebalance(self):
        numberOfSecurities = len(self.Securities.Keys)
        self.Debug("Number of securities in universe: "+str(numberOfSecurities))
        if numberOfSecurities <= 1: return
        history = self.History(self.Securities.Keys,  self.lookBackWindow, Resolution.Daily)
        for symbol in history.index.get_level_values(0):
            self.atrDict[symbol]=self.ATR(symbol,self.atrWindow)
       
        closes = history["close"].unstack(level=0)
        #Calculate slopes for each asset
        slopes = np.log(closes.tail(self.momentumWindowLength)).apply(self.slope)
        rankingTable = slopes[slopes > slopes.quantile(1 - self.rankTablePercentile)].sort_values(ascending=False)
        self.Debug("Top 5 in ranking table: ")
        self.Debug(rankingTable.head())
        estimatedCashBalance = float(self.Portfolio.Cash)
        # close positions that are no longer in the top of the ranking table
        positions =  self.Portfolio.Values
        for security in positions:
            if security not in rankingTable.index:
                self.Liquidate(security.Symbol)
            else:
                positionSize = positions[security].Amount
                newPositionSize = self.GetPositionSize(security)
                if position_size<= 0:
                    break
                if self.SignificantChangeInPositionSize(newPositionSize, positionSize):
                    estimatedCost = price * (newPositionSize - positionSize)
                    self.MarketOrder(security, newPositionSize, self.Securities[security].Price)
                    estimatedCashBalance -= estimatedCost
        #Open new positions based on ranking_table
        for security in rankingTable.index:
            if security not in positions:
                newPositionSize = self.GetPositionSize(security)
                if newPositionSize <= 0:
                    continue
                estimated_cost = float(self.Securities[security].Price) * newPositionSize
                if estimatedCashBalance > estimatedCost:
                    self.MarketOrder(security, newPositionSize)
                    estimatedCashBalance -= estimatedCost
        
    def GetPositionSize(self,symbol):
        averageTrueRange = self.atrDict[symbol].Current.Value
        self.Debug("Average true range: "+str(averageTrueRange))
        positionSize = 0
        if averageTrueRange > 0:
            positionSize = float(self.Portfolio.TotalPortfolioValue)  * self.riskFactor / float(averageTrueRange)
        return positionSize
        
    def SignificantChangeInPositionSize(context, newPositionSize, oldPositionSize):
        return np.abs((newPositionSize - oldPositionSize)  / oldPositionSize) > self.significantPositionDifference