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 modules required
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")

from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Python import PythonData

from datetime import date, timedelta, datetime
import decimal
import numpy as np

# Useful references:
# https://www.quantconnect.com/lean/documentation/topic16.html
#   -> bad link for "Hard Method" Static Sourcing
# https://www.quantconnect.com/docs/algorithm-reference/importing-custom-data


class BasicTemplateAlgorithm(QCAlgorithm):   
    def Initialize(self):
        '''Initialize algorithm.'''
        
    # Set backtest details
        self.SetStartDate(2018,9,1)
        self.SetEndDate(2018,9,8)
        self.SetCash(100000)
        #self.SetBenchmark("SPY")
        
        self.UniverseSettings.Resolution = Resolution.Minute
        
        # German XETRA (IBIS) exchange / Berlin time (9:00-17:30)
        # https://www.interactivebrokers.com/en/index.php?f=2222&exch=ibis
        self.SetTimeZone(TimeZones.Berlin)
        
    # Define Brokerage model and account type
        self.SetBrokerageModel(
            BrokerageName.InteractiveBrokersBrokerage,
            AccountType.Margin)

    # Define stocks for system
        self.assets = ["1COV"] # I'll eventually add more here...
    
    # System User Inputs
        self.trading_time_start = '09:02'
        #self.exchange_open_time = '09:00' # for reference (Berlin tz)
        self.trading_time_stop = '17:20'
        self.exchange_close_time = '17:30' #  Berlin tz
    
    # Add equities to algorithm
        equities = {}
        equity_data = {}
        for asset in self.assets:
            equities[asset] = self.AddEquity(asset, Resolution.Minute)
            #market=Market.Germany # does this even matter for custom data?
            #market default seems to be Market.USA
                
            equity_data[asset] = self.AddData(MyCustomData, asset)
            equities[asset].MarginModel = PatternDayTradingMarginModel()
          
        # Just adding this so the algo will run
        self.spy = "SPY"
        self.AddEquity(self.spy, Resolution.Minute)

    # Create variable(s) used for algorithm
        self.entries = False
        
    # Schedule functions
        # Check for entry signals at self.trading_time_start
        start_split = self.trading_time_start.split(':')
        start_hrs = int(start_split[0])
        start_minutes = int(start_split[1])
        self.Log('call MyEntries at {}:{}'.format(start_hrs, start_minutes))
            
        self.Schedule.On(
            self.DateRules.EveryDay(),
            self.TimeRules.At(start_hrs, start_minutes),
            Action(self.MyEntries)
            )
            
        # Schedule closing all positions at self.trading_time_stop
        stop_split = self.trading_time_stop.split(':')
        stop_hrs = int(stop_split[0])
        stop_minutes = int(stop_split[1])
        self.Log('call CloseAllPositions at {}:{}'.format(stop_hrs, stop_minutes))
            
        self.Schedule.On(
            self.DateRules.EveryDay(),
            self.TimeRules.At(stop_hrs, stop_minutes),
            Action(self.CloseAllPositions)
            )        
        
        # Schedule end of day function
        close_split = self.exchange_close_time.split(':')
        close_hrs = int(close_split[0])
        close_minutes = int(close_split[1])
        self.Log('call OnEndOfDay at {}:{}'.format(close_hrs, close_minutes))
            
        self.Schedule.On(
            self.DateRules.EveryDay(),
            self.TimeRules.At(close_hrs, close_minutes),
            Action(self.OnEndOfDay)
            )
      
      
    def MyEntries(self):
        '''Enter positions for the day.'''
        self.Log('MyEntries() called')

        try:
            for asset in self.assets:
                # Get latest closing price
                #self.Log('{} close: {}'.format(asset, self.close[asset]))
                
                # Place market entry order
                self.MarketOrder(asset, 100)
        except:
            pass

        # Update self.entries variable
        self.entries = True


    def CancelOpenOrders(self):
        '''Cancel all open orders.'''
        open_orders = self.Transactions.GetOpenOrders()
        if open_orders:
            for order in open_orders:
                self.Log('Cancelling order: {}'.format(order))
                self.Transactions.CancelOrder(order.Id)
            
                
    def CancelSymbolOpenOrders(self, symbol):
        '''Cancel all open orders for a given symbol.'''
        open_orders = self.Transactions.GetOpenOrders(symbol)
        if open_orders:
            for order in open_orders:
                self.Log('Cancelling order: {}'.format(order))
                self.Transactions.CancelOrder(order.Id)
                
                
    def CloseAllPositions(self):
        '''Close all positions.'''
        # Cancel open orders
        self.CancelOpenOrders()

        # Close all equity positions
        self.Log('Closing all positions for the end of the trading day')
        for asset in self.assets:
            shares = self.Portfolio[asset].Quantity
            if shares != 0:
                self.MarketOrder(asset, -shares)
                self.Log(' Close position for {} shares of {}'.format(
                    shares, asset))
                

    def OnData(self, slice):
        '''Each new data point will be pumped in here.'''
        # Skip once positions are entered for the day
        if self.entries:
            return
        
        # Get the latest prices?
        self.close = {}
        for asset in self.assets:
            if slice.ContainsKey(asset):
                self.close[asset] = data[asset].Close
                self.Debug("Time: {}, {} close: {}".format(
                    datetime.now(), asset, self.close[asset]))
                
                
    def OnEndOfDay(self):
        '''Called at the end of every day.'''
        # Reset variable
        self.entries = False

        
    def OnOrderEvent(self, orderEvent):
        # Skip if not filled
        if orderEvent.Status != OrderStatus.Filled:
            return
        
        # Get order info
        order = self.Transactions.GetOrderById(orderEvent.OrderId)
        
        # Check for filled entry order
        current_qty = self.Portfolio[order.Symbol].Quantity
        order_qty = order.Quantity
        if current_qty == order_qty:
            self.Log('Filled entry order: {}'.format(order))
        elif current_qty == 0:
            # Cancel other open exit order for symbol
            self.Log('Filled exit order: {}'.format(order))
            self.CancelSymbolOpenOrders(order.Symbol)

        # Print order details when desired
        self.Log(str(orderEvent))
           
            
class MyCustomData(PythonData):
    '''
    Custom Data Class
    REFs:
    https://www.quantconnect.com/forum/discussion/4079/python-best-practise-for-using-consolidator-on-custom-data/p1
    '''
    def GetSource(self, config, date, isLiveMode):
        
        file = "https://docs.google.com/spreadsheets/d/e/2PACX-1vReHX1zAOU8Kgylr1npfZjxw8b52vXA5EH5MpBkFqm2-eN1GVXYi7ei8T_a1xiJReDNulRerDmqpg9L/pub?output=csv"
        return SubscriptionDataSource(
            file, SubscriptionTransportMedium.RemoteFile)

    def Reader(self, config, line, date, isLiveMode):
        # If first character is not digit, pass
        if not (line.strip() and line[0].isdigit()):
            return None

        # New object
        asset = MyCustomData()
        asset.Symbol = config.Symbol
#asset.DataType = MarketDataType.TradeBar

        try:
            # Example File Format:
            # Date                      Open    High    Low     Close   Volume
            # 2017-01-02 09:02:00+01:00 64.88   64.88   64.43   64.43   8082
            
            # Date,       Open       High        Low       Close     Volume      Turnover
            # 2011-09-13  7792.9    7799.9     7722.65    7748.7    116534670    6107.78
            data = line.split(',')
            _date = datetime.strptime(data[0].split(' ')[0], "%Y-%m-%d")
            _time = data[0].split(' ')[1]
            
            #asset.Time = ?
            asset.Value = decimal.Decimal(data[4])
            asset["Open"] = float(data[1])
            asset["High"] = float(data[2])
            asset["Low"] = float(data[3])
            asset["Close"] = float(data[4])
            asset["Volume"] = float(data[5])
            
        except ValueError:
            # Do nothing
            return None

        return asset