Overall Statistics
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Securities import *
from datetime import timedelta
import decimal as d
import numpy as np
from QuantConnect.Data.Market import TradeBar
from QuantConnect.Indicators import *

## Trend Following Algorithm
## A Simple Program to show the trend and trend following syste
class TrendFollowingAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2013, 1, 1)
        self.SetEndDate(2016, 8, 18)
        self.SetCash(10000)
        
        self._tolerance = d.Decimal(1 + 0.001)
        self._mult_factor = d.Decimal(0.5 + 0.001)
        self.IsUpTrend = False
        self.IsDownTrend = False
        
        self.SetWarmUp(200)

        # Adds SPY to be used in our SMA indicators
        equity = self.AddEquity("SPY", Resolution.Hour)
        self.symbol  = equity.Symbol

        #Add SMA indicators
        self.SMA10 = self.EMA(self.symbol, 10, Resolution.Hour)
        self.SMA20 = self.EMA(self.symbol, 20, Resolution.Hour)
        self.SMA200 = self.EMA(self.symbol, 200, Resolution.Hour)
        
        #Add Stochastics
        self.oversold = 20
        self.overbought = 80
        self.midpoint = 50
        
        #initializing stochastic
        KPeriod = 14
        DPeriod = 3
        self.sto = self.STO(self.symbol,14,KPeriod,DPeriod, Resolution.Hour)
        
        #ATR
        self.atr = self.ATR(self.symbol,14,Resolution.Hour)
        
        #RSI
        self.rsi = self.RSI(self.symbol,14,Resolution.Hour)
        
        # Creates a Rolling Window indicator to keep the 4 TradeBar
        self.window = RollingWindow[TradeBar](4)    # For other security types, use QuoteBar
        
        #Consolidator
        OneHourConsolidator = TradeBarConsolidator(timedelta(minutes=60))
        
        # attach our event handler. the event handler is a function that will
        # be called each time we produce a new consolidated piece of data.
        OneHourConsolidator.DataConsolidated += self.HourBarHandler
        
        # this call adds our 60 minute consolidator to
        # the manager to receive updates from the engine
        self.SubscriptionManager.AddConsolidator(self.symbol, OneHourConsolidator)
        #self.consolidatedHour = None
        
        
    def HourBarHandler(self, sender, bar):
        '''This is our event handler for our one hour consolidated defined using the Consolidate method'''
        #self.consolidateHour = bar
        
        
    def OnData(self, slice):
        if self.IsWarmingUp:
           return
       
        ## Check for Dividends
        if slice.Dividends.ContainsKey(self.symbol):
            
            ## If SPY pays a dividend, log it and then skip the rest of OnData (if this is what you want to do,
            ## otherwise you can write the code for how you want to address a dividend payment
            self.Log(str(self.Time) + str(self.symbol) + str(' Paid a dividend: ') + str(slice.Dividends[self.symbol].Distribution))
            return
        
        if slice.Bars.ContainsKey(self.symbol) and (slice[self.symbol] is not None):
            self.window.Add(slice[self.symbol])
        
        
        
        if self.window.IsReady and (self.window[0] is not None):
            
            self.Log(str(self.Time) + str(slice[self.symbol]) + str(" ") + str(self.window[0].Open))
            #Get the Bar/Data from RollingWindowself.
            currBar = self.window[0] #Current window has an index 0
            past_1day = self.window[1] #Previoud day has index 1
            past_2day = self.window[2] 
            past_3day = self.window[3]
            
            price = currBar.Open
            self.Log(str(self.Time) + str(price) + str(" ") + str(past_1day.Close))
            
            #Buy Order / Entry
            if (not self.Portfolio.Invested) and (price > self.SMA200.Current.Value):
                    
                    #num_shares = int(self.Portfolio.Cash / price)
                    num_shares = int(self.CalculateOrderQuantity(self.symbol, 1.0))
                    self.MarketOrder(self.symbol, num_shares)
                    

            #Sell Order/Exit from Market
            if self.Portfolio.Invested and (price < self.SMA200.Current.Value):
                self.Liquidate()
        

    def OnOrderEvent(self, orderEvent):
        self.Log(str(orderEvent))