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.
Alexandre Catarino
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
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
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
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
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.
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.
AMDQuant
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).
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.
AMDQuant
Please disregard my last question. I think I found what I need on this sample Algo.
... Link broken
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
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()))
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
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.
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
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)
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
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.
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
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.
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.
AMDQuant
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
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
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)
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.
Yan Xiaowei
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.
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.
Tom Lin
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?
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.
Jonathan Gomez
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?
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 Broad
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))
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.
Vladimir Prelovac
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?
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
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)
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
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.
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
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.
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.
Tyler Bandy
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?
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.
Yan Xiaowei
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.
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 Broad
Vladimir Prelovac - We don't limit account size; but we'd prefer institutional investors contact us and setup a institutional / dedicated account.
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.
Tyler Bandy
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.
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.
Eric Novinson
Thanks for the tutorials, cloning them and testing them out now.
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.
Jonathan Gomez
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
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.
Jonathan Gomez
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)
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.
Eric Cheshier
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
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.
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
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)
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 Broad
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.
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
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)
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.
Jonathan Gomez
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?
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 Broad
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.
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.
Takis Mercouris
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
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.
AMDQuant
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)
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.
AMDQuant
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:
I found out that History Request for Daily QQQ is returning an empty list. We will look into it.
""
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 Broad
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")
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.
Takis Mercouris
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.
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.
LukeI
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?
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.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!