Migrating from Quantopian to QuantConnect

Back

In this thread, we are going to cover the differences between Quantopian and QuantConnect APIs.

Basic Algorithm
In QuantConnect, all algorithms must have an Initialize method to setup your strategy. Once setup most algorithms have OnData event handlers to process market data and make trading decisions:

# Quantopian
def initialize(context):
    # Reference to AAPL
    context.aapl = sid(24)

def handle_data(context, data):
    # Position 100% of our portfolio to be long in AAPL
    order_target_percent(context.aapl, 1.00)
# QuantConnect

class MyAlgo(QCAlgorithm):
    def Initialize(self):
    # Reference to AAPL
        self.aapl = self.AddEquity("AAPL")

    def OnData(self, data):
        # Position 100% of our portfolio to be long in AAPL
        self.SetHoldings("AAPL", 1.00)

Please note that we must define a class with the QuantConnect API and it must inherit from QCAlgorithm.
self refers to the instance attributes of the algorithm class. It is used to access methods and members of QCAlgorithm like AddEquity in the example above.

Update Backtest






The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.



 
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Core Functions
An algorithm on QuantConnect has 2 core functions: Initialize and OnData. On Initialize is mandatory.

Initialize
The Initialize method is called to setup your strategy. Here you can request data, set starting cash or warm up periods. It requires self as an input, since we need to use methods from the instance to setup our strategy:

class MyAlgo(QCAlgorithm):
def Initialize(self):
self.SetCash(1000000)
self.SetStartDate(2015,2,26)
self.SetEndDate(2017,6,08)
self.AddForex("EURUSD")

OnData
Requested data is passed into event handlers for you to use to make trading decisions.
It is called one every time new data is available. If you have subscribed to minute data only, it will be called avery minute, if you have subscribed to daily data only, it will be called every day, etc...
It requires self and data. data is an object that groups all data types together at a single moment in time in the OnData(self, data) handler. Slice is short for "time slice" - representing a slice of time and values of the data at that time:

class MyAlgo(QCAlgorithm):
def OnData(self, data):
#Access data in a Slice object:
# 1. Grouped Properties: Ticks, Bars, Delistings, SymbolChangedEvents, Splits and Dividends
bars = data.Bars; # e.g. bars["IBM"].Open
delistings = data.Delistings

# 2. Dynamic String / Symbol Indexer:
bar = data["IBM"] # e.g. bar.Open - TradeBar properties OHLCV
spyTickList = data["SPY"] # Tick assets return a list of Tick objects

 

3

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Referencing Securities
In QuantConnect we can subscribe to different asset types with different resolution and different "markets". For instance, we can select forex data from FXCM or Oanda. Please checkout the docs, under Asset Classes, for more detailed information about data subscription.
While Quantopian relies on the sid method to robustly refer to a security, since tickers can change, in QuantConnect we create an ID for each symbol for the same effect. The unique security symbol is mapped to the ticker you used to subscribe them and you can use both:

class MyAlgo(QCAlgorithm):
def Initialize(self):
equity = self.AddEquity("BAC")
self.bac = equity.Symbol
print str(self.bac.ID) # prints NB R735QTJ8XC9X

def OnData(self, data):
print data[self.bac].Close == data["BAC"].Close # prints True

 

3

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Ordering Securities
Algorithms can place an order through calling the appropriate method in the API. Going long is denoted with a ordering positive number, and short a negative one. LEAN does not support hedging (long and short at the same time).
Please checkout the docs, under Trading and Orders, for detailed information and a complete information.
In this post, we will focus on SetHoldings method which is equivalent to Quantopian's order_target_percent:

# Quantopian
order_target_percent(sid(24), 0.50)
order_target_percent(sid(24), -0.50)

# QuantConnect
self.SetHoldings("AAPL", 0.50)
self.SetHoldings("AAPL", -0.50)

The quantity of shares used in SetHoldings is calculated by CalculateOrderQuantity method.

 

 

2

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks for the tips. Can you advise why am having trouble scheduling an event in Python? I get a error. (I'm on my phone, hard to add details now). 

0

Please disregard my last question. I think I found what I need on this sample Algo. 

https://github.com/QuantConnect/Lean/blob/master/Algorithm.Python/ScheduledEventsAlgorithm.py

... Link broken

2

The history() Function
In QuantConnect, Historical Data Requests are handled slightly different from Quantopian. While in Quantopian the history() function is a method from the data object that arrives in handle_data, QuantConnect's History method belongs to QCAlgorithm:

# Quantopain
# Get the 10-day trailing price history of AAPL in the form of a Series.
hist = data.history(sid(24), 'price', 10, '1d')

# Mean price over the last 10 days.
mean_price = hist.mean()

# QuantConnect
# Get the 10-day trailing bar history of AAPL in the form of list of bars
# Using the "symbol" method returns a list of tradebars.

hist = self.History("AAPL", 10, Resolution.Daily)
for bar in hist:
open = bar.Open

# Get the 10-day trailing bar history of AAPL in the form of pandas DataFrame
# Use a list of tickers to get back a pandas dataframe
hist = self.History(["AAPL"], 10, Resolution.Daily)

The following code snippets are working examples in each platform:

def initialize(context):
# AAPL, MSFT, SPY
context.security_list = [sid(24), sid(8554), sid(5061)]

def handle_data(context, data):
hist = data.history(context.security_list, 'volume', 10, '1m').mean()
print hist.mean()
class MyAlgo(QCAlgorithm):
def Initialize(self):
self.AddEquity("SPY")
self.AddEquity("BAC")
self.AddEquity("IBM")
self.security_list = ["SPY", "BAC", "IBM"]

def OnData(self, data):
hist = self.History(self.security_list, 10, Resolution.Minute)
self.Log(str(hist['volume'].mean()))

4

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Scheduling Functions
Scheduled events allow you to trigger code to run at specific times of day. This happens regardless of your data events. The schedule API requires a date and time rule to specify when the event is fired:

# Quantopian
schedule_function(func=rebalance,
date_rules=date_rules.every_day(),
time_rules=time_rules.market_open(hours=1))

# QuantConnect
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen(self.spy, 60),
Action(self.rebalance))

Unlike Quantopian, the func does not require a data object:

def rebalance(self):
self.Log("EveryDay.SPY 60 min after open: Fired at: {0}".format(self.Time))

At this point, we need to introduce another member of QCAlgorithm: Securities. This object have the information about all the subcribed securities and can be accessed anywhere in the algorithm, unlike the Slice object that arrives at OnData:

def rebalance(self):
spy = self.Securities["SPY"]
price = spy.Price
self.Log("EveryDay.SPY 60 min after open: Fired at: {0}".format(self.Time))

The following working example takes a long position in SPY at the start of the week, and closes out the position at 3:30pm on the last day of the week:

def initialize(context):
context.spy = sid(8554)

schedule_function(open_positions, date_rules.week_start(), time_rules.market_open())
schedule_function(close_positions, date_rules.week_end(), time_rules.market_close(minutes=30))

def open_positions(context, data):
order_target_percent(context.spy, 0.10)

def close_positions(context, data):
order_target_percent(context.spy, 0)
class MyAlgo(QCAlgorithm):
def Initialize(self):
AddEquity("SPY")

self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday, DayOfWeek.Monday), \
self.TimeRules.AfterMarketOpen(self.spy), \
Action(self.open_positions))

self.Schedule.On(self.DateRules.Every(DayOfWeek.Friday, DayOfWeek.Friday), \
self.TimeRules.BeforeMarketClose(self.spy, 30), \
Action(self.close_positions))

def open_positions(self):
self.SetHoldings("SPY", 0.10)

def close_positions(self):
self.Liquidate("SPY")

From complete Date and Time rules, please checkout these reference tables. Since the equivalent date rule for week start and week end are missing, we can look into implementing it.

2

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


 

Managing Your Portfolio
Another key member in the QCAlgorithm is Portfolio. While Securities keep information about the securities that have been subscribed, Portfolio provides easy access to the holding properties. In order to know whether a security has an open position, we can look for the Invested/HoldStock member of SecurityHolding (Portfolio is an enhanced dictionary wihere the keys are the symbols and the value are SecurityHolding object).
Here is a simple example on how to close all open positions:

self.Liquidate()

Yes, that is it. The Liquidate method, without any paramenter, will close all open positions.
Let now see how this is done in Quantopian and similarly in QuantConnect:

# Quantopian
for security in context.portfolio.positions:
order_target_percent(security, 0)

# QuantConnect
for security in self.Portfolio.Values:
if security.Invested:
self.Liquidate(security.Symbol)

 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Plotting Variables

We provide a powerful charting API which can be build many chart types. At its simplest it can be used with a single line of code:

self.Plot("Series Name", value)

While Quantopian only allows one chart with some series, we allow many charts with some series two, since we can create more than one chart, add series into it and, finally, add the charts in the algorithm usinf AddChart method: 

# In your initialize method:
# Note - use single quotation marks: ' instead of double "
# Chart - Master Container for the Chart:
stockPlot = Chart('Trade Plot')
# On the Trade Plotter Chart we want 3 series: trades and price:
stockPlot.AddSeries(Series('Buy', SeriesType.Scatter, 0))
stockPlot.AddSeries(Series('Sell', SeriesType.Scatter, 0))
stockPlot.AddSeries(Series('Price', SeriesType.Line, 0))
self.AddChart(stockPlot)

// Later in your OnData(self, data):
self.Plot('Trade Plot', 'Price', self.lastPrice)

Please checkout fully working backtest below.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Slippage and Commission
At the moment, it is not possible to customize slippage and commission in Python algorithm, despite the fact we can do it in C# algorithms. However, commission are modeled, by default, with the specifications from the brokerages.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thank you for all you've written here so far, Alexandre. Regarding scheduling functions/events to run, is it possible to schedule a function/event before market open? I've tried with 

self.Schedule.On(self.DateRules.EveryDay(), self.TimeRules.At(9, 0), Action(self.BeforeTradingStart))

followed with 

def BeforeTradingStart(self):
# This is where we will run daily code checks to ensure lists are synced with positions.
# additionally, will determine how many days a position has been held in Portfolio
self.Log("BTS")

my log keeps showing:

2017-02-22 09:31:00 :BTS

0

Managing Orders
In QCAlgorithm, all orders are recorded in the Transactions object. This object have several methods to select orders under any criteria:

# Cancel all open orders from SPY
cancelledOrders = self.Transactions.CancelOpenOrders("SPY")

# Cancel order #10
cancelledOrder = self.Transactions.CancelOrder(10)

# Get open orders
openOrders = self.Transactions.GetOpenOrders()

# Get open orders from SPY
openOrders = self.Transactions.GetOpenOrders("SPY")

# Get open order #10
openOrder = self.Transactions.GetOrderById(10)

# Get all orders
orders = self.Transactions.GetOrders()

# Get order ticket #10
orderTicket = self.Transactions.GetOrderTicket(10)

# Get all orders tickets
openOrderTickets = self.Transactions.GetOrderTickets()

Quantopian's API has three methods for managing existing orders: cancel_order(order), get_open_orders(sid) and get_order(order). For this thread, let's compare the methods for getting open orders in a working example:

# Quantopian
def initialize(context):
    # Relatively illiquid stock.
    context.xtl = sid(40768)

def handle_data(context, data):
    # Get all open orders.
    open_orders = get_open_orders()

    if context.xtl not in open_orders and data.can_trade(context.xtl):
        order_target_percent(context.xtl, 1.0)

# QuantConnect
class MyAlgo(QCAlgorithm):
    def Initialize(self):
        # Relatively illiquid stock.
        self.AddEquity("XTL")

    def OnData(self, data):
        # Get all open orders.
        open_orders = self.Transactions.GetOpenOrders()

        if len(open_orders) == 0 and not Portfolio.Invested:
            self.SetHoldings("XTL", 1)

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Demo Algorithm 1; Simple SMA Weekly Mean-reversion Strategy

This algorithm calculates 30-day SMA and 10-day SMA for each stock and it's rebalanced weekly. Every Monday if the 10-day SMA is higher than the 30-day SMA, I short the stock, and vice versa. 

2


Thanks Alexandre! Really appreciate the quality of your guide with parallel examples between the two IDE's

If it's possible in QC, could you cover the equivalent implementation of Quantopian's Pipeline API for filtering down a large universe of securities based on custom factors and fundamental data?

2

import numpy as np

class TestAlgo(QCAlgorithm):

def Initialize(self):
# Backetst Info
self.SetCash(25000)
self.SetStartDate(2009,1,1)
self.SetEndDate(2017,1,1)

# Initialize Assets
self.stocks = ["SPY","TLT"]

#Schedule
self.Schedule.On(self.DateRules.MonthStart(), self.TimeRules.AfterMarketOpen(0),Action(self.trade))

def trade(self):
print "Test"

So if someone could help me out. If I am understanding this right, I should get a print on logs at the start of everymonth right?

0

Jonathan Gomez - Almost. Because we are multi-asset each asset has a different start of month. So for that method you need to remember to 1) add the assets to the algorithm, and 2) specify start of month for which security. See this example algorithm attached.  

self.Schedule.On(self.DateRules.MonthStart("SPY"), self.TimeRules.AfterMarketOpen("SPY"), Action(self.RebalancingCode))

 

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks for starting this thread, very informative.

Can you give an example of an equivalent of Quantopian pipeline with fundamentals data. Like for example selecting universe of top decile stocks by daily volume that had positive earnings in last quarter?

Does Quantconnect have any limits on account sizes connected to IB?

 

 

2

Data Normalization Mode
By default, equity prices are adjusted in QuantConnect for all resolutions.
If we want Raw prices, we need to set the data normalization mode for each equity:

equity = self.AddEquity("SPY", Resolution.Minute)
equity.SetDataNormalizationMode(DataNormalizationMode.Raw)

Up next: Universe Selection (QuantConnect's equivalent to Quantopian's Pipeline)

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Dynamic Security Selection
Pipeline is the name Quantopian has choosen for the dynamic security selection feature. In QuantConnect, we call it Universe Selection. Before we show how the differences, here is how this feature is used in each platform:

# Quantopian
from quantopian.pipeline import Pipeline
from quantopian.algorithm import attach_pipeline, pipeline_output

def initialize(context):
    my_pipe = make_pipeline()
    attach_pipeline(my_pipe, 'my_pipeline')

def make_pipeline():
    return Pipeline()

def before_trading_start(context, data):
    # Store our pipeline output DataFrame in context.
    context.output = pipeline_output('my_pipeline')

# QuantConnect
from System.Collections.Generic import List
from QuantConnect.Data.UniverseSelection import *

class MyAlgorithm(QCAlgorithm):
    def Initialize(self):
        self.AddUniverse(self.CoarseSelectionFunction)

    def CoarseSelectionFunction(self, coarse):
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)

        list = List[Symbol]()
        for c in sortedByDollarVolume[:5]: list.Add(c.Symbol)
        return list

    # this event fires whenever we have changes to our universe
    def OnSecuritiesChanged(self, changes):
        self.changes = changes

In QuantConnect, the AddUniverse method is used to pass a function that selects the securities from a pre-defined universe passed as 'coarse'. The coarse object is a CoarseFundamental type, please checkout the docs for more information. Once the universe members change, the OnSecuritiesChanged event handler is triggered. We can make trading decisions and place orders in this method:

def OnSecuritiesChanged(self, changes):
    # liquidate removed securities
    for security in changes.RemovedSecurities:
        if security.Invested:
            self.Liquidate(security.Symbol)

    # we want 20% allocation in each security in our universe
    for security in changes.AddedSecurities:
        self.SetHoldings(security.Symbol, 0.2)

    # Store our changes output in self
    self.changes = changes

Pipeline relies heavily on pandas Dataframe and has a lot of build-in factors (based on indicators) that can be used to define filters and classifiers. In QuantConnect, we need to combine our indicators to select the securities.

 

3

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Dynamic Security Selection - Fundamental Data
At the moment, we can only get fundamental data for universe selection. To access it, we need to add a function as a second parameter in AddUniverse that will receive fine fundamental data from the universe that was pre-filtered by Coarse Fundamental:

# In Initialize
self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)

# sort the data by P/E ratio and take the top 'NumberOfSymbolsFine'
def FineSelectionFunction(self, fine):
# sort descending by P/E ratio
sortedByPeRatio = sorted(fine, key=lambda x: x.ValuationRatios.PERatio, reverse=True)

# take the top entries from our sorted collection
topFine = sortedByPeRatio[:self.__numberOfSymbolsFine]

list = List[Symbol]()
for x in topFine: list.Add(x.Symbol)
return list

Please checkout a fully working example below.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks for writing this Quantopian transition guide. In Quantopian's Morningstar fundamentals, you can get a company's sector with morningstar.asset_classification.morningstar_sector_code. I don't see an equivalent version in Quant Connect's Morningstar documentation. Am I missing it? Is there some other way to filter by sector?

1

Hi Tyler Bandy 

Check out the doc for Morningstar fundamental data here

I also made a simple demonstration algo based on Alexandre Catarino 's example above. 

1


Vladimir Prelovac - We don't limit account size; but we'd prefer institutional investors contact us and setup a institutional / dedicated account. 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi Yan Xiaowei,

Thanks for the response. I was already familiar with that Morningstar fundamental doc. It has the other fundamental factors I want, but the Morningstar Sector Code seems to be missing. The IndustryTemplateCode that you used in your demonstration only differentiates between normal, mining, utility, transportation, bank, and insurance. Unfortunately, I need a little more granularity. The Quantopian Morningstar Sector Code is a 3 digit code that represents different sectors. Since Quant Connect seems to have most of the same Morningstar data, I thought it would be available.

1

Thanks for the tutorials, cloning them and testing them out now.

0

Having some trouble with getting data from history. Since its bars I assume that the OHLC data can be called via ['open'] ['close']. Shouldnt this work if I wanted to get a list of close data where close[-1] gives the last bar close.

 

data = self.History(self.qqq, period, Resolution.Daily)
close = data['close']


#So that close[-1] > close[-2] = 1 bar ago close greater than 2 bars ago.

Also in history is volume included in this bar object?

Thanks

1

For example to get something like this working.

import numpy as np
import pandas as pd

class TestAlgo(QCAlgorithm):

def Initialize(self):
# Backetst Info
self.SetCash(25000)
self.SetStartDate(2009,1,1)
self.SetEndDate(2011,1,1)

# Initialize Assets
self.AddEquity('QQQ')
self.qqq = 'QQQ'

#Schedule
self.Schedule.On(self.DateRules.EveryDay("QQQ"),self.TimeRules.AfterMarketOpen("QQQ"),Action(self.trade))

def trade(self):
period = 10

data = self.History(self.qqq, period, Resolution.Daily)
close = data['close']

if (close[-1] > close[-2]):
self.SetHoldings(self.qqq,1.0)
else:
self.SetHoldings(self.qqq,0)

 

1

Thank you very much for posting this guide, Alex
1

Jonathan Gomez, if you want a pandas.DataFrame of the Historical Request, you need to use a list of simbols for the first parameter:

data = self.History([self.qqq], period, Resolution.Daily)
if data.empty:
return

I found out that History Request for Daily QQQ is returning an empty list. We will look into it.

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


We create an example to show how to use a simple indicator with universe selection.
A dictionary is created to save object that keeps the state of a exponencial moving average cross:

class SymbolData(object):
def __init__(self, symbol):
self.symbol = symbol
self.tolerance = d.Decimal(1.01)
self.fast = ExponentialMovingAverage(100)
self.slow = ExponentialMovingAverage(300)
self.is_uptrend = False
self.scale = 0

def update(self, time, value):
datapoint = IndicatorDataPoint(time, value)

if self.fast.Update(datapoint) and self.slow.Update(datapoint):
fast = self.fast.Current.Value
slow = self.slow.Current.Value
self.is_uptrend = fast > slow * self.tolerance

if self.is_uptrend:
self.scale = (fast - slow) / ((fast + slow) / 2)

We select the securities that are up trending and get those with the highest "scale":

# In the selector method: CoarseSelectionFunction
# Filter the values of the dict: we only want up-trending securities
values = filter(lambda x: x.is_uptrend, self.averages.values())

# Sorts the values of the dict: we want those with greater difference between the moving averages
values.sort(key=lambda x: x.scale, reverse=False)

 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Resolution of Universe Data:

A common misunderstanding is this line of the universe selection: 

self.UniverseSettings.Resolution = Resolution.Daily

This means the assets being added to your universe will be added at Daily resolution. It defaults to Minute resolution (i.e. universe added securities are in Minute resolution).

It is great for doing really fast backtests -- but it also means all market orders (or SetHoldings) will be converted to MarketOnOpen orders as when the daily bar arrives -- the market has already closed. 

As the orders are placed when market is closed it can also make portfolio modelling tricky as we don't know what price the market order will fill for -- so some orders may be rejected due to insufficient margin. Those orders will show up as Invalid in the console.

 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Leverage
On Quantopian, there is no limit to the amount of money that can be invested by an algorithm, regardless of its starting capital, so controlling cash and leverage is necessary.
On QuantConnect, each asset has its own pre-defined leverage (2 for Equity, 50 for Forex and CFD, etc). This value are used in margin models to check whether there is margin for an order to be filled. We can change the default values in two different ways: either using the method to subscribe to the security or the SetLeverage mthod that belong to the Security object:

 

AddEquity("SPY", Resolution.Minute, Market.USA, True, 1)

# or
spy = AddEquity("SPY")
spy.SetLeverage(1)
# or
self.Securities["SPY"].SetLeverage(1)

 

If we want to use all the leverage in SetHoldings helper method, we can verify the leverage the secutiry has and multiply it by the target percentage:

import decimal as d

spy_leverage = self.Securities["SPY"].Leverage
qqq_leverage = self.Securities["QQQ"].Leverage
self.SetHoldings("SPY", d.Decimal(0.5) * spy_leverage)
self.SetHoldings("QQQ", d.Decimal(0.5) * qqq_leverage)

 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


import numpy as np
import pandas as pd
import talib as tb

class TestAlgo(QCAlgorithm):

def Initialize(self):
# Backetst Info
self.SetCash(25000)
self.SetStartDate(2009,1,1)
self.SetEndDate(2011,1,1)

# Initialize Assets
self.AddEquity('SPY')
self.spy = ['SPY',0]
self.stocks = [self.spy]

#Schedule
self.Schedule.On(self.DateRules.EveryDay("SPY"),self.TimeRules.AfterMarketOpen("SPY"),Action(self.trade))

def trade(self):
period = 30
spy = self.spy

for i in self.stocks:
data = self.History([i[0]], period, Resolution.Daily)
i[1] = data['close']

rsi = tb.RSI(spy[1],timeperiod=14)

for i in self.stocks:
if (i[1][-1] > i[1][-2]) and (rsi[-1] > rsi[-2]):
self.SetHoldings(i[0],1.0)
else:
self.SetHoldings(i[0],0)

Just a note, I write things in loops because later on there would be more than just 1 security. If I can get it working for 1 I can get it working for all.

So in Quantopian when you used talib you would be able to source the data as the close (aka spy[1]) and then it would spit out a list of values I could reference using [-1] for last bar, [-2] for 2 bars ago ect. When I added rsi[-1] > rsi[-2] it breaks. I assume just as in price its not outputting a list?

1

Specifying Assets - Symbols

In Quantopian you specify a security id sid(#). The number is unique from the QP database.

In QuantConnect you should use the string name of the ticker, as of today/when you launch the algorithm (or use universe selection). We use that string to look up the Symbol object.

Under the surface we use Symbol objects to uniquely identify securities. These are class objects which encode all the information required to uniquely identify a symbol. This information includes: original ticker string, list date of the security, security type, contract expiry, contract strike price.

We encode it into a symbol string: e.g. YHOO R735QTJ8XC9X is actually the original list string, YHOO, with the rest of the information encoded into the hash string after it. Over the last few years that company was renamed to AABA. For more information on decoding this see the symbol class. If you specify "AABA" we automatically look up the right Symbol object for you.

Common Issue

Because of delistings, renames etc the encoded symbol isn't neccessarily the same as the ticker, People often do things like this:

Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA);

Which is OK for stocks which don't really change symbol but sometimes with complex symbols like GOOG this can cause trouble. The SPY string is the ticker string *at the listing date*. Depending on the listing date of the ticker you might select the wrong one by accident. The listetd GOOG is today called GOOGL.

 

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thanks for writing these short helpers. Regarding history requests for a particular symbol, is it possible to get the history in the form of a panda data frame or Series timeseries object? I can't seem to find a way to get the date part of the TradeBar enumerations returned by self.History(symbol, n, Resolution.Daily).

 

Thanks for your help,

Takis

1

Hi Takis,

I used np.array to convert a (pandas?) series into a (numpy?) array. I imagine you may find a similar code on google. I also wanted to post how I was able to 'resample' the minutely pricing into 30-Minute time bars for anyone interested. I'm certain there is a better way, but it works for now.

for stock in self.stock_list:
_30mprices = []
_30mrsi = []
pricesm = self.History(stock, 8000, Resolution.Minute).close
price_array = np.array(pricesm)

#until code can be resampled, iterating through numbers to pull close of last minute of 30 minute time period.
for i in range (1, 250):
_30mprices.append(price_array[(29-i*30)]) #list[-1], list[-31], list[-61], etc.
_30mprices.reverse() #To correct the order
_30ray = np.array(_30mprices)
_30mrsi = talib.RSI(_30ray, timeperiod=14)

 

1

Also Takis, Alexandre probably provided an answer earlier in this thread.

""

Alexandre Catarino

Staff  Pro , 19 hours ago, ,

Jonathan Gomez, if you want a pandas.DataFrame of the Historical Request, you need to use a list of simbols for the first parameter:


 
  1. data = self.History([self.qqq], period, Resolution.Daily)
  2. if data.empty:
  3. return

I found out that History Request for Daily QQQ is returning an empty list. We will look into it.

""

1

QuantConnect Debug Message Flooding:

Its common for people to put a debug message into the primary flow of data. As we're working with high resolution data that can result in millions of debug packets being streamed to the browser; slowing everything down and often crashing your browser tab. To prevent these self-DDOS attacks we require debug messages to be slightly different each time. An exact duplicate message will be filtered out. You can simply get around this by putting the time onto the message:

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

 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Addison/Jonathan,  Thanks for the answer -- the pandas dataframe returned when you use a list of symbols in the history request is what I was looking for.

1

Three questions, sorry for the length, I thought this was going to be shorter  when I started typing:

1. When do I need to use the warmup functionality? If I use "data = self.History([self.qqq], period, Resolution.Daily)" do I also need to use warmup? If my course and fine universe selection selects stocks based on a 30 day moving average crossover do I need to warmup?

 

2. Is there a 'best practice' to calculate stuff prior to market open? The equivalent quantopian code would be:

def before_trading_start(context, data):
#Run before trading

Which runs about 45min before trading begins for the day. 

 

3. What order do all the functions run, or is there a specific time that the algo beings executing? If I have a function scheduled to run at 10:00am and a function that is running every minute with OnData(self, data) which one will fire first? What time of day does the algorithm universe selection run?

0

The warmup feature is an improved historical data request. When we use it, most of the event handlers will be triggered with with historical data. If we just need warm up indicators, we can use History. However, SetWarmup is just one line of code. At the moment, Universe Selection doesn't work with warmup. We need to add symbols to the universe and make a History call in OnSecuritiesChanged method.

Lean/QuantConnect is data driven, so you need data before market open to trigger an event. By default, we subscribe to data that doesn't include extented market hours, but we can do it if we request it explicitly:

# In Initialize
self.AddEquity("SPY", Resolution.Minute, Market.USA, True, 2, True)
self.Schedule.On(self.DateRules.EveryDay("SPY"),
self.TimeRules.AfterMarketOpen(self.spy, -45),
Action(self.EveryDayBeforeMarketOpen))

# EveryDayBeforeMarketOpen fires at 08:45:00

For the order of events please checkout the AlgorithmManager,Run method. You will see that OnData is the last method to run. Coarse/Fine Universe selection runs at midnight UTC.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


"The warmup feature is an improved historical data request. When we use it, most of the event handlers will be triggered with with historical data. If we just need warm up indicators, we can use History. However, SetWarmup is just one line of code. At the moment, Universe Selection doesn't work with warmup. We need to add symbols to the universe and make a History call in OnSecuritiesChanged method."

Ok so this paragraph confused me. I did a little digging and found this example in the lean documentation (it's in C# but I'm assuming it will work similarly in python). I cloned it and I can see that it takes 100 days in a backtest of warming up before it places any trades.

My understanding:

I think i understand now that SetWarmup makes your algorithm "run" a specified number of days in the past, with most logic included. Which is good for things like a crossover that might happen once a month and you want to know if you already have a signal to buy without needing to wait for the next signal to occur. However, if you don't care about your algorithm's logic in the past but just need an indicator to tell you a value such as the 200 day SMA you can use history without SetWarmup. But none of that matters with Universe Selection, It can't look back into the past at all.

Are you saying that in live trading we would need to wait 100 days before any trades are placed if our universe selection uses a 100 day EMA? or is there a workaround?

Thanks for your patience,

0

Very good point LukeI - we're going to ponder on that one. You're 100% correct the existing setup won't handle it well. There are work arounds but they aren't clean. E.g. you can potentially request history in your selection function -- but you must be careful to request a small batch or you will timeout the request.  You should probably prefilter your universe by volume -- then apply the indicators (I'll try get you a tangible example shortly). 

We're going to give this some thought as it will probably need a light redesign and ultimately making Universe get triggered in warm up to avoid any manual history requests.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


import numpy as np
import pandas as pd
import talib as tb

class TestAlgo(QCAlgorithm):

def Initialize(self):
# Backetst Info
self.SetCash(25000)
self.SetStartDate(2009,1,1)
self.SetEndDate(2009,1,30)

# Initialize Assets
self.AddEquity('SPY')
self.spy = ['SPY',0]
self.stocks = [self.spy]

#Schedule
self.Schedule.On(self.DateRules.EveryDay('SPY'),self.TimeRules.BeforeMarketClose('SPY',30),Action(self.trade))

def trade(self):
period = 20
spy = self.spy

for i in self.stocks:
data = self.History([i[0]], period, Resolution.Daily)
i[1] = np.array(data['close'])

self.Log(str(self.spy[1][-1]))

So while toying around I found something interesting. It seems that price for SPY may be incorrect? According to the logs:

2009-01-02 15:30:00 :75.702615744

2009-01-05 15:30:00 :78.043155393

2009-01-06 15:30:00 :77.883763804

2009-01-07 15:30:00 :78.420661788

2009-01-08 15:30:00 :76.021398922

2009-01-09 15:30:00 :76.348571131

2009-01-12 15:30:00 :74.670764931

2009-01-13 15:30:00 :72.942624545

 

When I look at historical charts SPY is trading in the low 90s high 80s in this timeframe. Any explination?

And to ask my original question why I did this. Is there any lookahead bias in the history function? Or does it get the current bar at that exact minute.

 

Thanks

0

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Thank you for the support guys! I have to imagine this shutdown of Quantopian has kept you busy. You've all been quick to answer quesions, and provides as much assistance in porting over algorithms. It is much appreciated! 

So, I finally completed the coversion of my algorithm! I just signed up for prime so I can backtest it first!

1

I apologize for this brute force questions as there has been a great discussion and multiple examples above on universe selection, but would it be of any use/value to users and the system to have a pre-defined high quality default universes? Before switching from quantopian, my systems had a heavy focus on starting with the Q500, Q1500, or Q3000(not documented yet) universes before filtering down to a much smaller set of assets.
 

From the Q1500 docs linked above:
default universe containing approximately 1500 US equities each day.

Constituents are chosen at the start of each month by selecting the top 1500 “tradeable” stocks by 200-day average dollar volume, capped at 30% of equities allocated to any single sector.

A stock is considered “tradeable” if it meets the following criteria:

  1. The stock must be the primary share class for its company.
  2. The company issuing the stock must have known market capitalization.
  3. The stock must not be a depository receipt.
  4. The stock must not be traded over the counter (OTC).
  5. The stock must not be for a limited partnership.
  6. The stock must have a known previous-day close price.
  7. The stock must have had nonzero volume on the previous trading day.


While I see that some of the features of the Q1500 are easily repeatable here, I wonder about the more nuanced 'tradable' filters that make the assets appropriate for live trading with a higher degree of confidence. This makes using such universes nice as many bugs may be avoided due to the clean data. I would absolutely love to see a single line QC500, QC1500, QC3000 or other high quality universes cached in the system for quick backtesting/live trading.

3

Thank you AMDQuant !

Derek Tishler -- great idea and I like those filters. We already have a simple version of that in C# but hadn't brought it up yet as it has a bug in the cloud version of python. It looks like this:

// C#
AddUniverse(Universe.DollarVoume.Top(500));
//Python:
self.AddUniverse(self.Universe.DollarVolume.Top(500));

This helper section could be expanded to include a QC500, 1500 with the extended filters. I've asked a team member to take a look into the python helper universe issue and will post back when its resolved.

1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


That is another difference -- for QC history requests today's bar (or bars in general) won't be included in the history until the bar end time has passed. To have a partial bar for a current time step you would need to create a running tradebar for the day. This can be done with a Consolidator

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Jared

If today's last price isn't included in history, then how do you merge today's data with history to get an up-to-date moving average? If I was building a real time RSI-2 indicator, I would need to merge 1 day of history which would be yesterday's closing price, and the current price of the stock into a dataframe correct?

Which actually leads me to another question.

num = 17*390 #There are 390 minutes in a trading day, so this is 17 days worth of minute level data

sma = self.SMA("SPY", num, Resolution.Minute)
Would that sma be 17 days worth of minute data only during trading hours(like Quantopian)? To word it another way, does history cull out the minutes that there is no data or do I need to specify 17*24*60 and remove null data from the data frame?
0

@Lukel 

 - You would need to merge the current day/minute/hour's bar to create the final one for your indicator if you want it dynamically updated intra-bar. It sounds like work.. the easiest way would probably be to create a rolling window and re-create the indicator each time.
 - Currect in QC anytime there's a bar count its refering to the market open bars so that code should be transportable.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


In QC, is there an equivalent of Quantopian's data.can_trade before placing an order? Or is it not necessary in QC?

5

Hi guys, 

Thank you for helping us to switch from Qantopian to QC.

How can I follow the leverage ? On Q I was using:

record(Leverage = context.account.leverage)
0

If anyone is having trouble porting their code over from Quantopian, one thing that I discovered was causing a lot of errors was the whitespace. Quantopian didn't have a problem using 4 spaces as equivalent to tab, and mixing both methods but when you copy that code over QC has trouble reading it.

My solution was to go into a text editor like notepad++, enable "view tabs and whitespaces" and then change all space indents to tabs. That fixed a lot of problems that were hard to pin down. Also on QC the indents matter on blank lines, if you have a function with a blank line in it QC ends that function at the blank line. You need to indent your blank lines to the correct level so that QC will continue recognizing the rest of the function. These errors don't always get picked up in the text editor, you only see the real effect during the backtest with a mysterious error.

2

Thank you for mentioning it LukeI - if possible please send examples (support@quantconnect.com) as we're trying to create a code solution to the "white space issue" :) 

Chris D - We limit leverage for you like a real broker would do. To make it close to Quantopian's behavior you could set the leverage very high so you can trade without limits. Leverage for each security is set when you add the asset. 

Internally this is modelled as margin used. Each holding on leverage takes a cash position/margin to hold. At the time of purchase this is called "Initial Margin". To hold a position you need a "Maintenance Margin" fraction which is often lower than the initial margin. Margin is a good way of modelling multiple security types in a single portfolio as some assets have a fixed margin-requirement per contract (vs leverage which is variable on portfolio value).

Instead of following "total leverage" which only applies to a Equities-only portfolio of fixed leverage per asset; you should probably track TotalMarginUsed --> Portfolio.TotalMarginUsed. Perhaps one of the community or team will have a better idea here of what could be equivalent.

2

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Lukel, you could also use Ctrl+H and use the Replace All to replace all 4 consecutive spaces with a tab. This is what I do each time. Find/Replace is actually a very helpful functionality that I don't believe was available in the Quantopian IDE

1

Do you or any members here offer any algo coding service? Tutorials are a great effort but finding time to learn this all over again is problematic. I'd pay to have my algo ported.

ps. What if QC offered free algo rewrite for Quantopian members with a 1yr subscription to QC?

0

@Jared Broad - Thank you for your response. I will try to adapt this method.

0

Hi,

I'm also a migrant from Quantopian. I guess this forum is the one we migrants need. Please help us. I will learn from you guys and hopefully rebuild my algos here. :)

0

Thank you Vladimir its an interesting idea and appreciate the sentiment. We'll keep it in mind. Ideally we'd like to highlight the community members who can help with this.

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Hi,

def OnData(self, slice):

history = self.History(self.security_list, 40, Resolution.Daily)
history_mean = history['close'].mean()
self.log(str(history_mean))

I tried the above and got 'Build Request Successful'. But failed to do the backtest. What went wrong? I just wanted to see logs of 'mean' of the securities for the past 40 days. Help me! Thanks.  

0

Hi,

self.Schedule.On(self.DateRules.EveryDay(self.security_list),
self.TimeRules.AfterMarketOpen(self.security_list, 60),
Action(self.OnData))

1). Can we do this? 'Action(self.OnData))' ?

2). Do we need to put all the trading orders under the 'OnData(self, data)'? or can we do so under anywhere we want (e.g. def rebalance(self), ...)?

Thanks.

0

HanByul P, could you please open a new thread with your question and share the algorithm instead of code snippets?
Answering the last two questions:
1. No. System.Action encapsulates a method that has no parameters and does not return a value. OnData has one parameter.
2. Also no. You can place orders in method of the algorithm. In OnData is "special" because it is a entry point of new data and the Slice object was designed to deliver a snapshot of the market at a given time. However, the Security object also has pricing data, so if we need the price for placing an order, we can use it:

# In OnData(self, slice)
price = slice["SPY"].Close

# In any method
price = self.Securities["SPY"].Price
0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@Alexandre Catarino, Thanks a lot.

I will have many more questions: In Quantopian, we did this as below.

# Quantopian

# For checking our leverage and counting longs/shorts
def my_record_vars(context, data):

longs = shorts = 0
for position in context.portfolio.positions.itervalues():
if position.amount > 0:
longs += 1
if position.amount < 0:
shorts += 1

record(leverage=context.account.leverage, \
Long_Count=longs, Short_Count=shorts)
In Quantopian, the 'record' function plots what we want to see as above in the backtest screen. In the QC's backtest, I see a plot of 'Daily Performance' below the equity performance chart. Just like a 'Daily Performance', I want to see leverage and counting of all the numbers of longs and shorts in the backtest screen..Can we do this in QC? Thanks.
0

We have addressed Charting in QuantConnect in this thread. Here is the comment with a working example:

https://www.quantconnect.com/forum/discussion/2317/migrating-from-quantopian-to-quantconnect/p1/comment-7000

The account leverage for Equity can be calculated by the ratio between Portfolio.TotalAbsoluteHoldingsCost and Portfolio.TotalPortfolioValue:

account_leverage = self.Portfolio.TotalAbsoluteHoldingsCost / self.Portfolio.TotalPortfolioValue
1

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


@HanByul P, (and others)

I spent MANY hours struggling with this until I figured out the trick: QC's historical data is given in a multiindex dataframe like this:

                    open    high    low    close   volume
spy 2017-1-1 00:00  101.00  105.00  99.00  100.00  123456
    2017-1-2 00:00  101.00  105.00  99.00  100.00  123456
    2017-1-3 00:00  101.00  105.00  99.00  100.00  123456
qqq 2017-1-1 00:00  201.00  205.00  199.00 200.00  123456
    2017-1-2 00:00  201.00  205.00  199.00 200.00  123456
    2017-1-3 00:00  201.00  205.00  199.00 200.00  123456

 

So when you use history["close"].mean() it gives you the mean of all the close prices of all the stocks averaged together. In my example it would give you a value of 150.00 which is useless to us. In order to get the data into quantopian format (for use with the quantopian code) You need to pick an OHLCV value then unstack the multiindex dataframe so that each stock becomes it's own column like this:

History = self.History(stocks, 20, Resolution.Daily)["close"].unstack(level=0)

                spy     qqq
2017-1-1 00:00  100.00  200.00
2017-1-2 00:00  100.00  200.00
2017-1-3 00:00  100.00  200.00

So now you can use .mean() which would give you values of SPY = 100.00 and QQQ = 200.00

I'm sure there's a better way to do it in a pure QC way but .unstack(level=0) pretty much gives you plug and play with quantopian code.

2

Great suggestion LukeI!

To keep this thread focused on specific migration tips I'll close it for now. If anyone has a migration tip contact us and we'll re-open to add your suggestion/addition so others reading the thread can get the most condensed information possible. 

0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Update Backtest





0

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.


Loading...

This discussion is closed