QuantConnect Logo

Welcome to The QuantConnect Research Page¶

Refer to this page for documentation https://www.quantconnect.com/docs#Introduction-to-Jupyter¶

Contribute to this template file https://github.com/QuantConnect/Lean/blob/master/Jupyter/BasicQuantBookTemplate.ipynb¶

QuantBook Basics¶

Start QuantBook¶

  • Add the references and imports
  • Create a QuantBook instance
In [ ]:
%matplotlib inline
# Imports
from clr import AddReference
AddReference("System")
AddReference("QuantConnect.Common")
AddReference("QuantConnect.Jupyter")
AddReference("QuantConnect.Indicators")
from System import *
from QuantConnect import *
from QuantConnect.Data.Custom import *
from QuantConnect.Data.Market import TradeBar, QuoteBar
from QuantConnect.Jupyter import *
from QuantConnect.Indicators import *

import time
from multiprocessing import Pool
import datetime as dt
from functools import partial
import pandas as pd
import numpy as np


# Create an instance
qb = QuantBook()

# Select asset data
spy = qb.AddEquity("SPY")
In [ ]:
class SymbolBox:


    def __init__(self, symbol, secFrame, minFrame, hrFrame):

        self.symbol = symbol

        self.inds = {'EMA':{'fast':EMA(symbol, 20),
                             'slow':EMA(symbol, 100),
                             'ema':inds['EMA']['fast'] - (
                                 inds['EMA']['slow'] * self.params['tolerance'])},
                                  
                                  'ATR':{'AATR':ATR(symbol, period = 20, type = Alma),
                                         'EATR':ATR(symbol, period = 20, type = Exponential),
                                         'atr':(inds['ATR']['AATR'] + inds['ATR']['EART']) /2},

                                  'AROON':AROON(symbol, 50),
                                  'ADOSC':ADOSC(symbol, 100, 200)}


        self.Strats = pd.DataFrame({'s':EmaAdoscCross(symbol), #input strategy class for second 
                                    'm':EmaAdoscCross(symbol), #input strategy class for minute
                                    'h':EmaAdoscCross(symbol)}) #input strategy class for hour

        self.params = pd.DataFrame({'is_up':False,'is_down':False,
                                    ' trade':False,'strength':0,
                                    'tolerance': 1.01})

        self.data =  pd.DataFrame({})




##########################################################################################


    def OnData(self):
        pass


    def update(self, slice):

        self.data['open'].append(slice['open'][0])
        self.data['close'].append(slice['close'][len(slice['close'])-1])
        self.data['closeTime'].append(slice['closeTime'][len(slice['closeTime'])-1])

        slice.sort_values(by='high', ascending=False)
        data['high'].append(slice['high'][0])

        slice.sort_values(by='low')
        self.data['low'].append(slice['low'][0])

        self.data['volume'].append(slice['volume'].sum)
        self.data.sort_index(inplace=True, ascending=False)

        self.wData




    def wData(self):
        '''
        input data to indicators and logic to take on them
        '''
        self.inds['EMA']['fast'].Update(self.symbol, self.data.index[0], value)
        self.inds['EMA']['slow'].Update(self.symbol, self.data.index[0], value)
        self.inds['EMA']['alma'] = self.inds['EMA']['fast'] - (
            self.inds['EMA']['slow'] * self.params['tolerance'])
        #currently trying to figure out the best way to update the indicators

        self.inds['ATR']['AATR'].Update(self.symbol, self.data.index[0], value)
        self.inds['ATR']['EATR'].Update(self.symbol, self.data.index[0], value)
        self.inds['ATR']['atr'] = (self.inds['ATR']['AATR'] + 
                                   self.inds['ATR']['EART']) /2
        #currently trying to figure out the best way to update the indicators

        self.inds['Aroon'].Update(self.symbol, self.data.index[0], value)
        self.inds['ADOSC'].Update(self.symbol, self.data.index[0], value)

        self.updateStrength

        
        if self.params['trade']:
            
            if self.params['is_up'] and self.params['is_down']:
                self.params['trade'] = False


    def updateStrength(self):
        self.params['strength'] = 0
        self.params['is_down'] = False
        self.params['is_up'] = False
        self.params['trade'] = False
        
        self.wEma
        self.wAroon
        self.wAdosc

        if self.strength > 2:
            self.params['is_up'] = True
            self.params['trade'] = True

        elif self.params['strength'] < -2:
            self.params['is_down'] = True
            self.params['trade'] = True



    def wEma(self):
        pass
    #check data for indicator to see if params are met

    def wAroon(self):
        pass
    #check data for indicator to see if params are met

    def wAdosc(self):
        pass
    #check data for indicator to see if params are met

    def Liquidate(self, frame):
        
        for s in self.Strats:
            strat = self.Strats[s]
            if self.Portfolio[self.symbol].Invested:
                strat.Liquidate(i = 0, frame = frame)
                strat.trades = pd.DataFrame([])
                    
In [1]:
class Universe:
    
    def __init__(self):

        self.allTicks = pd.DataFrame({'eurusd': object, 'usdjpy':object,'gbpusd':object,
                                      'audusd':object ,'usdcad':object,'usdchf':object})

        self.ticksToUse = {'up': pd.DataFrame({}),
                             'down': pd.DataFrame({})}

        self.SymbolsToUse = []
        self.strength = pd.DataFrame({})


        self.symbols = ['eurusd','usdjpy','gbpusd','audusd','usdcad','usdchf']


        self.status = pd.DataFrame({'PnL':self.Portfolio.Invested.TotalUnrealizedProfit,
                                    'bankRole':self.Portfolio.Invested.TotalHoldingsValue})        

        


    def buildTicks(self, i):

        self.allTicks[i] = SymbolBox(i)
        

    def buildStrength(self, i):


        t = self.allTicks[i]

        t.updateStrength()
        strength[t.symbol] = t.params['strength']


    def pauseTrades(self, i):

        t = self.allTicks[i]
        t.params['trade'] = False
        t.Liquidate()
            


    def fineSelection(self, t):


        if strength[t] > 2:
            self.ticksToUse['up'][t] = self.allTicks[t]

        elif strength[t] < -2:
            self.ticksToUse['down'][t] = self.allTicks[t]

        else:
            if t in self.ticksToUse['up']:
                fineExit(self, frame= 'up', t =t)

            if t in self.ticksToUse['down']:
                fineExit(self, frame= 'down', t =t)

        self.SymbolsToUse = (self.ticksToUse.keys())
        


    def fineExit(self, frame, t):
        #exit postitions and cancel open orders
        pass
    


    def CoarseSelection(self, i):


        if self.allTicks[i].params['trade']:
                
            fineSelection(i)
                
        elif i in self.ticksToUse['up'] or i in self.ticksToUse['down']:

            if self.Portfolio[i].Invested and i in self.ticksToUse['up']:
                self.ticksToUse['up'][i].Liquidate()
                Transactions.CancelOpenOrders(i)

            if self.Portfolio[i].Invested and i in self.SymbolsToUse['down']:
                self.ticksToUse['down'][i].Liquidate()
                Transactions.CancelOpenOrders(i)
                
            self.ticksToUse.drop(i)
            self.SymbolsToUse = (self.SymbolsToUse.keys())
In [ ]:
 
In [ ]:
class Algo(QCAlgorithm):


    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.pool = Pool(processes=9)

        self.SetStartDate(2006,5, 2)  #Set Start Date
        self.SetEndDate(datetime.now() - timedelta(1))    #Set End Date
        self.SetCash(500000)           #Set Strategy Cash
        self.SetBrokerageModel(BrokerageName.OandaBrokerage)        
        #add margin model

        self.ticks = []
        self.tradeStopTime = 0
        self.secFrame = 30
        self.minFrame = 15
        self.hrFrame = 1
        self.minute = (60 / secframe) * self.minframe
        self.hour = ((60 / secframe) * 60) * hrframe
        self.day = ((60 / self.secframe) * 60) * 24



        # Find more symbols here: http://quantconnect.com/data

        self.univDict = Universe()

        for i in range(len(self.univDict.symbols)):
            symbol = self.univDict.symbols[i]
            self.ticks.append(self.AddForex(symbol, Resolution.Second, Market.Oanda))


            SecondConsolidator = TickQuoteBarConsolidator(timedelta(seconds=self.secframe))
            SecondConsolidator.DataConsolidated += self.SecondBarHandler
            self.SubscriptionManager.AddConsolidator(symbol, SecondConsolidator)


        par = partial(self.univDict.buildTicks)

        self.pool.map(par, self.univDict.symbols)

        self.SetWarmUp(timedelta(30))
        self.warming
        self.univDict.benchmark = self.SetBenchmark("SPY")
        self.checkUniv

    def SecondBarHandler(self, sender, bar):
        '''Each time the consolidator produces a new bar, this function will be called automatically. 
        The sender parameter will be the instance of the IDataConsolidator that invoked the event '''

        '''
        get bar schema
        '''
        symb = self.univDict.allTicks[bar.symbol]
        symb.Strats['s'].update(bar)#update 's'  data pd.DF

        #check difference between t and s date
        t = dt.datetime(symb.Strats['m'].data.index[0]) # 'm', 'h', day time
        s = dt.datetime(symb.Strats['s'].data.index[0]) #'s' time

        if (s-t).total_seconds() >= self.min:
            symb.Strats['m'].update(symb.Strats['s'].data.iloc[s:t]) #update 'm'  data pd.DF with 's' 
        else:
            checktrades(frame='m', symb = symb)

        t = symb.Strats['h'].data.index[0]

        if (s-t).total_seconds() >= self.hr:
            symb.Strats['h'].update(symb.Strats['s'].data.iloc[s:t]) #update 'm'  data pd.DF with 's' 

        else:
            checktrades(frame='h', symb = symb)

        t = symb.data.index[0]

        if (s-t).total_seconds() >= self.day:
            symb.update(self.Strats['s'].data.iloc[s:t])
            OnEndOfDay(s)
            

        self.Debug(str(self.Time) + " " + str(bar))


    def checktrades(frame, symb):
        if len(symb.Strats[frame].trades['long']) > 0:
            symb.Strats[frame].checkTrades()
        if len(symb.Strats[frame].trades['short']) > 0:
            symb.Strats[frame].checkTrades(frame = 'short')

    def checkUniv(self):


        par = partial(self.univDict.buildStrength)
        self.pool.map(par, self.univDict.tickList)
        self.univDict.strength.sort_values(axis = 1)
        
        #update inds in coarseSelection
        par = partial(self.univDict.CoarseSelection)
        self.pool.map(par, self.univDict.tickList)
 

    def OnEndOfDay(self, s):
        tst = self.tradeStopTime
        
        if self.univDict.status['PnL'] < 0 and (
            self.univDict.status['PnL'] * -1 >= self.univDict.status['bankRole'] * .17 
            and (
            tst == 0 or 
                    (s - tst).total_seconds() >= self.day)):

            par = partial(self.univDict.pauseTrades)
            self.pool.map(par, self.univDict.tickList)

            self.univDict.SymbolsToUse = {'up': pd.DataFrame({}),
                             'down': pd.DataFrame({})}
            self.tradeStopTime = s
        elif (tst == 0 or 
              (s - tst).total_seconds() >= self.day):
                    
            self.checkUniv

       

    def warming(self):

        while(self.IsWarmingUp):
            
            time.sleep(1)